source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-files.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


  • Property svn:keywords set to Id
File size: 34.5 KB
Line 
1/* file manipulation
2 $Id: libmondo-files.c 2508 2010-01-04 18:21:55Z bruno $
3*/
4
5/**
6 * @file
7 * Functions to manipulate files.
8 */
9
10
11#include "my-stuff.h"
12#include "mr_mem.h"
13#include "mondostructures.h"
14#include "libmondo-files.h"
15
16#include "lib-common-externs.h"
17
18#include "libmondo-tools-EXT.h"
19#include "libmondo-gui-EXT.h"
20#include "libmondo-devices-EXT.h"
21#include "libmondo-fork-EXT.h"
22#include "libmondo-string-EXT.h"
23
24/*@unused@*/
25//static char cvsid[] = "$Id: libmondo-files.c 2508 2010-01-04 18:21:55Z bruno $";
26
27extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN];
28
29extern int g_currentY;
30extern char *g_mondo_home;
31
32/* Reference to global bkpinfo */
33extern struct s_bkpinfo *bkpinfo;
34
35/**
36 * @addtogroup fileGroup
37 * @{
38 */
39/**
40 * Get an md5 checksum of the specified file.
41 * @param filename The file to checksum.
42 * @return The 32-character ASCII representation of the 128-bit checksum.
43 * @note The returned string points to static storage that will be overwritten with each call.
44 */
45char *calc_checksum_of_file(char *filename)
46{
47 /*@ buffers ***************************************************** */
48 char *output = NULL;
49 char *command = NULL;
50
51 /*@ pointers **************************************************** */
52 char *p = NULL;
53 FILE *fin;
54
55 /*@************************************************************** */
56
57 assert_string_is_neither_NULL_nor_zerolength(filename);
58 if (does_file_exist(filename)) {
59 mr_asprintf(command, "md5sum \"%s\"", filename);
60 fin = popen(command, "r");
61 if (fin) {
62 mr_getline(output, fin);
63 p = strchr(output, ' ');
64 if (p != NULL) {
65 *p = '\0';
66 } else {
67 mr_free(output);
68 mr_asprintf(output, "");
69 }
70 paranoid_pclose(fin);
71 }
72 mr_free(command);
73 } else {
74 log_it("File '%s' not found; cannot calc checksum", filename);
75 mr_asprintf(output, "");
76 }
77 return (output);
78}
79
80
81/**
82 * Get a not-quite-unique representation of some of the file's @c stat properties.
83 * The returned string has the form <tt>size-mtime-ctime</tt>.
84 * @param curr_fname The file to generate the "checksum" for.
85 * @return The "checksum".
86 * @note The returned string points to static storage that will be overwritten with each call.
87 */
88char *calc_file_ugly_minichecksum(char *curr_fname)
89{
90
91 /*@ buffers ***************************************************** */
92 static char curr_cksum[1000];
93
94 /*@ pointers **************************************************** */
95
96 /*@ structures ************************************************** */
97 struct stat buf;
98
99 /*@ initialize data *************************************************** */
100 curr_cksum[0] = '\0';
101
102 /*@************************************************************** */
103
104 assert_string_is_neither_NULL_nor_zerolength(curr_fname);
105 if (lstat(curr_fname, &buf)) {
106 return (curr_cksum); // empty
107 }
108
109 sprintf(curr_cksum, "%ld-%ld-%ld", (long) (buf.st_size),
110 (long) (buf.st_mtime), (long) (buf.st_ctime));
111 return (curr_cksum);
112}
113
114
115
116/**
117 * Get the number of lines in @p filename.
118 * @param filename The file to count lines in.
119 * @return The number of lines in @p filename.
120 * @bug This function uses the shell and "wc -l"; it should probably be rewritten in C.
121 */
122long count_lines_in_file(char *filename)
123{
124
125 /*@ buffers ***************************************************** */
126 char *command = NULL;
127 char *incoming = NULL;
128
129 /*@ long ******************************************************** */
130 long noof_lines = -1L;
131
132 /*@ pointers **************************************************** */
133 FILE *fin;
134
135 assert_string_is_neither_NULL_nor_zerolength(filename);
136 if (!does_file_exist(filename)) {
137 log_it("%s does not exist, so I cannot found the number of lines in it", filename);
138 return (0);
139 }
140 mr_asprintf(command, "cat %s | wc -l", filename);
141 if (!does_file_exist(filename)) {
142 mr_free(command);
143 return (-1);
144 }
145 fin = popen(command, "r");
146 mr_free(command);
147 if (fin) {
148 if (feof(fin)) {
149 noof_lines = 0;
150 } else {
151 mr_getline(incoming, fin);
152 while (strlen(incoming) > 0 && incoming[strlen(incoming) - 1] < 32) {
153 incoming[strlen(incoming) - 1] = '\0';
154 }
155 noof_lines = atol(incoming);
156 mr_free(incoming);
157 }
158 paranoid_pclose(fin);
159 }
160 return (noof_lines);
161}
162
163
164/**
165 * Check for existence of given @p filename.
166 * @param filename The file to check for.
167 * @return TRUE if it exists, FALSE otherwise.
168 */
169bool does_file_exist(char *filename)
170{
171
172 /*@ structures ************************************************** */
173 struct stat buf;
174
175 /*@************************************************************** */
176
177 assert(filename != NULL);
178 // assert_string_is_neither_NULL_nor_zerolength(filename);
179 if (lstat(filename, &buf)) {
180 log_msg(20, "%s does not exist", filename);
181 return (FALSE);
182 } else {
183 log_msg(20, "%s exists", filename);
184 return (TRUE);
185 }
186}
187
188
189
190
191
192
193/**
194 * Modify @p inout (a file containing a list of files) to only contain files
195 * that exist.
196 * @param inout The filelist to operate on.
197 * @note The original file is renamed beforehand, so it will not be accessible
198 * while the modification is in progress.
199 */
200void exclude_nonexistent_files(char *inout)
201{
202 char *infname = NULL;
203 char *outfname = NULL;
204 char *tmp = NULL;
205 char *incoming = NULL;
206
207 /*@ int ********************************************************* */
208 int i;
209
210 /*@ pointers **************************************************** */
211 FILE *fin, *fout;
212
213
214 /*@ end vars *********************************************************** */
215
216 assert_string_is_neither_NULL_nor_zerolength(inout);
217 mr_asprintf(infname, "%s.in", inout);
218 mr_asprintf(outfname, "%s", inout);
219 mr_asprintf(tmp, "cp -f %s %s", inout, infname);
220 run_program_and_log_output(tmp, FALSE);
221 mr_free(tmp);
222
223 if (!(fin = fopen(infname, "r"))) {
224 log_OS_error("Unable to openin infname");
225 mr_free(infname);
226 return;
227 }
228 if (!(fout = fopen(outfname, "w"))) {
229 log_OS_error("Unable to openout outfname");
230 mr_free(outfname);
231 return;
232 }
233 mr_free(outfname);
234
235 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
236 i = strlen(incoming) - 1;
237 if (i >= 0 && incoming[i] < 32) {
238 incoming[i] = '\0';
239 }
240 if (does_file_exist(incoming)) {
241 fprintf(fout, "%s\n", incoming);
242 } else {
243 log_it("Excluding '%s'-nonexistent\n", incoming);
244 }
245 mr_free(incoming);
246 }
247 mr_free(incoming);
248
249 paranoid_fclose(fout);
250 paranoid_fclose(fin);
251 unlink(infname);
252 mr_free(infname);
253}
254
255
256
257
258
259
260
261
262
263/**
264 * Attempt to find the user's kernel by calling Mindi.
265 * If Mindi can't find the kernel, ask user. If @p kernel is not empty,
266 * don't do anything.
267 * @param kernel Where to put the found kernel.
268 * @return 0 for success, 1 for failure.
269 */
270char *figure_out_kernel_path_interactively_if_necessary(void) {
271
272 char *tmp = NULL;
273 char *command = NULL;;
274 char *kernel = NULL;;
275
276 kernel = call_program_and_get_last_line_of_output("mindi --findkernel 2> /dev/null");
277
278 // If we didn't get anything back, check whether mindi raised a fatal error
279 if (!kernel[0]) {
280 mr_asprintf(command, "%s", "grep 'Fatal error' /var/log/mindi.log");
281 tmp = call_program_and_get_last_line_of_output(command);
282 if (strlen(tmp) > 1) {
283 popup_and_OK(tmp);
284 mr_free(tmp);
285 mr_free(command);
286 mr_free(kernel);
287 fatal_error("Mindi gave a fatal error. Please check '/var/log/mindi.log'.");
288 }
289 mr_free(tmp);
290 mr_free(command);
291 }
292 log_it("Calling Mindi with kernel path of '%s'", kernel);
293 while (!kernel[0]) {
294 if (!ask_me_yes_or_no("Kernel not found or invalid. Choose another?")) {
295 return (NULL);
296 }
297 tmp = popup_and_get_string("Kernel path", "What is the full path and filename of your kernel, please?", kernel);
298 if (tmp == NULL) {
299 fatal_error("Kernel not found. Please specify with the '-k' flag.");
300 }
301 mr_free(kernel);
302 kernel = tmp;
303
304 log_it("User says kernel is at %s", kernel);
305 }
306 return (kernel);
307}
308
309
310
311
312
313
314/**
315 * Find location of specified executable in user's PATH.
316 * @param fname The basename of the executable to search for (e.g. @c afio).
317 * @return The full path to the executable, or "" if it does not exist, or NULL if @c file could not be found.
318 * @note The returned string points to static storage that will be overwritten with each call.
319 * @bug The checks with @c file and @c dirname seem pointless. If @c output is "", then you're calling
320 * <tt>dirname 2\>/dev/null</tt> or <tt>file 2\>/dev/null | cut -d':' -f1 2\>/dev/null</tt>, which basically amounts
321 * to nothing.
322 */
323char *find_home_of_exe(char *fname)
324{
325 /*@ buffers ********************* */
326 char *output = NULL;
327 char *command = NULL;
328
329 /*@******************************* */
330
331 assert_string_is_neither_NULL_nor_zerolength(fname);
332 mr_asprintf(command, "which %s 2> /dev/null", fname);
333 output = call_program_and_get_last_line_of_output(command);
334 mr_free(command);
335 if (output[0] == '\0') {
336 if (system("which file > /dev/null 2> /dev/null")) {
337 mr_free(output);
338 return (NULL); // forget it :)
339 }
340 mr_asprintf(command, "file %s 2> /dev/null | cut -d':' -f1 2> /dev/null", output);
341 mr_free(output);
342 output = call_program_and_get_last_line_of_output(command);
343 mr_free(command);
344 }
345 if (output[0] == '\0') {
346 mr_asprintf(command, "dirname %s 2> /dev/null", output);
347 mr_free(output);
348 output = call_program_and_get_last_line_of_output(command);
349 mr_free(command);
350 }
351
352 if (output[0] != '\0' && does_file_exist(output)) {
353 log_msg(4, "find_home_of_exe () --- Found %s at %s", fname, output);
354 } else {
355 mr_free(output);
356 log_msg(4, "find_home_of_exe() --- Could not find %s", fname);
357 }
358 return (output);
359}
360
361
362
363
364
365
366
367
368/**
369 * Get the last sequence of digits surrounded by non-digits in the first 32k of
370 * a file.
371 * @param logfile The file to look in.
372 * @return The number found, or 0 if none.
373 */
374int get_trackno_from_logfile(char *logfile)
375{
376
377 /*@ pointers ********************************************************* */
378 FILE *fin;
379
380 /*@ int ************************************************************** */
381 int trackno = 0;
382 size_t len = 0;
383
384 /*@ buffer ************************************************************ */
385 char datablock[32701];
386
387 assert_string_is_neither_NULL_nor_zerolength(logfile);
388 if (!(fin = fopen(logfile, "r"))) {
389 log_OS_error("Unable to open logfile");
390 fatal_error("Unable to open logfile to read trackno");
391 }
392 len = fread(datablock, 1, 32700, fin);
393 paranoid_fclose(fin);
394 if (len <= 0) {
395 return (0);
396 }
397 for (; len > 0 && !isdigit(datablock[len - 1]); len--);
398 datablock[len--] = '\0';
399 for (; len > 0 && isdigit(datablock[len - 1]); len--);
400 trackno = atoi(datablock + len);
401 return (trackno);
402}
403
404
405
406
407
408
409
410/**
411 * Get a percentage from the last line of @p filename. We look for the string
412 * "% done" on the last line and, if we find it, grab the number before the last % sign.
413 * @param filename The file to get the percentage from.
414 * @return The percentage found, or 0 for error.
415 */
416int grab_percentage_from_last_line_of_file(char *filename)
417{
418
419 /*@ buffers ***************************************************** */
420 char *lastline = NULL;
421 char *command = NULL;
422 /*@ pointers **************************************************** */
423 char *p = NULL;
424
425 /*@ int's ******************************************************* */
426 int i = 0;
427
428 for (i = NOOF_ERR_LINES - 1; i >= 0 && !strstr(err_log_lines[i], "% Done") && !strstr(err_log_lines[i], "% done"); i--);
429 if (i < 0) {
430 mr_asprintf(command, "tail -n3 %s | grep -Fi %% | tail -n1 | awk '{print $0;}'", filename);
431 lastline = call_program_and_get_last_line_of_output(command);
432 mr_free(command);
433 if (!lastline[0]) {
434 mr_free(lastline);
435 return (0);
436 }
437 } else {
438 mr_asprintf(lastline, "%s", err_log_lines[i]);
439 }
440
441 p = strrchr(lastline, '%');
442 if (p) {
443 *p = '\0';
444 } else {
445 mr_free(lastline);
446 return (0);
447 }
448
449 for (p--; isdigit(*p) && p != lastline; p--);
450 if (p != lastline) {
451 p++;
452 }
453 i = atoi(p);
454 mr_free(lastline);
455 return (i);
456}
457
458
459
460
461
462/**
463 * Return the last line of @p filename.
464 * @param filename The file to get the last line of.
465 * @return The last line of the file.
466 * @note The returned string points to static storage that will be overwritten with each call.
467 */
468char *last_line_of_file(char *filename)
469{
470 /*@ buffers ***************************************************** */
471 char *output = NULL;
472 char *command = NULL;
473
474 /*@ pointers **************************************************** */
475 FILE *fin;
476
477 /*@ end vars **************************************************** */
478
479 if (!does_file_exist(filename)) {
480 log_it("Tring to get last line of nonexistent file (%s)", filename);
481 mr_asprintf(output, "");
482 return (output);
483 }
484 mr_asprintf(command, "tail -n1 %s", filename);
485 fin = popen(command, "r");
486 mr_free(command);
487
488 mr_getline(output, fin);
489 paranoid_pclose(fin);
490 while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
491 output[strlen(output) - 1] = '\0';
492 }
493 return (output);
494}
495
496/**
497 * Get the length of @p filename in bytes.
498 * @param filename The file to get the length of.
499 * @return The length of the file, or -1 for error.
500 */
501off_t length_of_file(char *filename)
502{
503 /*@ pointers *************************************************** */
504 FILE *fin;
505
506 /*@ long long ************************************************* */
507 off_t length;
508
509 fin = fopen(filename, "r");
510 if (!fin) {
511 log_it("filename=%s", filename);
512 log_OS_error("Unable to openin filename");
513 return (-1);
514 }
515 fseeko(fin, 0, SEEK_END);
516 length = ftello(fin);
517 paranoid_fclose(fin);
518 return (length);
519}
520
521
522
523/**
524 * ?????
525 * @bug I don't know what this function does. However, it seems orphaned, so it should probably be removed.
526 */
527int make_checksum_list_file(char *filelist, char *cksumlist, char *comppath) {
528 /*@ pointers **************************************************** */
529 FILE *fin;
530 FILE *fout;
531
532 /*@ int ******************************************************* */
533 int percentage;
534 int i;
535 int counter = 0;
536
537 /*@ buffer ****************************************************** */
538 char *stub_fname = NULL;
539 char *curr_fname = NULL;
540 char *curr_cksum = NULL;
541 char *tmp = NULL;
542
543 /*@ long [long] ************************************************* */
544 off_t filelist_length;
545 off_t curr_pos;
546 long start_time;
547 long current_time;
548 long time_taken;
549 long time_remaining;
550
551 /*@ end vars *************************************************** */
552
553 start_time = get_time();
554 filelist_length = length_of_file(filelist);
555 log_it("filelist = %s; cksumlist = %s", filelist, cksumlist);
556
557 fin = fopen(filelist, "r");
558 if (fin == NULL) {
559 log_OS_error("Unable to fopen-in filelist");
560 log_to_screen("Can't open filelist");
561 return (1);
562 }
563 fout = fopen(cksumlist, "w");
564 if (fout == NULL) {
565 log_OS_error("Unable to openout cksumlist");
566 paranoid_fclose(fin);
567 log_to_screen("Can't open checksum list");
568 return (1);
569 }
570 for (mr_getline(stub_fname, fin); !feof(fin); mr_getline(stub_fname, fin)) {
571 if (stub_fname[(i = strlen(stub_fname) - 1)] < 32) {
572 stub_fname[i] = '\0';
573 }
574 mr_asprintf(tmp, "%s%s", comppath, stub_fname);
575 mr_free(stub_fname);
576
577 mr_asprintf(curr_fname, "%s", tmp + 1);
578 mr_free(tmp);
579
580 mr_asprintf(curr_cksum, "%s", calc_file_ugly_minichecksum(curr_fname));
581 fprintf(fout, "%s\t%s\n", curr_fname, curr_cksum);
582 mr_free(curr_cksum);
583
584 if (counter++ > 12) {
585 current_time = get_time();
586 counter = 0;
587 /* BERLIOS: 37 really ? */
588 curr_fname[37] = '\0';
589 curr_pos = ftello(fin) / 1024;
590 percentage = (int) (curr_pos * 100 / filelist_length);
591 time_taken = current_time - start_time;
592 if (percentage != 0) {
593 time_remaining = time_taken * 100 / (long) (percentage) - time_taken;
594 log_to_screen("%02d%% done %02d:%02d taken %02d:%02d remaining %-37s\r", percentage, (int) (time_taken / 60), (int) (time_taken % 60), (int) (time_remaining / 60), (int) (time_remaining % 60), curr_fname);
595 }
596 sync();
597 }
598 mr_free(curr_fname);
599 }
600 mr_free(stub_fname);
601
602 paranoid_fclose(fout);
603 paranoid_fclose(fin);
604 log_it("Done.");
605 return (0);
606}
607
608
609/**
610 * Create the directory @p outdir_fname and all parent directories. Equivalent to <tt>mkdir -p</tt>.
611 * @param outdir_fname The directory to create.
612 * @return The return value of @c mkdir.
613 */
614int make_hole_for_dir(const char *outdir_fname)
615{
616 char *tmp = NULL;
617 int res = 0;
618
619 assert_string_is_neither_NULL_nor_zerolength(outdir_fname);
620 mr_asprintf(tmp, "mkdir -p %s", outdir_fname);
621 res = system(tmp);
622 mr_free(tmp);
623 return (res);
624}
625
626
627/**
628 * Create the parent directories of @p outfile_fname.
629 * @param outfile_fname The file to make a "hole" for.
630 * @return 0, always.
631 * @bug Return value unnecessary.
632 */
633int make_hole_for_file(char *outfile_fname)
634{
635 /*@ buffer ****************************************************** */
636 char *command = NULL;
637
638 /*@ int ******************************************************** */
639 int res = 0;
640
641 /*@ end vars *************************************************** */
642
643 assert_string_is_neither_NULL_nor_zerolength(outfile_fname);
644 assert(!strstr(outfile_fname, MNT_CDROM));
645 assert(!strstr(outfile_fname, "/dev/cdrom"));
646 mr_asprintf(command, "mkdir -p \"%s\" 2> /dev/null", outfile_fname);
647 res += system(command);
648 mr_free(command);
649
650 mr_asprintf(command, "rmdir \"%s\" 2> /dev/null", outfile_fname);
651 res += system(command);
652 mr_free(command);
653
654 mr_asprintf(command, "rm -f \"%s\" 2> /dev/null", outfile_fname);
655 res += system(command);
656 mr_free(command);
657
658 unlink(outfile_fname);
659 return (0);
660}
661
662
663
664
665/**
666 * Get the number of lines in @p filelist_fname that contain the string @p wildcard.
667 * @param filelist_fname The file to search through.
668 * @param wildcard The string to search for. This is @e not a shell glob or a regular expression.
669 * @return The number of lines matched.
670 */
671long noof_lines_that_match_wildcard(char *filelist_fname, char *wildcard)
672{
673 /*@ long ******************************************************* */
674 long matches = 0;
675
676 /*@ pointers *************************************************** */
677 FILE *fin;
678
679 /*@ buffers **************************************************** */
680 char *incoming = NULL;
681
682 /*@ end vars *************************************************** */
683
684
685 fin = fopen(filelist_fname, "r");
686
687 if (!fin) {
688 log_OS_error("Unable to openin filelist_fname");
689 return (0);
690 }
691 mr_getline(incoming, fin);
692 while (!feof(fin)) {
693 if (strstr(incoming, wildcard)) {
694 matches++;
695 }
696 mr_free(incoming);
697 mr_getline(incoming, fin);
698 }
699 mr_free(incoming);
700 paranoid_fclose(fin);
701 return (matches);
702}
703
704
705
706/**
707 * Determine the size (in KB) of @p dev in the mountlist in mountlist.txt.
708 * @param tmpdir The tempdir where the mountlist is stored.
709 * @param dev The device to search for.
710 * @return The size of the partition in KB.
711 */
712long size_of_partition_in_mountlist_K(char *tmpdir, char *dev)
713{
714 char *command = NULL;
715 char *mountlist = NULL;
716 char *sz_res = NULL;
717 long file_len_K;
718
719 mr_asprintf(mountlist, "%s/mountlist.txt", MINDI_CACHE);
720 mr_asprintf(command, "grep \"%s \" %s/mountlist.txt | head -n1 | awk '{print $4}'", dev, MINDI_CACHE);
721 mr_free(mountlist);
722
723 log_it(command);
724 sz_res = call_program_and_get_last_line_of_output(command);
725 file_len_K = atol(sz_res);
726 log_msg(4, "%s --> %s --> %ld", command, sz_res, file_len_K);
727 mr_free(sz_res);
728 mr_free(command);
729
730 return (file_len_K);
731}
732
733/**
734 * Calculate the total size (in KB) of all the biggiefiles in this backup.
735 * @param bkpinfo The backup information structure. Only the @c bkpinfo->tmpdir field is used.
736 * @return The total size of all biggiefiles in KB.
737 */
738long size_of_all_biggiefiles_K()
739{
740 /*@ buffers ***************************************************** */
741 char *fname = NULL;
742 char *biggielist = NULL;
743 char *tmp = NULL;
744 char *command = NULL;
745
746 /*@ long ******************************************************** */
747 long scratchL = 0;
748 long file_len_K;
749
750 /*@ pointers *************************************************** */
751 FILE *fin = NULL;
752
753 /*@ end vars *************************************************** */
754
755 log_it("Calculating size of all biggiefiles (in total)");
756 mr_asprintf(biggielist, "%s/biggielist.txt", bkpinfo->tmpdir);
757 log_it("biggielist = %s", biggielist);
758 fin = fopen(biggielist, "r");
759 mr_free(biggielist);
760
761 if (!(fin)) {
762 log_OS_error("Cannot open biggielist. OK, so estimate is based on filesets only.");
763 } else {
764 log_msg(4, "Reading it...");
765 for (mr_getline(fname, fin); !feof(fin); mr_getline(fname, fin)) {
766 if (fname[strlen(fname) - 1] <= 32) {
767 fname[strlen(fname) - 1] = '\0';
768 }
769 if (0 == strncmp(fname, "/dev/", 5)) {
770 if (is_dev_an_NTFS_dev(fname)) {
771 tmp = find_home_of_exe("ntfsresize");
772 if (!tmp) {
773 mr_free(tmp);
774 mr_free(fname);
775 fatal_error("ntfsresize not found");
776 }
777 mr_free(tmp);
778
779 mr_asprintf(command, "ntfsresize --force --info %s|grep '^You might resize at '|cut -d' ' -f5", fname);
780 log_it("command = %s", command);
781 tmp = call_program_and_get_last_line_of_output(command);
782 mr_free(command);
783
784 log_it("res of it = %s", tmp);
785 file_len_K = atoll(tmp) / 1024L;
786 mr_free(tmp);
787 } else {
788 file_len_K = get_phys_size_of_drive(fname) * 1024L;
789 }
790 } else {
791 /* BERLIOS: more than long here ??? */
792 file_len_K = (long) (length_of_file(fname) / 1024);
793 }
794 if (file_len_K > 0) {
795 scratchL += file_len_K;
796 log_msg(4, "%s --> %ld K", fname, file_len_K);
797 }
798 log_msg(4, "After adding %s, scratchL+%ld now equals %ld", fname, file_len_K, scratchL);
799 if (feof(fin)) {
800 break;
801 }
802 mr_free(fname);
803 }
804 mr_free(fname);
805 }
806 log_it("Closing...");
807 paranoid_fclose(fin);
808 log_it("Finished calculating total size of all biggiefiles");
809 return (scratchL);
810}
811
812/**
813 * Determine the amount of space (in KB) occupied by a mounted CD.
814 * This can also be used to find the space used for other directories.
815 * @param mountpt The mountpoint/directory to check.
816 * @return The amount of space occupied in KB.
817 */
818long long space_occupied_by_cd(char *mountpt)
819{
820 /*@ buffer ****************************************************** */
821 char *tmp = NULL;
822 char *command = NULL;
823 long long llres;
824 /*@ pointers **************************************************** */
825 char *p;
826 FILE *fin;
827
828 /*@ end vars *************************************************** */
829
830 mr_asprintf(command, "du -sk %s", mountpt);
831 errno = 0;
832 fin = popen(command, "r");
833 if (errno) {
834 log_it("popen() FAILED: command=%s, mountpt=%s, fin=%d, errno=%d, strerror=%s", command, mountpt, fin, errno, strerror(errno));
835 llres = 0;
836 } else {
837 mr_getline(tmp, fin);
838 paranoid_pclose(fin);
839 p = strchr(tmp, '\t');
840 if (p) {
841 *p = '\0';
842 }
843 for (p = tmp, llres = 0; *p != '\0'; p++) {
844 llres *= 10;
845 llres += (int) (*p - '0');
846 }
847 mr_free(tmp);
848 }
849 mr_free(command);
850
851 return (llres);
852}
853
854
855/**
856 * Update a CRC checksum to include another character.
857 * @param crc The original CRC checksum.
858 * @param c The character to add.
859 * @return The new CRC checksum.
860 * @ingroup utilityGroup
861 */
862unsigned int updcrc(unsigned int crc, unsigned int c)
863{
864 unsigned int tmp;
865 tmp = (crc >> 8) ^ c;
866 crc = (crc << 8) ^ crctttab[tmp & 255];
867 return crc;
868}
869
870/**
871 * Update a reverse CRC checksum to include another character.
872 * @param crc The original CRC checksum.
873 * @param c The character to add.
874 * @return The new CRC checksum.
875 * @ingroup utilityGroup
876 */
877unsigned int updcrcr(unsigned int crc, unsigned int c)
878{
879 unsigned int tmp;
880 tmp = crc ^ c;
881 crc = (crc >> 8) ^ crc16tab[tmp & 0xff];
882 return crc;
883}
884
885
886
887
888/**
889 * Check for an executable on the user's system; write a message to the
890 * screen and the log if we can't find it.
891 * @param fname The executable basename to look for.
892 * @return 0 if it's found, nonzero if not.
893 */
894int whine_if_not_found(char *fname)
895{
896 /*@ buffers *** */
897 char *command = NULL;
898 int res = 0;
899
900 mr_asprintf(command, "which %s > /dev/null 2> /dev/null", fname);
901 res = system(command);
902 mr_free(command);
903
904 if (res) {
905 log_to_screen("Please install '%s'. I cannot find it on your system.", fname);
906 log_to_screen("There may be hyperlink at http://www.mondorescue.com which");
907 log_to_screen("will take you to the relevant (missing) package.");
908 return (1);
909 } else {
910 return (0);
911 }
912}
913
914
915
916
917
918
919/**
920 * Create a data file at @p fname containing @p contents.
921 * The data actually can be multiple lines, despite the name.
922 * @param fname The file to create.
923 * @param contents The data to put in it.
924 * @return 0 for success, 1 for failure.
925 */
926int write_one_liner_data_file(char *fname, char *contents)
927{
928 /*@ pointers *************************************************** */
929 FILE *fout;
930 int res = 0;
931
932 /*@ end vars *************************************************** */
933
934 assert_string_is_neither_NULL_nor_zerolength(fname);
935 if (!contents) {
936 log_it("%d: Warning - writing NULL to %s", __LINE__, fname);
937 }
938 if (!(fout = fopen(fname, "w"))) {
939 log_it("fname=%s");
940 log_OS_error("Unable to openout fname");
941 return (1);
942 }
943 fprintf(fout, "%s\n", contents);
944 paranoid_fclose(fout);
945 return (res);
946}
947
948
949
950/**
951 * Read @p fname into @p contents.
952 * @param fname The file to read.
953 * @param contents Where to put its contents.
954 * @return 0 for success, nonzero for failure.
955 */
956int read_one_liner_data_file(char *fname, char *contents)
957{
958 /*@ pointers *************************************************** */
959 FILE *fin;
960 int res = 0;
961 int i;
962
963 /*@ end vars *************************************************** */
964
965 assert_string_is_neither_NULL_nor_zerolength(fname);
966 if (!contents) {
967 log_it("%d: Warning - reading NULL from %s", __LINE__, fname);
968 }
969 if (!(fin = fopen(fname, "r"))) {
970 log_it("fname=%s", fname);
971 log_OS_error("Unable to openin fname");
972 return (1);
973 }
974 fscanf(fin, "%s\n", contents);
975 i = strlen(contents);
976 if (i > 0 && contents[i - 1] < 32) {
977 contents[i - 1] = '\0';
978 }
979 paranoid_fclose(fin);
980 return (res);
981}
982
983
984
985
986
987
988
989
990
991/**
992 * Copy the files that Mondo/Mindi need to run to the scratchdir or tempdir.
993 * Currently this includes: copy Mondo's home directory to scratchdir,
994 * copy post-nuke.tgz (if it exists) to tmpdir,
995 * and run "hostname > scratchdir/HOSTNAME".
996 * @param bkpinfo The backup information structure. Fields used:
997 * - @c bkpinfo->postnuke_tarball
998 * - @c bkpinfo->scratchdir
999 * - @c bkpinfo->tmpdir
1000 */
1001void copy_mondo_and_mindi_stuff_to_scratchdir()
1002{
1003 /*@ Char buffers ** */
1004 char *command = NULL;
1005 char *tmp = NULL;
1006 int res = 0;
1007
1008 mvaddstr_and_log_it(g_currentY, 0, "Copying Mondo's core files to the scratch directory");
1009
1010 log_msg(4, "g_mondo_home='%s'", g_mondo_home);
1011 if (strlen(g_mondo_home) < 2) {
1012 find_and_store_mondoarchives_home(g_mondo_home);
1013 }
1014 mr_asprintf(command, CP_BIN " --parents -pRdf %s %s", g_mondo_home, bkpinfo->scratchdir);
1015
1016 log_msg(4, "command = %s", command);
1017 res = run_program_and_log_output(command, 1);
1018 mr_free(command);
1019
1020 if (res) {
1021 fatal_error("Failed to copy Mondo's stuff to scratchdir");
1022 }
1023
1024 tmp = call_program_and_get_last_line_of_output("which mondorestore");
1025 if (!tmp[0]) {
1026 mr_free(tmp);
1027 fatal_error("'which mondorestore' returned null. Where's your mondorestore? `which` can't find it. That's odd. Did you install mondorestore?");
1028 }
1029 mr_free(tmp);
1030
1031 mr_asprintf(command, "hostname > %s/HOSTNAME", bkpinfo->scratchdir);
1032 paranoid_system(command);
1033 mr_free(command);
1034
1035 if (bkpinfo->postnuke_tarball) {
1036 mr_asprintf(command, "cp -f %s %s/post-nuke.tgz", bkpinfo->postnuke_tarball, bkpinfo->tmpdir);
1037 res = run_program_and_log_output(command, FALSE);
1038 mr_free(command);
1039
1040 if (res) {
1041 fatal_error("Unable to copy post-nuke tarball to tmpdir");
1042 }
1043 }
1044
1045 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1046}
1047
1048
1049
1050
1051
1052/**
1053 * Store the client's NETFS configuration in files to be restored at restore-time.
1054 * Assumes that @c bkpinfo->media_type = netfs, but does not check for this.
1055 * @param bkpinfo The backup information structure. Fields used:
1056 * - @c netfs_mount
1057 * - @c netfs_remote_dir
1058 * - @c tmpdir
1059 */
1060void store_netfs_config()
1061{
1062
1063 /*@ buffers ******** */
1064 char *netfs_dev = NULL;
1065 char *mac_addr = NULL;
1066 char *netfs_mount = NULL;
1067 char *netfs_client_ipaddr = NULL;
1068 char *netfs_client_netmask = NULL;
1069 char *netfs_client_broadcast = NULL;
1070 char *netfs_client_defgw = NULL;
1071 char *netfs_server_ipaddr = NULL;
1072 char *tmp = NULL;
1073 char *command = NULL;
1074
1075 /*@ pointers ***** */
1076 char *p;
1077
1078 if (! bkpinfo->netfs_mount) {
1079 fatal_error("No netfs_mount found !");
1080 }
1081
1082 log_it("Storing Network configuration");
1083 mr_asprintf(tmp, "%s", bkpinfo->netfs_mount);
1084 p = strchr(tmp, ':');
1085 if (!p) {
1086 fatal_error("Network mount doesn't have a colon in it, e.g. 192.168.1.4:/home/nfs");
1087 }
1088 *(p++) = '\0';
1089 mr_asprintf(netfs_server_ipaddr, "%s", tmp);
1090 mr_asprintf(netfs_mount, "%s", p);
1091 mr_free(tmp);
1092
1093 /* BERLIOS : there is a bug #67 here as it only considers the first NIC */
1094 mr_asprintf(command, "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\n' | head -n1 | cut -d' ' -f1");
1095 netfs_dev = call_program_and_get_last_line_of_output(command);
1096 mr_free(command);
1097
1098 mr_asprintf(command, "%s", "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f7 | cut -d':' -f2");
1099 netfs_client_ipaddr = call_program_and_get_last_line_of_output(command);
1100 mr_free(command);
1101
1102 mr_asprintf(command, "%s", "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f9 | cut -d':' -f2");
1103 netfs_client_netmask = call_program_and_get_last_line_of_output(command);
1104 mr_free(command);
1105
1106 mr_asprintf(command, "%s", "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f8 | cut -d':' -f2");
1107 netfs_client_broadcast = call_program_and_get_last_line_of_output(command);
1108 mr_free(command);
1109
1110 mr_asprintf(command, "%s", "route -n | grep '^0.0.0.0' | awk '{print $2}'");
1111 netfs_client_defgw = call_program_and_get_last_line_of_output(command);
1112 mr_free(command);
1113
1114 if (strlen(netfs_dev) < 2) {
1115 fatal_error("Unable to find ethN (eth0, eth1, ...) adapter via Network mount you specified.");
1116 }
1117
1118 /********
1119 * If the Network device that found above is a bonded device,
1120 * we need to replace it with an ethN device or the
1121 * networking will not start during an Network restore.
1122 *
1123 * If the Network device in netfs_dev begins with the word "bond", or alb or aft
1124 * look for the corresponding slave ethN device and copy it to netfs_dev.
1125 * Using the common MAC address
1126 ********/
1127 if (!strncmp(netfs_dev, "bond", 4) || !strncmp(netfs_dev, "alb", 3) || !strncmp(netfs_dev, "aft", 3)) {
1128 log_to_screen("Found bonding device %s; looking for corresponding ethN slave device\n", netfs_dev);
1129 mr_asprintf(command, "%s", "ifconfig %s | awk '{print $5}' | head -n1", netfs_dev);
1130 mac_addr = call_program_and_get_last_line_of_output(command);
1131 mr_free(command);
1132
1133 mr_asprintf(command, "ifconfig | grep -E '%s' | grep -v '%s' | head -n1 | cut -d' ' -f1", mac_addr,netfs_dev);
1134 mr_free(mac_addr);
1135 mr_free(netfs_dev);
1136
1137 netfs_dev = call_program_and_get_last_line_of_output(command);
1138 mr_free(command);
1139
1140 log_to_screen("Replacing it with %s\n", netfs_dev);
1141 }
1142
1143 mr_asprintf(tmp, "%s/NETFS-DEV", bkpinfo->tmpdir);
1144 write_one_liner_data_file(tmp, netfs_dev);
1145 mr_free(netfs_dev);
1146 mr_free(tmp);
1147
1148 mr_asprintf(tmp, "%s/NETFS-SERVER-MOUNT", bkpinfo->tmpdir);
1149 write_one_liner_data_file(tmp, bkpinfo->netfs_mount);
1150 mr_free(tmp);
1151 mr_free(netfs_mount);
1152
1153 mr_asprintf(tmp, "%s/NETFS-SERVER-PATH", bkpinfo->tmpdir);
1154 write_one_liner_data_file(tmp, bkpinfo->netfs_remote_dir);
1155 mr_free(tmp);
1156
1157 log_it("Finished storing Network configuration");
1158}
1159
1160
1161/**
1162 * Determine the approximate number of media that the backup will take up,
1163 * and tell the user. The uncompressed size is estimated as size_of_all_biggiefiles_K()
1164 * plus (noof_sets x bkpinfo->optimal_set_size). The compression factor is estimated as
1165 * 2/3 for LZO and 1/2 for bzip2. The data is not saved anywhere. If there are any
1166 * "imagedevs", the estimate is not shown as it will be wildly inaccurate.
1167 * If there are more than 50 media estimated, the estimate will not be shown.
1168 * @param bkpinfo The backup information structure. Fields used:
1169 * - @c bkpinfo->backup_media_type
1170 * - @c bkpinfo->media_size
1171 * - @c bkpinfo->optimal_set_size
1172 * - @c bkpinfo->use_lzo
1173 * @param noof_sets The number of filesets created.
1174 * @ingroup archiveGroup
1175 */
1176void
1177estimate_noof_media_required(long noof_sets)
1178{
1179 /*@ buffers *************** */
1180 char *tmp = NULL;
1181 char *mds = NULL;
1182
1183 /*@ long long ************* */
1184 long long scratchLL;
1185
1186 if (bkpinfo->media_size[1] <= 0) {
1187 log_to_screen("Number of media required: UNKNOWN");
1188 return;
1189 }
1190
1191 log_it("Estimating number of media required...");
1192 scratchLL =
1193 (long long) (noof_sets) * (long long) (bkpinfo->optimal_set_size)
1194 + (long long) (size_of_all_biggiefiles_K());
1195 scratchLL = (scratchLL / 1024) / bkpinfo->media_size[1];
1196 scratchLL++;
1197 if (bkpinfo->use_lzo) {
1198 scratchLL = (scratchLL * 2) / 3;
1199 } else if (bkpinfo->use_gzip) {
1200 scratchLL = (scratchLL * 2) / 3;
1201 } else if (bkpinfo->use_lzma) {
1202 scratchLL = (scratchLL * 2) / 3;
1203 } else {
1204 scratchLL = scratchLL / 2;
1205 }
1206 if (!scratchLL) {
1207 scratchLL++;
1208 }
1209 if (scratchLL <= 1) {
1210 mds = media_descriptor_string(bkpinfo->backup_media_type);
1211 mr_asprintf(tmp, "Your backup will probably occupy a single %s. Maybe two.", mds);
1212 mr_free(mds);
1213 } else if (scratchLL > 4) {
1214 mr_asprintf(tmp, "Your backup will occupy one meeeeellion media! (maybe %s)", number_to_text((int) (scratchLL + 1)));
1215 } else {
1216 mr_asprintf(tmp, "Your backup will occupy approximately %s media.", number_to_text((int) (scratchLL + 1)));
1217 }
1218 if (scratchLL < 50) {
1219 log_to_screen(tmp);
1220 }
1221 mr_free(tmp);
1222}
1223
1224
1225/**
1226 * Determine whether a file is compressed. This is done
1227 * by reading through the "do-not-compress-these" file distributed with Mondo.
1228 * @param filename The file to check.
1229 * @return TRUE if it's compressed, FALSE if not.
1230 */
1231bool is_this_file_compressed(char *filename)
1232{
1233 char *do_not_compress_these = NULL;
1234 char *tmp = NULL;
1235 char *p;
1236 char *q = NULL;
1237
1238 q = strrchr(filename, '.');
1239 if (q == NULL) {
1240 return (FALSE);
1241 }
1242
1243 mr_asprintf(tmp, "%s/do-not-compress-these", g_mondo_home);
1244 if (!does_file_exist(tmp)) {
1245 mr_free(tmp);
1246 return (FALSE);
1247 }
1248 /* BERLIOS: This is just plain WRONG !! */
1249 do_not_compress_these = last_line_of_file(tmp);
1250 mr_free(tmp);
1251
1252 for (p = do_not_compress_these; p != NULL; p++) {
1253 mr_asprintf(tmp, "%s", p);
1254 if (strchr(tmp, ' ')) {
1255 *(strchr(tmp, ' ')) = '\0';
1256 }
1257 if (!strcmp(q, tmp)) {
1258 mr_free(tmp);
1259 mr_free(do_not_compress_these);
1260 return (TRUE);
1261 }
1262 if (!(p = strchr(p, ' '))) {
1263 break;
1264 }
1265 mr_free(tmp);
1266 }
1267 mr_free(do_not_compress_these);
1268 return (FALSE);
1269}
1270
1271
1272int mode_of_file(char *fname)
1273{
1274 struct stat buf;
1275
1276 if (lstat(fname, &buf)) {
1277 return (-1);
1278 } // error
1279 else {
1280 return (buf.st_mode);
1281 }
1282}
1283
1284
1285
1286
1287/**
1288 * Create a small script that mounts /boot, calls @c grub-install, and syncs the disks.
1289 * @param outfile Where to put the script.
1290 * @return 0 for success, 1 for failure.
1291 */
1292int make_grub_install_scriptlet(char *outfile)
1293{
1294 FILE *fout;
1295 char *tmp = NULL;
1296 int retval = 0;
1297
1298 if ((fout = fopen(outfile, "w"))) {
1299 fprintf(fout,
1300 "#!/bin/sh\n\nmount /boot > /dev/null 2> /dev/null\ngrub-install $@\nres=$?\nsync;sync;sync\nexit $res\n");
1301 paranoid_fclose(fout);
1302 log_msg(2, "Created %s", outfile);
1303 mr_asprintf(tmp, "chmod +x %s", outfile);
1304 paranoid_system(tmp);
1305 mr_free(tmp);
1306 retval = 0;
1307 } else {
1308 retval = 1;
1309 }
1310 return (retval);
1311}
1312
1313/* @} - end fileGroup */
Note: See TracBrowser for help on using the repository browser.