source: branches/stable/mondo/src/common/libmondo-tools.c @ 1770

Last change on this file since 1770 was 1770, checked in by bruno, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

  • Property svn:keywords set to Id
File size: 35.7 KB
Line 
1/* $Id: libmondo-tools.c 1770 2007-11-06 10:01:53Z bruno $
2misc tools
3*/
4
5/**
6 * @file
7 * Miscellaneous tools that didn't really fit anywhere else.
8 */
9
10#include "my-stuff.h"
11#include "mr_mem.h"
12#include "mr_msg.h"
13#include "mr_file.h"
14#include "mr_gettext.h"
15#include "mr_conf.h"
16
17#include "mondostructures.h"
18#include "libmondo-tools.h"
19#include "newt-specific-EXT.h"
20#include "libmondo-files-EXT.h"
21#include "libmondo-fork-EXT.h"
22#include "libmondo-raid-EXT.h"
23#include <sys/socket.h>
24#include <netdb.h>
25#include <stdlib.h>
26#include <netinet/in.h>
27#include <arpa/inet.h>
28#include <sys/utsname.h>
29
30/*@unused@*/
31//static char cvsid[] = "$Id: libmondo-tools.c 1770 2007-11-06 10:01:53Z bruno $";
32
33extern int g_tape_buffer_size_MB;
34extern char *g_serial_string;
35extern bool g_text_mode;
36extern int g_currentY;
37extern int g_current_media_number;
38extern char *MONDO_LOGFILE;
39
40extern struct mr_ar_conf *mr_conf;
41
42/* Reference to global bkpinfo */
43extern struct s_bkpinfo *bkpinfo;
44
45/**
46 * @addtogroup globalGroup
47 * @{
48 */
49bool g_remount_cdrom_at_end,    ///< TRUE if we unmounted the CD-ROM and should remount it when done with the backup.
50 g_remount_floppy_at_end;       ///< TRUE if we unmounted the floppy and should remount it when done with the backup.
51bool g_cd_recovery;             ///< TRUE if we're making an "autonuke" backup.
52double g_kernel_version;
53
54/**
55 * The place where /boot is mounted. - Used locally only
56 */
57static char *g_boot_mountpt = NULL;
58
59/**
60 * The serial string (used to differentiate between backups) of the current backup.
61 */
62char *g_serial_string = NULL;
63
64/**
65 * The location where tmpfs is mounted, or "" if it's not mounted.
66 */
67char *g_tmpfs_mountpt = NULL;
68char *g_magicdev_command = NULL;
69
70/* @} - end of globalGroup */
71
72
73extern pid_t g_buffer_pid;
74extern pid_t g_main_pid;
75
76extern t_bkptype g_backup_media_type;
77extern char *g_backup_media_string;
78
79extern bool am_I_in_disaster_recovery_mode(void);
80
81
82/**
83 * @addtogroup utilityGroup
84 * @{
85 */
86/**
87 * Assertion handler. Prints a friendly message to the user,
88 * offering to ignore all, dump core, break to debugger,
89 * exit, or ignore. Intended to be used with an assert() macro.
90 *
91 * @param file The file in which the assertion triggered.
92 * @param function The function (@c __FUNCTION__) in which the assertion triggered.
93 * @param line The line number of the assert() statement.
94 * @param exp The expression that failed (as a string).
95 */
96void _mondo_assert_fail(const char *file,
97                        const char *function, int line, const char *exp)
98{
99    static int ignoring_assertions = 0;
100    bool is_valid = TRUE;
101
102    log_it("ASSERTION FAILED: `%s' at %s:%d in %s", exp, file, line,
103           function);
104    if (ignoring_assertions) {
105        log_it("Well, the user doesn't care...");
106        return;
107    }
108#ifndef _XWIN
109    if (!g_text_mode)
110        newtSuspend();
111#endif
112    printf(_("ASSERTION FAILED: `%s'\n"), exp);
113    printf(_("\tat %s:%d in %s\n\n"), file, line, function);
114    printf(_("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? "));
115    do {
116        is_valid = TRUE;
117        switch (toupper(getchar())) {
118        case 'A':               // ignore (A)ll
119            ignoring_assertions = 1;
120            break;
121        case 'B':               // a(B)ort
122            signal(SIGABRT, SIG_DFL);   /* prevent SIGABRT handler from running */
123            raise(SIGABRT);
124            break;              /* "can't get here" */
125        case 'D':               // (D)ebug, aka asm("int 3")
126#ifdef __IA32__
127            __asm__ __volatile__("int $3"); // break to debugger
128#endif
129            break;
130        case 'E':               // (E)xit
131            fatal_error("Failed assertion -- see above for details");
132            break;              /* "can't get here" */
133        case 'I':               // (I)gnore
134            break;
135            /* These next two work as follows:
136               the `default' catches the user's invalid choice and says so;
137               the '\n' catches the newline on the end and prints the prompt again.
138             */
139        case '\n':
140            printf
141                (_("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? "));
142            break;
143        default:
144            is_valid = FALSE;
145            printf(_("Invalid choice.\n"));
146            break;
147        }
148    } while (!is_valid);
149
150    if (ignoring_assertions) {
151        log_it("Ignoring ALL assertions from now on.");
152    } else {
153        log_it("Ignoring assertion: %s", exp);
154    }
155
156    getchar();                  // skip \n
157
158#ifndef _XWIN
159    if (!g_text_mode)
160        newtResume();
161#endif
162}
163
164/**
165 * Clean's up users' KDE desktops.
166 * @bug Details about this function are unknown.
167 */
168void clean_up_KDE_desktop_if_necessary(void)
169{
170    char *tmp;
171
172    mr_asprintf(&tmp,
173             "for i in `find /root /home -type d -name Desktop -maxdepth 2`; do \
174file=$i/.directory; if [ -f \"$file\" ] ; then mv -f $file $file.old ; \
175awk '{if (index($0, \"rootimagesmindi\")) { while (length($0)>2) { getline;} ; } \
176else { print $0;};}' $file.old  > $file ; fi ; done");
177    run_program_and_log_output(tmp, 5);
178    mr_free(tmp);
179}
180
181
182/**
183 * Locate mondoarchive's home directory. Searches in /usr/share/mondo,
184 * /usr/local/share/mondo, /opt, or if all else fails, search /usr.
185 *
186 * @param home_sz String to store the home directory ("" if it could not be found).
187 * @return 0 for success, nonzero for failure.
188 */
189int find_and_store_mondoarchives_home(char *home_sz)
190{
191    assert(home_sz != NULL);
192    strcpy(home_sz, MONDO_SHARE);
193    return (0);
194}
195
196
197char *get_architecture(void) {
198#ifdef __IA32__
199#   ifdef __X86_64__
200        return ("x86_64");
201#   else
202        return ("i386");
203#   endif
204#endif
205#ifdef __X86_64__
206    return ("x86_64");
207#endif
208#ifdef __IA64__
209    return ("ia64");
210#endif
211    return ("unknown");
212}
213
214
215char *get_uname_m(void) {
216
217    struct utsname utsn;
218    char *tmp = NULL;
219
220    uname(&utsn);
221    mr_asprintf(&tmp, utsn.machine);
222    return (tmp);
223}
224
225
226
227/* BERLIOS: Use uname instead */
228double get_kernel_version(void)
229{
230    char *p, tmp[200];
231    double d;
232#ifdef __FreeBSD__
233    // JOSH - FIXME :)
234    d = 5.2;                    // :-)
235#else
236    strcpy(tmp, call_program_and_get_last_line_of_output("uname -r"));
237    p = strchr(tmp, '.');
238    if (p) {
239        p = strchr(++p, '.');
240        if (p) {
241            while (*p) {
242                *p = *(p + 1);
243                p++;
244            }
245        }
246    }
247//  mr_msg(1, "tmp = '%s'", tmp);
248    d = atof(tmp);
249#endif
250    mr_msg(1, "g_kernel_version = %f", d);
251    return (d);
252}
253
254
255/**
256 * Get the current time.
257 * @return number of seconds since the epoch.
258 */
259long get_time(void)
260{
261    return (long) time((void *) 0);
262}
263
264
265/**
266 * Initialize a RAID volume structure, setting fields to zero. The
267 * actual hard drive is unaffected.
268 *
269 * @param raidrec The RAID volume structure to initialize.
270 * @note This function is system dependent.
271 */
272#ifdef __FreeBSD__
273void initialize_raidrec(struct vinum_volume *raidrec)
274{
275    int i, j;
276    raidrec->volname[0] = '\0';
277    raidrec->plexes = 0;
278    for (i = 0; i < 9; ++i) {
279        raidrec->plex[i].raidlevel = -1;
280        raidrec->plex[i].stripesize = 0;
281        raidrec->plex[i].subdisks = 0;
282        for (j = 0; j < 9; ++j) {
283            strcpy(raidrec->plex[i].sd[j].which_device, "");
284        }
285    }
286}
287#else
288void initialize_raidrec(struct raid_device_record *raidrec)
289{
290    assert(raidrec != NULL);
291    raidrec->raid_device[0] = '\0';
292    raidrec->raid_level = -9;
293    raidrec->persistent_superblock = 1;
294    raidrec->chunk_size = 64;
295    raidrec->parity = -1;
296    raidrec->data_disks.entries = 0;
297    raidrec->spare_disks.entries = 0;
298    raidrec->parity_disks.entries = 0;
299    raidrec->failed_disks.entries = 0;
300    raidrec->additional_vars.entries = 0;
301}
302#endif
303
304
305/**
306 * Insert modules that Mondo requires.
307 * Currently inserts @c msdos, @c vfat, and @c loop for Linux;
308 * @c msdosfs and @c ext2fs for FreeBSD.
309 */
310void insmod_crucial_modules(void)
311{
312#ifdef __FreeBSD__
313    system("kldstat | grep msdosfs || kldload msdosfs 2> /dev/null");
314    system("kldstat | grep ext2fs  || kldload ext2fs 2> /dev/null");
315#else
316    system("modprobe -a msdos vfat loop &> /dev/null");
317#endif
318}
319
320
321/**
322 * Finish configuring the backup information structure. Call this function
323 * to set the parameters that depend on those that can be given on the command
324 * line.
325 *
326 * @param bkpinfo The backup information structure. Fields modified/used:
327 * - Used: @c bkpinfo->backup_data
328 * - Used: @c bkpinfo->backup_media_type
329 * - Used: @c bkpinfo->writer_speed
330 * - Used: @c bkpinfo->include_paths
331 * - Used: @c bkpinfo->prefix
332 * - Used: @c bkpinfo->isodir
333 * - Used: @c bkpinfo->manual_tray
334 * - Used: @c bkpinfo->make_cd_use_lilo
335 * - Used: @c bkpinfo->media_device
336 * - Used: @c bkpinfo->nfs_mount
337 * - Used: @c bkpinfo->nonbootable_backup
338 * - Used: @c bkpinfo->scratchdir
339 * - Used: @c bkpinfo->tmpdir
340 * - Modified: @c bkpinfo->call_before_iso
341 * - Modified: @c bkpinfo->call_make_iso
342 * - Modified: @c bkpinfo->optimal_set_size
343 *
344 * @return number of errors, or 0 for success.
345 * @note Also creates directories that are specified in the @c bkpinfo structure but
346 * do not exist.
347 */
348int post_param_configuration()
349{
350    char *extra_cdrom_params = NULL;
351    char *mondo_mkisofs_sz = NULL;
352    char *command = NULL;
353    char *hostname = NULL;
354    char *ip_address = NULL;
355    int retval = 0;
356    long avm = 0;
357    char *colon = NULL;
358    char *tmp = NULL;
359    char *call_before_iso_user = NULL;
360    int rdsiz_MB;
361    char *iso_dev = NULL;
362    char *iso_mnt = NULL;
363    char *iso_tmp = NULL;
364    char *iso_path = NULL;
365    FILE *fd1 = NULL;
366
367    assert(bkpinfo != NULL);
368    bkpinfo->optimal_set_size =
369        (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type) ? 16 : 16) *
370        1024;
371
372    mr_msg(1, "Foo");
373    if (bkpinfo->backup_media_type == tape) {
374        mr_msg(1, "Bar");
375        mr_asprintf(&tmp, "mt -f %s status", bkpinfo->media_device);
376        mr_msg(1, "tmp = '%s'", tmp);
377        if (run_program_and_log_output(tmp, 3)) {
378            fatal_error
379                ("Unable to open tape device. If you haven't specified it with -d, do so. If you already have, check your parameter. I think it's wrong.");
380        }
381        mr_free(tmp);
382    }
383    make_hole_for_dir(bkpinfo->scratchdir);
384    if (bkpinfo->backup_media_type == iso)
385        make_hole_for_dir(bkpinfo->isodir);
386
387    run_program_and_log_output("uname -a", 5);
388    run_program_and_log_output("cat /etc/*-release", 5);
389    sprintf(g_tmpfs_mountpt, "%s/tmpfs", bkpinfo->tmpdir);
390    mr_asprintf(&command, "mkdir -p %s", g_tmpfs_mountpt);
391    paranoid_system(command);
392    mr_free(command);
393    rdsiz_MB = PPCFG_RAMDISK_SIZE + g_tape_buffer_size_MB;
394#ifdef __FreeBSD__
395    mr_asprintf(&tmp,
396           call_program_and_get_last_line_of_output
397           ("vmstat | tail -1 | tr -s ' ' | cut -d' ' -f6"));
398    avm += atol(tmp);
399    mr_free(tmp);
400    mr_asprintf(&tmp,
401           call_program_and_get_last_line_of_output
402           ("swapinfo | grep -v Device | tr -s ' ' | cut -d' ' -f4 | tr '\n' '+' | sed 's/+$//' | bc"));
403    avm += atol(tmp);
404    mr_free(tmp);
405    mr_asprintf(&command, "mdmfs -s %d%c md9 %s", rdsiz_MB, 'm',
406             g_tmpfs_mountpt);
407#else
408    mr_asprintf(&tmp,
409           call_program_and_get_last_line_of_output
410           ("free | grep ':' | tr -s ' ' '\t' | cut -f2 | head -n1"));
411    avm += atol(tmp);
412    mr_free(tmp);
413    mr_asprintf(&command, "mount /dev/shm -t tmpfs %s -o size=%d%c",
414            g_tmpfs_mountpt, rdsiz_MB, 'm');
415    run_program_and_log_output("cat /proc/cpuinfo", 5);
416    /* BERLIOS: rpm is not necessarily there ! */
417    run_program_and_log_output
418        ("rpm -q newt newt-devel slang slang-devel ncurses ncurses-devel gcc",
419         5);
420#endif
421    if (avm / 1024 > rdsiz_MB * 3) {
422        if (run_program_and_log_output(command, 5)) {
423            g_tmpfs_mountpt[0] = '\0';
424            log_it("Failed to mount tmpfs");
425        } else {
426            log_it("Tmpfs mounted OK - %d MB", rdsiz_MB);
427        }
428    } else {
429        g_tmpfs_mountpt[0] = '\0';
430        log_it("It doesn't seem you have enough swap to use tmpfs. Fine.");
431    }
432    mr_free(command);
433
434// CD-R or CD-RW or DVD
435    if (bkpinfo->backup_media_type == cdrw
436        || bkpinfo->backup_media_type == dvd
437        || bkpinfo->backup_media_type == iso
438        || bkpinfo->backup_media_type == nfs
439        || bkpinfo->backup_media_type == cdr) {
440        if (!bkpinfo->manual_tray) {
441            mr_strcat(extra_cdrom_params, "-waiti ");
442        }
443        if (bkpinfo->backup_media_type == cdrw) {
444            mr_strcat(extra_cdrom_params, "blank=fast ");
445        }
446        if (bkpinfo->nonbootable_backup) {
447            mr_asprintf(&mondo_mkisofs_sz, "%s -no-boot", mr_conf->iso_creation_opt);
448        } else if
449#ifdef __FreeBSD__
450            (TRUE)
451#else
452            (bkpinfo->make_cd_use_lilo)
453#endif
454#ifdef __IA64__
455    {
456        mr_asprintf(&mondo_mkisofs_sz, "%s -b images/mindi-boot.2880.img -c boot.cat", mr_conf->iso_creation_opt);
457    }
458#else
459    {
460        mr_asprintf(&mondo_mkisofs_sz, "%s -b isolinux.bin -c boot.cat", mr_conf->iso_creation_opt);
461    }
462#endif
463        else {
464            mr_asprintf(&mondo_mkisofs_sz, "%s -b isolinux.bin -c boot.cat", mr_conf->iso_creation_opt);
465        }
466        if (bkpinfo->manual_tray) {
467            if (strstr(mr_conf->iso_burning_cmd,"growisofs") != NULL) {
468                fatal_error("Unable to use manual CD tray with growisofs");
469            }
470            if (bkpinfo->call_before_iso[0] == '\0') {
471                sprintf(bkpinfo->call_before_iso,
472                        "%s %s -o %s/"MONDO_TMPISOS" . 2>> %s",
473                        mr_conf->iso_creation_cmd,mondo_mkisofs_sz, bkpinfo->tmpdir, MONDO_LOGFILE);
474            } else {
475                mr_asprintf(&call_before_iso_user, bkpinfo->call_before_iso);
476                sprintf (bkpinfo->call_before_iso,
477                                    "(%s %s -o %s/"MONDO_TMPISOS" . 2>> %s ; %s )",
478                        mr_conf->iso_creation_cmd,mondo_mkisofs_sz, bkpinfo->tmpdir, MONDO_LOGFILE, call_before_iso_user);
479                mr_free(call_before_iso_user);
480            }
481            log_it("bkpinfo->call_before_iso = %s", bkpinfo->call_before_iso);
482            sprintf(bkpinfo->call_make_iso,
483                    "%s %s %s dev=%s speed=%d %s/"MONDO_TMPISOS,
484                    mr_conf->iso_burning_cmd,
485                    extra_cdrom_params, 
486                    mr_conf->iso_burning_opt, 
487                    bkpinfo->iso_burning_dev,
488                    bkpinfo->writer_speed, 
489                    bkpinfo->tmpdir);
490        } else {
491            if (bkpinfo->backup_media_type == iso) {
492                sprintf(bkpinfo->call_make_iso,
493                    "%s %s . 2>> %s",
494                        mr_conf->iso_creation_cmd,
495                        mondo_mkisofs_sz, 
496                        MONDO_LOGFILE);
497            } else {
498                if (strstr(mr_conf->iso_burning_cmd,"growisofs") != NULL) {
499                    if (getenv ("SUDO_COMMAND")) {
500                        mr_asprintf(&command, "strings %s | grep -c SUDO_COMMAND", mr_conf->iso_burning_cmd);
501                        if (!strcmp(call_program_and_get_last_line_of_output(command), "1")) {
502                            fatal_error("Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
503                        }
504                        mr_free(command);
505                    }
506                    sprintf(bkpinfo->call_make_iso,
507                        "%s %s %s %s -Z %s -speed=%d . 2>> %s",
508                        mr_conf->iso_burning_cmd,
509                        mondo_mkisofs_sz, 
510                        extra_cdrom_params, 
511                        mr_conf->iso_burning_opt,
512                        bkpinfo->iso_burning_dev,
513                        bkpinfo->writer_speed,
514                        MONDO_LOGFILE);
515                } else {
516                    sprintf(bkpinfo->call_make_iso,
517                        "%s %s . 2>> %s | %s %s %s dev=%s speed=%d -",
518                        mr_conf->iso_creation_cmd,
519                        mondo_mkisofs_sz, 
520                        MONDO_LOGFILE,
521                        mr_conf->iso_burning_cmd,
522                        extra_cdrom_params, 
523                        mr_conf->iso_burning_opt,
524                        bkpinfo->iso_burning_dev,
525                        bkpinfo->writer_speed);
526                }
527            mr_free(mondo_mkisofs_sz);
528            mr_free(extra_cdrom_params);
529            }
530        }
531    }                           // end of CD code
532
533    if (bkpinfo->backup_media_type == iso) {
534
535/* Patch by Conor Daly <conor.daly@met.ie>
536 * 23-june-2004
537 * Break up isodir into iso_mnt and iso_path
538 * These will be used along with iso-dev at restore time
539 * to locate the ISOs where ever they're mounted
540 */
541
542        log_it("isodir = %s", bkpinfo->isodir);
543        mr_asprintf(&command, "df -P %s | tail -n1 | cut -d' ' -f1",
544                 bkpinfo->isodir);
545        log_it("command = %s", command);
546        mr_asprintf(&iso_dev, call_program_and_get_last_line_of_output(command));
547        mr_free(command);
548        log_it("res of it = %s", iso_dev);
549
550        fd1 = mr_fopen(MONDORESTORECFG, "a");
551        mr_fprintf(fd1, "iso-dev=%s\n", iso_dev);
552
553        mr_asprintf(&command, "mount | grep -w %s | tail -n1 | cut -d' ' -f3",
554                 iso_dev);
555        mr_free(iso_dev);
556
557        log_it("command = %s", command);
558        mr_asprintf(&iso_mnt,call_program_and_get_last_line_of_output(command));
559        mr_free(command);
560
561        log_it("res of it = %s", iso_mnt);
562        mr_fprintf(fd1, "iso-mnt=%s\n", iso_mnt);
563        log_it("isomnt: %s, %d", iso_mnt, strlen(iso_mnt));
564
565        mr_asprintf(&iso_tmp, "%s", bkpinfo->isodir);
566        if (strlen(iso_tmp) >= strlen(iso_mnt)) {
567            mr_asprintf(&iso_path, "%s", iso_tmp + strlen(iso_mnt));
568        } else {
569            mr_asprintf(&iso_path, "");
570        }
571        mr_free(iso_tmp);
572        mr_free(iso_mnt);
573
574        log_it("isodir: %s", iso_path);
575        mr_fprintf(fd1, "isodir=%s\n", iso_path);
576        mr_free(iso_path);
577
578        log_it("iso-prefix: %s",  bkpinfo->prefix);
579        mr_fprintf(fd1, "iso-prefix=%s\n", bkpinfo->prefix);
580
581        mr_fclose(fd1);
582    }                           // end of iso code
583
584    if (bkpinfo->backup_media_type == nfs) {
585        mr_asprintf(&hostname, bkpinfo->nfs_mount);
586        colon = strchr(hostname, ':');
587        if (!colon) {
588            log_it("nfs mount doesn't have a colon in it");
589            retval++;
590        } else {
591            struct hostent *hent;
592
593            *colon = '\0';
594            hent = gethostbyname(hostname);
595            if (!hent) {
596                log_it("Can't resolve NFS mount (%s): %s", hostname,
597                       hstrerror(h_errno));
598                retval++;
599            } else {
600                mr_asprintf(&ip_address, "%s%s", inet_ntoa((struct in_addr)
601                                                *((struct in_addr *) hent->h_addr)),
602                                                strchr(bkpinfo->nfs_mount, ':'));
603                strcpy(bkpinfo->nfs_mount, ip_address);
604                mr_free(ip_address);
605            }
606        }
607        store_nfs_config();
608        mr_free(hostname);
609    }
610
611    log_it("Finished processing incoming params");
612    if (retval) {
613        fprintf(stderr, "Type 'man mondoarchive' for help.\n");
614    }
615
616    if (strlen(bkpinfo->tmpdir) < 2 || strlen(bkpinfo->scratchdir) < 2) {
617        log_it("tmpdir or scratchdir are blank/missing");
618        retval++;
619    }
620    if (bkpinfo->include_paths[0] == '\0') {
621        //      fatal_error ("Why no backup path?");
622        strcpy(bkpinfo->include_paths, "/");
623    }
624    chmod(bkpinfo->scratchdir, 0700);
625    g_backup_media_type = bkpinfo->backup_media_type;
626    g_backup_media_string = bkpinfo->backup_media_string;
627    return (retval);
628}
629
630
631/**
632 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
633 * Seeds the random-number generator, loads important modules, checks the sanity
634 * of the user's Linux distribution, and deletes logfile.
635 * @param bkpinfo The backup information structure. Will be initialized.
636 * @return number of errors (0 for success)
637 */
638int pre_param_configuration()
639{
640    int res = 0;
641    char *tmp = NULL;
642
643    make_hole_for_dir(MNT_CDROM);
644    assert(bkpinfo != NULL);
645    srandom((unsigned long) (time(NULL)));
646    insmod_crucial_modules();
647    if (bkpinfo->disaster_recovery) {
648        if (!does_nonMS_partition_exist()) {
649            fatal_error
650                ("I am in disaster recovery mode\nPlease don't run mondoarchive.");
651        }
652    }
653
654    asprintf(&tmp,"rm -Rf %s/changed.files*",MONDO_CACHE);
655    run_program_and_log_output(tmp, FALSE);
656    paranoid_free(tmp);
657    res += some_basic_system_sanity_checks();
658    if (res) {
659        log_it("Your distribution did not pass Mondo's sanity test.");
660    }
661    g_current_media_number = 1;
662    bkpinfo->postnuke_tarball[0] = bkpinfo->nfs_mount[0] = '\0';
663    return (res);
664}
665
666void setup_tmpdir(char *path) {
667   
668    char *tmp = NULL;
669    char *p = NULL;
670
671    if (bkpinfo->tmpdir != NULL) {
672        /* purging a potential old tmpdir */
673        asprintf(&tmp,"rm -Rf %s",bkpinfo->tmpdir);
674        system(tmp);
675        paranoid_free(tmp);
676    }
677       
678    if (path != NULL) {
679        asprintf(&tmp, "%s/mondo.tmp.XXXXXX", path);
680    } else if (getenv("TMPDIR")) {
681        asprintf(&tmp, "%s/mondo.tmp.XXXXXX", getenv("TMPDIR"));
682    } else if (getenv("TMP")) {
683        asprintf(&tmp, "%s/mondo.tmp.XXXXXX", getenv("TMP"));
684    } else {
685        asprintf(&tmp, "/tmp/mondo.tmp.XXXXXX");
686    }
687    p = mkdtemp(tmp);
688    if (p == NULL) {
689        log_it("Failed to create global tmp directory %s for Mondo.",tmp);
690        finish(-1);
691    }
692    strcpy(bkpinfo->tmpdir,p);
693    paranoid_free(tmp);
694
695    //sprintf(bkpinfo->tmpdir, "%s/tmpfs/mondo.tmp.%d", "/tmp", (int) (random() % 32768));  // for mondorestore
696}
697
698
699/**
700 * Reset all fields of the backup information structure to a sensible default.
701 * @param bkpinfo The @c bkpinfo to reset.
702 */
703void reset_bkpinfo()
704{
705    char *tmp = NULL;
706
707    mr_msg(1, "Hi");
708
709    assert(bkpinfo != NULL);
710    /* BERLIOS : Useless ?? */
711    memset((void *) bkpinfo, 0, sizeof(struct s_bkpinfo));
712
713    /* special case for tmpdir as used eveywhere after */
714    setup_tmpdir(NULL);
715
716    bkpinfo->manual_tray = mr_conf->manual_tray;
717    bkpinfo->internal_tape_block_size = mr_conf->internal_tape_blocksize;
718    bkpinfo->compression_level = mr_conf->compression_level;
719    mr_asprintf(&tmp,mr_conf->compression_suffix);
720    bkpinfo->compression_suffix = tmp;
721    mr_asprintf(&tmp,mr_conf->compression_tool);
722    bkpinfo->compression_tool = tmp;
723    mr_asprintf(&tmp,mr_conf->media_device);
724    bkpinfo->media_device = tmp;
725    mr_asprintf(&tmp,mr_conf->iso_burning_dev);
726    bkpinfo->iso_burning_dev = tmp;
727
728    bkpinfo->media_size = mr_conf->iso_burning_speed;
729    mr_asprintf(&tmp,mr_conf->kernel);
730    bkpinfo->kernel_path = tmp;
731
732    if (strcmp(mr_conf->boot_loader,"LILO") == 0) {
733        bkpinfo->boot_loader = 'L';
734    } else if (strcmp(mr_conf->boot_loader,"GRUB") == 0) {
735        bkpinfo->boot_loader = 'G';
736    } else if (strcmp(mr_conf->boot_loader,"ELILO") == 0) {
737        bkpinfo->boot_loader = 'E';
738    } else if (strcmp(mr_conf->boot_loader,"RAW") == 0) {
739        bkpinfo->boot_loader = 'R';
740    } else if (strcmp(mr_conf->boot_loader,"DD") == 0) {
741        bkpinfo->boot_loader = 'D';
742    } else if (strcmp(mr_conf->boot_loader,"BOOT0") == 0) {
743        bkpinfo->boot_loader = 'B';
744    } else if (strcmp(mr_conf->boot_loader,"NATIVE") == 0) {
745        bkpinfo->boot_loader = '\0';
746    } else{
747        mr_msg("Boot Loader %s unknown\n",mr_conf->boot_loader);
748        fatal_error("Unknown Boot Loader in conf file");
749    }
750    bkpinfo->boot_device[0] = '\0';
751    bkpinfo->restore_path[0] = '\0';
752    bkpinfo->do_not_compress_these[0] = '\0';
753    bkpinfo->verify_data = FALSE;
754    bkpinfo->backup_data = FALSE;
755    bkpinfo->restore_data = FALSE;
756    bkpinfo->disaster_recovery =
757        (am_I_in_disaster_recovery_mode()? TRUE : FALSE);
758    if (bkpinfo->disaster_recovery) {
759        strcpy(bkpinfo->isodir, "/");
760    } else {
761        strcpy(bkpinfo->isodir, "/var/cache/mondo/iso");
762    }
763    mr_asprintf(&tmp,mr_conf->prefix);
764    bkpinfo->prefix = tmp;
765
766    bkpinfo->scratchdir[0] = '\0';
767    bkpinfo->make_filelist = TRUE;  // unless -J supplied to mondoarchive
768    bkpinfo->optimal_set_size = 0;
769    bkpinfo->backup_media_type = none;
770    bkpinfo->backup_media_string[0] = '\0';
771    strcpy(bkpinfo->include_paths, "/");
772    bkpinfo->exclude_paths[0] = '\0';
773    bkpinfo->call_before_iso[0] = '\0';
774    bkpinfo->call_make_iso[0] = '\0';
775    bkpinfo->call_after_iso[0] = '\0';
776    bkpinfo->image_devs[0] = '\0';
777    bkpinfo->postnuke_tarball[0] = '\0';
778    bkpinfo->nfs_mount[0] = '\0';
779    bkpinfo->nfs_remote_dir[0] = '\0';
780    bkpinfo->wipe_media_first = FALSE;
781    bkpinfo->differential = FALSE;
782    bkpinfo->writer_speed = mr_conf->iso_burning_speed;
783}
784
785
786/**
787 * Get the remaining free space (in MB) on @p partition.
788 * @param partition The partition to check free space on (either a device or a mountpoint).
789 * @return The free space on @p partition, in MB.
790 */
791long free_space_on_given_partition(char *partition)
792{
793    char *command = NULL;
794    char *out_sz = NULL;
795    long res = 0L;
796
797    assert_string_is_neither_NULL_nor_zerolength(partition);
798
799    mr_asprintf(&command, "df -m -P %s 1> /dev/null 2> /dev/null", partition);
800    if (system(command)) {
801        return (-1);
802    }                           // partition does not exist
803    mr_free(command);
804
805    mr_asprintf(&command, "df -m -P %s | tail -n1 | tr -s ' ' '\t' | cut -f4",
806            partition);
807    mr_asprintf(&out_sz, call_program_and_get_last_line_of_output(command));
808    mr_free(command);
809
810    if (strlen(out_sz) == 0) {
811        return (-1);
812    }                           // error within df, probably
813    res = atol(out_sz);
814    mr_free(out_sz);
815    return (res);
816}
817
818
819/**
820 * Check the user's system for sanity. Checks performed:
821 * - make sure user has enough RAM (32mb required, 64mb recommended)
822 * - make sure user has enough free space in @c /
823 * - check kernel for ramdisk support
824 * - make sure afio, cdrecord, bzip2, awk, md5sum, strings, mindi, and buffer exist
825 * - make sure CD-ROM is unmounted
826 * - make sure /etc/modules.conf exists
827 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
828 *
829 * @return number of problems with the user's setup (0 for success)
830 */
831int some_basic_system_sanity_checks()
832{
833
834    /*@ buffers ************ */
835    char *tmp = NULL;
836
837    /*@ int's *************** */
838    int retval = 0;
839
840    mvaddstr_and_log_it(g_currentY, 0,
841                        "Checking sanity of your Linux distribution");
842#ifndef __FreeBSD__
843    if (system("which mkfs.vfat 2> /dev/null 1> /dev/null")
844        && !system("which mkfs.msdos 2> /dev/null 1> /dev/null")) {
845        log_it
846            ("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
847        run_program_and_log_output
848            ("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
849    }
850    mr_asprintf(&tmp,
851           call_program_and_get_last_line_of_output
852           ("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2"));
853    if (atol(tmp) < 35000) {
854        retval++;
855        log_to_screen(_("You must have at least 32MB of RAM to use Mondo."));
856    }
857    if (atol(tmp) < 66000) {
858        log_to_screen
859            (_("WARNING! You have very little RAM. Please upgrade to 64MB or more."));
860    }
861    mr_free(tmp);
862#endif
863
864    Lres = free_space_on_given_partition(MONDO_CACHE);
865    log_it("Free space on given partition = %ld MB", Lres);
866
867    if (Lres < 50) {
868        fatal_error("Your "MONDO_CACHE" partition has <50MB free. Please adjust your partition table to something saner or make "MONDO_CACHE" a symbolic link"); 
869    }
870
871    if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
872        retval++;
873        log_to_screen
874            ("Unable to find " MKE2FS_OR_NEWFS " in system path.");
875        fatal_error
876            ("Please use \"su -\", not \"su\" to become root. OK? ...and please don't e-mail the mailing list or me about this. Just read the message. :)");
877    }
878#ifndef __FreeBSD__
879    if (run_program_and_log_output
880        ("grep ramdisk /proc/devices", FALSE)) {
881        if (!ask_me_yes_or_no
882            (_("Your kernel has no ramdisk support. That's mind-numbingly stupid but I'll allow it if you're planning to use a failsafe kernel. Are you?")))
883        {
884            //          retval++;
885            log_to_screen
886                (_("It looks as if your kernel lacks ramdisk and initrd support."));
887            log_to_screen
888                (_("I'll allow you to proceed but FYI, if I'm right, your kernel is broken."));
889        }
890    }
891#endif
892    retval += whine_if_not_found(mr_conf->iso_creation_cmd);
893    retval += whine_if_not_found(mr_conf->iso_burning_cmd);
894    retval += whine_if_not_found(MKE2FS_OR_NEWFS);
895    retval += whine_if_not_found(mr_conf->compresstion_tool);
896    retval += whine_if_not_found("gzip");
897    retval += whine_if_not_found("awk");
898    retval += whine_if_not_found("md5sum");
899    retval += whine_if_not_found("strings");
900    retval += whine_if_not_found("mindi");
901    retval += whine_if_not_found("buffer");
902
903    // abort if Windows partition but no ms-sys and parted
904    if (!run_program_and_log_output
905        ("mount | grep -w vfat | grep -vE \"/dev/fd|nexdisk\"", 0)
906        ||
907        !run_program_and_log_output
908        ("mount | grep -w dos | grep -vE \"/dev/fd|nexdisk\"", 0)) {
909        log_to_screen(_("I think you have a Windows 9x partition."));
910        retval += whine_if_not_found("parted");
911#ifndef __IA64__
912        /* IA64 always has one vfat partition for EFI even without Windows */
913        // retval +=
914        if (!find_home_of_exe("ms-sys")) {
915            log_to_screen("Please install ms-sys just in case.");
916        }
917#endif
918    }
919
920    if (!find_home_of_exe("cmp")) {
921        if (!find_home_of_exe("true")) {
922            whine_if_not_found("cmp");
923        } else {
924            log_to_screen
925                ("Your system lacks the 'cmp' binary. I'll create a dummy cmp for you.");
926            if (run_program_and_log_output
927                ("cp -f `which true` /usr/bin/cmp", 0)) {
928                fatal_error("Failed to create dummy 'cmp' file.");
929            }
930        }
931    }
932    run_program_and_log_output
933        ("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
934    mr_asprintf(&tmp,
935           call_program_and_get_last_line_of_output
936           ("mount | grep -E \"cdr(om|w)\""));
937    if (strcmp("", tmp)) {
938        if (strstr(tmp, "autofs")) {
939            log_to_screen
940                (_("Your CD-ROM is mounted via autofs. I therefore cannot tell"));
941            log_to_screen
942                (_("if a CD actually is inserted. If a CD is inserted, please"));
943            log_to_screen(_("eject it. Thank you."));
944            log_it
945                ("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
946        } else
947            if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
948            retval++;
949            fatal_error
950                ("Your CD-ROM drive is mounted. Please unmount it.");
951        }
952    }
953    mr_free(tmp);
954#ifndef __FreeBSD__
955    if (!does_file_exist("/etc/modules.conf")) {
956        if (does_file_exist("/etc/conf.modules")) {
957            log_it("Linking /etc/modules.conf to /etc/conf.modules");
958            run_program_and_log_output
959                ("ln -sf /etc/conf.modules /etc/modules.conf", 5);
960        } else if (does_file_exist("/etc/modprobe.d")) {
961            log_it
962                ("Directory /etc/modprobe.d found. mindi will use its contents.");
963        } else if (does_file_exist("/etc/modprobe.conf")) {
964            log_it("Linking /etc/modules.conf to /etc/modprobe.conf");
965            run_program_and_log_output
966                ("ln -sf /etc/modprobe.conf /etc/modules.conf", 5);
967        } else {
968            retval++;
969            log_to_screen
970                (_("Please find out what happened to /etc/modules.conf"));
971        }
972    }
973#endif
974
975    run_program_and_log_output("cat /etc/fstab", 5);
976#ifdef __FreeBSD__
977    run_program_and_log_output("vinum printconfig", 5);
978#else
979    run_program_and_log_output("cat /etc/raidtab", 5);
980#endif
981
982    if (run_program_and_log_output("mindi -V", 1)) {
983        log_to_screen(_("Could not ascertain mindi's version number."));
984        log_to_screen
985            (_("You have not installed Mondo and/or Mindi properly."));
986        log_to_screen(_("Please uninstall and reinstall them both."));
987        fatal_error("Please reinstall Mondo and Mindi.");
988    }
989    mr_asprintf(&tmp, "mindi --makemountlist %s/mountlist.txt.test", bkpinfo->tmpdir);
990    if (run_program_and_log_output(tmp, 5)) {
991        log_to_screen(tmp);
992        log_to_screen
993            (_("failed for some reason."));
994        log_to_screen
995            (_("Please run that command by hand and examine /var/log/mindi.log"));
996        log_to_screen
997            (_("for more information. Perhaps your /etc/fstab file is insane."));
998        log_to_screen
999            (_("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see."));
1000        retval++;
1001    }
1002    mr_free(tmp);
1003
1004    if (!run_program_and_log_output("parted2fdisk -l | grep -i raid", 1)
1005        && !does_file_exist("/etc/raidtab")) {
1006        log_to_screen
1007            (_("You have RAID partitions but no /etc/raidtab - creating one from "MDSTAT_FILE));
1008        create_raidtab_from_mdstat("/etc/raidtab");
1009    }
1010
1011    if (retval) {
1012        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1013    } else {
1014        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1015    }
1016    return (retval);
1017}
1018
1019/**
1020 * Retrieve the line containing @p label from the config file.
1021 * @param config_file The file to read from, usually @c /tmp/mondo-restore.cfg.
1022 * @param label What to read from the file.
1023 * @param value Where to put it.
1024 * @return 0 for success, 1 for failure.
1025 */
1026int read_cfg_var(char *config_file, char *label, char *value)
1027{
1028    /*@ buffer ****************************************************** */
1029    char *command = NULL;
1030    char *tmp = NULL;
1031
1032    /*@ end vars *************************************************** */
1033
1034    assert_string_is_neither_NULL_nor_zerolength(config_file);
1035    assert_string_is_neither_NULL_nor_zerolength(label);
1036
1037    if (!does_file_exist(config_file)) {
1038        mr_asprintf(&tmp, "(read_cfg_var) Cannot find %s config file",
1039                 config_file);
1040        log_to_screen(tmp);
1041        mr_free(tmp);
1042        value[0] = '\0';
1043        return (1);
1044    /* } BERLIOS: Useless:
1045         else if (strstr(value, "/dev/") && strstr(value, "t0")
1046               && !strcmp(label, "media-dev")) {
1047        mr_msg(2, "FYI, I shan't read new value for %s - already got %s",
1048                label, value);
1049        return (0);
1050    */ } else {
1051        mr_asprintf(&command, "grep '%s .*' %s| cut -d'=' -f2,3,4,5",
1052                label, config_file);
1053        strcpy(value, call_program_and_get_last_line_of_output(command));
1054        mr_free(command);
1055        if (strlen(value) == 0) {
1056            return (1);
1057        } else {
1058            return (0);
1059        }
1060    }
1061}
1062
1063
1064/**
1065 * Remount @c supermount if it was unmounted earlier.
1066 */
1067void remount_supermounts_if_necessary()
1068{
1069    if (g_remount_cdrom_at_end) {
1070        run_program_and_log_output("mount " MNT_CDROM, FALSE);
1071    }
1072}
1073
1074/**
1075 * Unmount @c supermount if it's mounted.
1076 */
1077void unmount_supermounts_if_necessary()
1078{
1079    if (run_program_and_log_output
1080        ("mount | grep cdrom | grep super", FALSE) == 0) {
1081        g_remount_cdrom_at_end = TRUE;
1082        run_program_and_log_output("umount " MNT_CDROM, FALSE);
1083    }
1084}
1085
1086/**
1087 * If this is a distribution like Gentoo that doesn't keep /boot mounted, mount it.
1088 */
1089void mount_boot_if_necessary()
1090{
1091    char *tmp = NULL;
1092    char *tmp1 = NULL;
1093    char *command = NULL;
1094
1095    mr_msg(1, "Started sub");
1096    mr_msg(4, "About to set g_boot_mountpt[0] to '\\0'");
1097    g_boot_mountpt[0] = '\0';
1098    mr_msg(4, "Done. Great. Setting command to something");
1099    mr_asprintf(&command,
1100             "grep -v ':' /etc/fstab | grep -vE '^#.*$' | grep -E \"[   ]/boot[     ]\" | tr -s ' ' '\t' | cut -f1 | head -n1");
1101    mr_msg(4, "Cool. Command = '%s'", command);
1102    mr_asprintf(&tmp, call_program_and_get_last_line_of_output(command));
1103    mr_free(command);
1104
1105    mr_msg(4, "tmp = '%s'", tmp);
1106    if (tmp[0]) {
1107        log_it("/boot is at %s according to /etc/fstab", tmp);
1108        if ((strstr(tmp, "LABEL=") || strstr(tmp,"UUID="))) {
1109            if (!run_program_and_log_output("mount /boot", 5)) {
1110                strcpy(g_boot_mountpt, "/boot");
1111                mr_msg(1, "Mounted /boot");
1112            } else {
1113                log_it("...ignored cos it's a label or uuid :-)");
1114            }
1115        } else {
1116            mr_asprintf(&command, "mount | grep -E '^%s'", tmp);
1117            mr_msg(3, "command = %s", command);
1118            if (run_program_and_log_output(command, 5)) {
1119                strcpy(g_boot_mountpt, tmp);
1120                mr_asprintf(&tmp1,
1121                        "%s (your /boot partition) is not mounted. I'll mount it before backing up",
1122                        g_boot_mountpt);
1123                log_it(tmp1);
1124                mr_free(tmp1);
1125
1126                mr_asprintf(&tmp1, "mount %s", g_boot_mountpt);
1127                if (run_program_and_log_output(tmp1, 5)) {
1128                    g_boot_mountpt[0] = '\0';
1129                    mr_msg(1, "Plan B");
1130                    if (!run_program_and_log_output("mount /boot", 5)) {
1131                        strcpy(g_boot_mountpt, "/boot");
1132                        mr_msg(1, "Plan B worked");
1133                    } else {
1134                        mr_msg(1,
1135                                "Plan B failed. Unable to mount /boot for backup purposes. This probably means /boot is mounted already, or doesn't have its own partition.");
1136                    }
1137                }
1138                mr_free(tmp1);
1139            }
1140            mr_free(command);
1141        }
1142    }
1143    mr_free(tmp);
1144    mr_msg(1, "Ended sub");
1145}
1146
1147
1148/**
1149 * If we mounted /boot earlier, unmount it.
1150 */
1151void unmount_boot_if_necessary()
1152{
1153    char *tmp;
1154
1155    mr_msg(3, "starting");
1156    if (g_boot_mountpt[0]) {
1157        mr_asprintf(&tmp, "umount %s", g_boot_mountpt);
1158        if (run_program_and_log_output(tmp, 5)) {
1159            log_it("WARNING - unable to unmount /boot");
1160        }
1161        mr_free(tmp);
1162    }
1163    mr_msg(3, "leaving");
1164}
1165
1166
1167/**
1168 * Write a line to a configuration file. Writes a line of the form,
1169 * @c label @c value.
1170 * @param config_file The file to write to. Usually @c mondo-restore.cfg.
1171 * @param label What to call this bit of data you're writing.
1172 * @param value The bit of data you're writing.
1173 * @return 0 for success, 1 for failure.
1174 */
1175int write_cfg_var(char *config_file, char *label, char *value)
1176{
1177    /*@ buffers ***************************************************** */
1178    char *command = NULL;
1179    char *tempfile = NULL;
1180    char *tmp = NULL;
1181
1182
1183    /*@ end vars *************************************************** */
1184    assert_string_is_neither_NULL_nor_zerolength(config_file);
1185    assert_string_is_neither_NULL_nor_zerolength(label);
1186    assert(value != NULL);
1187
1188    if (!does_file_exist(config_file)) {
1189        mr_asprintf(&tmp, "(write_cfg_file) Cannot find %s config file",
1190                 config_file);
1191        log_to_screen(tmp);
1192        mr_free(tmp);
1193        return (1);
1194    }
1195    mr_asprintf(&tempfile, "%s/mojo-jojo.blah", bkpinfo->tmpdir);
1196    if (does_file_exist(config_file)) {
1197        mr_asprintf(&command, "grep -vE '^%s .*$' %s > %s",
1198                label, config_file, tempfile);
1199        paranoid_system(command);
1200        mr_free(command);
1201    }
1202    mr_asprintf(&command, "echo \"%s %s\" >> %s", label, value, tempfile);
1203    paranoid_system(command);
1204    mr_free(command);
1205
1206    mr_asprintf(&command, "mv -f %s %s", tempfile, config_file);
1207    paranoid_system(command);
1208    mr_free(command);
1209    unlink(tempfile);
1210    mr_free(tempfile);
1211    return (0);
1212}
1213
1214
1215/**
1216 * Allocate or free important globals, depending on @p mal.
1217 * @param mal If TRUE, malloc; if FALSE, free.
1218 */
1219void do_libmondo_global_strings_thing(int mal)
1220{
1221    if (mal) {
1222        malloc_string(g_boot_mountpt);
1223        malloc_string(g_tmpfs_mountpt);
1224        malloc_string(g_serial_string);
1225        malloc_string(g_magicdev_command);
1226    } else {
1227        mr_free(g_boot_mountpt);
1228        mr_free(g_tmpfs_mountpt);
1229        mr_free(g_serial_string);
1230        mr_free(g_magicdev_command);
1231    }
1232}
1233
1234/**
1235 * Allocate important globals.
1236 * @see do_libmondo_global_strings_thing
1237 */
1238void malloc_libmondo_global_strings(void)
1239{
1240    do_libmondo_global_strings_thing(1);
1241}
1242
1243/**
1244 * Free important globals.
1245 * @see do_libmondo_global_strings_thing
1246 */
1247void free_libmondo_global_strings(void)
1248{
1249    do_libmondo_global_strings_thing(0);
1250}
1251
1252
1253
1254/**
1255 * Stop @c magicdev if it's running.
1256 * The command used to start it is saved in @p g_magicdev_command.
1257 */
1258void stop_magicdev_if_necessary()
1259{
1260    strcpy(g_magicdev_command,
1261           call_program_and_get_last_line_of_output
1262           ("ps ax | grep -w magicdev | grep -v grep | tr -s '\t' ' '| cut -d' ' -f6-99"));
1263    if (g_magicdev_command[0]) {
1264        mr_msg(1, "g_magicdev_command = '%s'", g_magicdev_command);
1265        paranoid_system("killall magicdev");
1266    }
1267}
1268
1269
1270/**
1271 * Restart magicdev if it was stopped.
1272 */
1273void restart_magicdev_if_necessary()
1274{
1275    char *tmp = NULL;
1276
1277    if (g_magicdev_command && g_magicdev_command[0]) {
1278        mr_asprintf(&tmp, "%s &", g_magicdev_command);
1279        paranoid_system(tmp);
1280        mr_free(tmp);
1281    }
1282}
1283
1284/* @} - end of utilityGroup */
Note: See TracBrowser for help on using the repository browser.