source: trunk/mondo/mondo/common/libmondo-tools.c @ 75

Last change on this file since 75 was 75, checked in by andree, 14 years ago

Various changes to get archiving to NFS work in interactive mode. It
wasn't really like were were bugs, it appeared more like it was simply
not finished.

Side note: I believe that bkpinfo->isodir and bkpinfo->prefix were the
wrong way round in libmondo-archive.c and I've swapped them.

  • Property svn:keywords set to Id
File size: 40.9 KB
Line 
1/* $Id: libmondo-tools.c 75 2005-10-20 12:35:15Z andree $
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 "mondostructures.h"
12#include "lib-common-externs.h"
13#include "libmondo-tools.h"
14#include "libmondo-gui-EXT.h"
15#include "libmondo-files-EXT.h"
16#include "libmondo-fork-EXT.h"
17#include "libmondo-raid-EXT.h"
18#include <sys/socket.h>
19#include <netdb.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22
23/*@unused@*/
24//static char cvsid[] = "$Id: libmondo-tools.c 75 2005-10-20 12:35:15Z andree $";
25
26extern int g_tape_buffer_size_MB;
27extern char *g_erase_tmpdir_and_scratchdir;
28extern char *g_serial_string;
29extern bool g_text_mode;
30extern int g_currentY;
31extern int g_current_media_number;
32
33/**
34 * @addtogroup globalGroup
35 * @{
36 */
37bool g_remount_cdrom_at_end,    ///< TRUE if we unmounted the CD-ROM and should remount it when done with the backup.
38 g_remount_floppy_at_end;       ///< TRUE if we unmounted the floppy and should remount it when done with the backup.
39bool g_cd_recovery;             ///< TRUE if we're making an "autonuke" backup.
40double g_kernel_version;
41
42/**
43 * The place where /boot is mounted.
44 */
45char *g_boot_mountpt = NULL;
46
47/**
48 * The location of Mondo's home directory.
49 */
50char *g_mondo_home = NULL;
51
52/**
53 * The serial string (used to differentiate between backups) of the current backup.
54 */
55char *g_serial_string = NULL;
56
57/**
58 * The location where tmpfs is mounted, or "" if it's not mounted.
59 */
60char *g_tmpfs_mountpt = NULL;
61char *g_magicdev_command = NULL;
62
63/**
64 * The default maximum level to log messages at or below.
65 */
66int g_loglevel = DEFAULT_DEBUG_LEVEL;
67
68/* @} - end of globalGroup */
69
70
71extern pid_t g_buffer_pid;
72extern pid_t g_main_pid;
73
74extern t_bkptype g_backup_media_type;
75
76extern bool am_I_in_disaster_recovery_mode(void);
77
78
79/**
80 * @addtogroup utilityGroup
81 * @{
82 */
83/**
84 * Assertion handler. Prints a friendly message to the user,
85 * offering to ignore all, dump core, break to debugger,
86 * exit, or ignore. Intended to be used with an assert() macro.
87 *
88 * @param file The file in which the assertion triggered.
89 * @param function The function (@c __FUNCTION__) in which the assertion triggered.
90 * @param line The line number of the assert() statement.
91 * @param exp The expression that failed (as a string).
92 */
93void _mondo_assert_fail(const char *file,
94                        const char *function, int line, const char *exp)
95{
96    static int ignoring_assertions = 0;
97    bool is_valid = TRUE;
98
99    log_it("ASSERTION FAILED: `%s' at %s:%d in %s", exp, file, line,
100           function);
101    if (ignoring_assertions) {
102        log_it("Well, the user doesn't care...");
103        return;
104    }
105#ifndef _XWIN
106    if (!g_text_mode)
107        newtSuspend();
108#endif
109    printf("ASSERTION FAILED: `%s'\n", exp);
110    printf("\tat %s:%d in %s\n\n", file, line, function);
111    printf("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
112    do {
113        is_valid = TRUE;
114        switch (toupper(getchar())) {
115        case 'A':               // ignore (A)ll
116            ignoring_assertions = 1;
117            break;
118        case 'B':               // a(B)ort
119            signal(SIGABRT, SIG_DFL);   /* prevent SIGABRT handler from running */
120            raise(SIGABRT);
121            break;              /* "can't get here" */
122        case 'D':               // (D)ebug, aka asm("int 3")
123#ifdef __IA32__
124            __asm__ __volatile__("int $3"); // break to debugger
125#endif
126            break;
127        case 'E':               // (E)xit
128            fatal_error("Failed assertion -- see above for details");
129            break;              /* "can't get here" */
130        case 'I':               // (I)gnore
131            break;
132            /* These next two work as follows:
133               the `default' catches the user's invalid choice and says so;
134               the '\n' catches the newline on the end and prints the prompt again.
135             */
136        case '\n':
137            printf
138                ("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
139            break;
140        default:
141            is_valid = FALSE;
142            printf("Invalid choice.\n");
143            break;
144        }
145    } while (!is_valid);
146
147    if (ignoring_assertions) {
148        log_it("Ignoring ALL assertions from now on.");
149    } else {
150        log_it("Ignoring assertion: %s", exp);
151    }
152
153    getchar();                  // skip \n
154
155#ifndef _XWIN
156    if (!g_text_mode)
157        newtResume();
158#endif
159}
160
161/**
162 * Clean's up users' KDE desktops.
163 * @bug Details about this function are unknown.
164 */
165void clean_up_KDE_desktop_if_necessary(void)
166{
167    char *tmp;
168
169    malloc_string(tmp);
170    strcpy(tmp,
171           "for i in `find /root /home -type d -name Desktop -maxdepth 2`; do \
172file=$i/.directory; if [ -f \"$file\" ] ; then mv -f $file $file.old ; \
173cat $file.old | awk '{if (index($0, \"rootimagesmindi\")) { while (length($0)>2) { getline;} ; } \
174else { print $0;};}' > $file ; fi ; done");
175    run_program_and_log_output(tmp, 5);
176    paranoid_free(tmp);
177}
178
179
180/**
181 * Locate mondoarchive's home directory. Searches in /usr/local/mondo, /usr/share/mondo,
182 * /usr/local/share/mondo, /opt, or if all else fails, search /usr.
183 *
184 * @param home_sz String to store the home directory ("" if it could not be found).
185 * @return 0 for success, nonzero for failure.
186 */
187int find_and_store_mondoarchives_home(char *home_sz)
188{
189    assert(home_sz != NULL);
190    strcpy(home_sz,
191           call_program_and_get_last_line_of_output
192           ("find /usr/lib/ /usr/local/ /usr/share/ /usr/local/share/ /opt/ /ramdisk/usr/share/ -type d -maxdepth 2 -name include -prune -o -type d -maxdepth 2 -path '*/mondo/restore-scripts' -printf '%h\n' 2> /dev/null"));
193
194    if (home_sz[0] == '\0') {
195        strcpy(home_sz,
196               call_program_and_get_last_line_of_output
197               ("find /usr -type d -path '*/mondo/restore-scripts' -follow -maxdepth 3 -printf '%h\n' 2> /dev/null"));
198    }
199    if (home_sz[0] == '\0') {
200        return (1);
201    } else {
202        return (0);
203    }
204}
205
206
207char *get_architecture()
208{
209#ifdef __IA32__
210    return ("i386");
211#endif
212#ifdef __IA64__
213    return ("ia64");
214#endif
215    return ("unknown");
216}
217
218
219
220double get_kernel_version()
221{
222    char *p, tmp[200];
223    double d;
224#ifdef __FreeBSD__
225    // JOSH - FIXME :)
226    d = 5.2;                    // :-)
227#else
228    strcpy(tmp, call_program_and_get_last_line_of_output("uname -r"));
229    p = strchr(tmp, '.');
230    if (p) {
231        p = strchr(++p, '.');
232        if (p) {
233            while (*p) {
234                *p = *(p + 1);
235                p++;
236            }
237        }
238    }
239//  log_msg(1, "tmp = '%s'", tmp);
240    d = atof(tmp);
241#endif
242    log_msg(1, "g_kernel_version = %f", d);
243    return (d);
244}
245
246
247
248
249
250/**
251 * Get the current time.
252 * @return number of seconds since the epoch.
253 */
254long get_time()
255{
256
257#if 0
258
259    /*@ pointers **************************************************** */
260    FILE *fin;
261
262    /*@ buffers ***************************************************** */
263    char incoming[MAX_STR_LEN];
264
265    /*@ end vars **************************************************** */
266
267    if (!(fin = popen("date +%s", "r"))) {
268        log_OS_error("Cannot popen date");
269        return (0);
270    }
271    fgets(incoming, MAX_STR_LEN - 1, fin);
272    paranoid_pclose(fin);
273    return (atol(incoming));
274#else
275    return (long) time((void *) 0);
276#endif
277}
278
279
280
281
282
283
284
285/**
286 * Initialize a RAID volume structure, setting fields to zero. The
287 * actual hard drive is unaffected.
288 *
289 * @param raidrec The RAID volume structure to initialize.
290 * @note This function is system dependent.
291 */
292#ifdef __FreeBSD__
293void initialize_raidrec(struct vinum_volume *raidrec)
294{
295    int i, j;
296    raidrec->volname[0] = '\0';
297    raidrec->plexes = 0;
298    for (i = 0; i < 9; ++i) {
299        raidrec->plex[i].raidlevel = -1;
300        raidrec->plex[i].stripesize = 0;
301        raidrec->plex[i].subdisks = 0;
302        for (j = 0; j < 9; ++j) {
303            strcpy(raidrec->plex[i].sd[j].which_device, "");
304        }
305    }
306}
307#else
308void initialize_raidrec(struct raid_device_record *raidrec)
309{
310    assert(raidrec != NULL);
311    raidrec->raid_device[0] = '\0';
312    raidrec->raid_level = 0;
313    raidrec->chunk_size = 4;
314    raidrec->persistent_superblock = 1;
315    raidrec->data_disks.entries = 0;
316    raidrec->spare_disks.entries = 0;
317    raidrec->parity_disks.entries = 0;
318    raidrec->failed_disks.entries = 0;
319    raidrec->additional_vars.entries = 0;
320}
321#endif
322
323
324
325
326/**
327 * Insert modules that Mondo requires.
328 * Currently inserts @c dos, @c fat, @c vfat, and @c osst for Linux;
329 * @c msdosfs and @c ext2fs for FreeBSD.
330 */
331void insmod_crucial_modules(void)
332{
333#ifdef __FreeBSD__
334    system("kldstat | grep msdosfs || kldload msdosfs 2> /dev/null");
335    system("kldstat | grep ext2fs  || kldload ext2fs 2> /dev/null");
336#else
337    system("modprobe dos &> /dev/null");
338    system("modprobe fat &> /dev/null");
339    system("modprobe vfat &> /dev/null");
340    //  system("modprobe osst &> /dev/null");
341#endif
342}
343
344
345/**
346 * Log a trace message to the trace file.
347 * @bug This function seems orphaned. Please remove.
348 */
349void log_trace(char *o)
350{
351    /*@ pointers **************************************************** */
352    FILE *fout;
353
354    /*@ buffers ***************************************************** */
355    char output[MAX_STR_LEN];
356
357    /*@ int    ****************************************************** */
358    int i;
359
360    /*@ end vars *************************************************** */
361
362    if (o[0] == '\0') {
363        return;
364    }
365    strcpy(output, o);
366    i = (int) strlen(output);
367    if (i <= 0) {
368        return;
369    }
370    if (output[i - 1] < 32) {
371        output[i - 1] = '\0';
372    }
373    if (g_text_mode
374        /* && !strstr(last_line_of_file(MONDO_LOGFILE),output) */ ) {
375        printf("%s\n", output);
376    }
377
378    fout = fopen(MONDO_TRACEFILE, "a");
379    if (fout) {
380        fprintf(fout, "%s\n", output);
381        paranoid_fclose(fout);
382    } else {
383        log_OS_error("Cannot write to tracefile");
384    }
385}
386
387
388
389
390
391/**
392 * Finish configuring the backup information structure. Call this function
393 * to set the parameters that depend on those that can be given on the command
394 * line.
395 *
396 * @param bkpinfo The backup information structure. Fields modified/used:
397 * - Used: @c bkpinfo->backup_data
398 * - Used: @c bkpinfo->backup_media_type
399 * - Used: @c bkpinfo->cdrw_speed
400 * - Used: @c bkpinfo->compression_level
401 * - Used: @c bkpinfo->include_paths
402 * - Used: @c bkpinfo->prefix
403 * - Used: @c bkpinfo->isodir
404 * - Used: @c bkpinfo->manual_cd_tray
405 * - Used: @c bkpinfo->make_cd_use_lilo
406 * - Used: @c bkpinfo->media_device
407 * - Used: @c bkpinfo->nfs_mount
408 * - Used: @c bkpinfo->nonbootable_backup
409 * - Used: @c bkpinfo->scratchdir
410 * - Used: @c bkpinfo->tmpdir
411 * - Used: @c bkpinfo->use_lzo
412 * - Modified: @c bkpinfo->call_before_iso
413 * - Modified: @c bkpinfo->call_make_iso
414 * - Modified: @c bkpinfo->optimal_set_size
415 * - Modified: @c bkpinfo->zip_exe
416 * - Modified: @c bkpinfo->zip_suffix
417 *
418 * @return number of errors, or 0 for success.
419 * @note Also creates directories that are specified in the @c bkpinfo structure but
420 * do not exist.
421 */
422int post_param_configuration(struct s_bkpinfo *bkpinfo)
423{
424    char *extra_cdrom_params;
425    char *mondo_mkisofs_sz;
426    char *command;
427    char *mtpt;
428    char *hostname, *ip_address;
429    int retval = 0;
430    long avm = 0;
431    char *colon;
432    char *cdr_exe;
433    char *tmp;
434    int rdsiz_MB;
435    char *iso_dev;
436    char *iso_mnt;
437    char *iso_tmp;
438    char *iso_path;
439
440    assert(bkpinfo != NULL);
441    malloc_string(extra_cdrom_params);
442    malloc_string(mondo_mkisofs_sz);
443    malloc_string(command);
444    malloc_string(mtpt);
445    malloc_string(hostname);
446    malloc_string(ip_address);
447    malloc_string(cdr_exe);
448    malloc_string(tmp);
449    malloc_string(iso_dev);
450    malloc_string(iso_mnt);
451    malloc_string(iso_tmp);
452    malloc_string(iso_path);
453    bkpinfo->optimal_set_size =
454        (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type) ? 4 : 8) *
455        1024;
456
457    log_msg(1, "Foo");
458    if (bkpinfo->backup_media_type == tape) {
459        log_msg(1, "Bar");
460        sprintf(tmp, "mt -f %s status", bkpinfo->media_device);
461        log_msg(1, "tmp = '%s'", tmp);
462        if (run_program_and_log_output(tmp, 3)) {
463            fatal_error
464                ("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.");
465        }
466    }
467    make_hole_for_dir(bkpinfo->scratchdir);
468    make_hole_for_dir(bkpinfo->tmpdir);
469    if (bkpinfo->backup_media_type == iso)
470        make_hole_for_dir(bkpinfo->isodir);
471
472    run_program_and_log_output("uname -a", 5);
473    run_program_and_log_output("cat /etc/*issue*", 5);
474    sprintf(g_tmpfs_mountpt, "%s/tmpfs", bkpinfo->tmpdir);
475    sprintf(command, "mkdir -p %s", g_tmpfs_mountpt);
476    paranoid_system(command);
477    rdsiz_MB = PPCFG_RAMDISK_SIZE + g_tape_buffer_size_MB;
478#ifdef __FreeBSD__
479    strcpy(tmp,
480           call_program_and_get_last_line_of_output
481           ("vmstat | tail -1 | tr -s ' ' | cut -d' ' -f6"));
482    avm += atol(tmp);
483    strcpy(tmp,
484           call_program_and_get_last_line_of_output
485           ("swapinfo | grep -v Device | tr -s ' ' | cut -d' ' -f4 | tr '\n' '+' | sed 's/+$//' | bc"));
486    avm += atol(tmp);
487    sprintf(command, "mdmfs -s %d%c md9 %s", rdsiz_MB, 'm',
488            g_tmpfs_mountpt);
489#else
490    strcpy(tmp,
491           call_program_and_get_last_line_of_output
492           ("free | grep \":\" | tr -s ' ' '\t' | cut -f2 | head -n1"));
493    avm += atol(tmp);
494    sprintf(command, "mount /dev/shm -t tmpfs %s -o size=%d%c",
495            g_tmpfs_mountpt, rdsiz_MB, 'm');
496    run_program_and_log_output("cat /proc/cpuinfo", 5);
497    run_program_and_log_output
498        ("rpm -q newt newt-devel slang slang-devel ncurses ncurses-devel gcc",
499         5);
500#endif
501    if (avm / 1024 > rdsiz_MB * 3) {
502        if (run_program_and_log_output(command, 5)) {
503            g_tmpfs_mountpt[0] = '\0';
504            log_it("Failed to mount tmpfs");
505        } else {
506            log_it("Tmpfs mounted OK - %d MB", rdsiz_MB);
507        }
508    } else {
509        g_tmpfs_mountpt[0] = '\0';
510        log_it("It doesn't seem you have enough swap to use tmpfs. Fine.");
511    }
512
513    if (bkpinfo->use_lzo) {
514        strcpy(bkpinfo->zip_exe, "lzop");
515        strcpy(bkpinfo->zip_suffix, "lzo");
516    } else if (bkpinfo->compression_level != 0) {
517        strcpy(bkpinfo->zip_exe, "bzip2");
518        strcpy(bkpinfo->zip_suffix, "bz2");
519    } else {
520        bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
521    }
522
523// DVD
524
525    if (bkpinfo->backup_media_type == dvd) {
526        extra_cdrom_params[0] = '\0';
527        mondo_mkisofs_sz[0] = '\0';
528        if (find_home_of_exe("growisofs")) {
529            strcpy(cdr_exe, "growisofs");
530        }                       // unlikely to be used
531        else {
532            fatal_error("Please install growisofs.");
533        }
534        if (bkpinfo->nonbootable_backup) {
535            strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_NONBOOT);
536        } else if
537#ifdef __FreeBSD__
538            (TRUE)
539#else
540            (bkpinfo->make_cd_use_lilo)
541#endif
542#ifdef __IA64__
543    {
544        strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_ELILO);
545    }
546#else
547    {
548        strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_LILO);
549    }
550#endif
551        else
552        {
553            strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_SYSLINUX);
554        }
555        if (bkpinfo->manual_cd_tray) {
556            fatal_error("Manual CD tray + DVD not supported yet.");
557            // -m isn't supported by growisofs, BTW...
558        } else {
559            sprintf(bkpinfo->call_make_iso,
560                    "%s %s -Z %s . 2>> _ERR_",
561                    mondo_mkisofs_sz,
562                    extra_cdrom_params, bkpinfo->media_device);
563        }
564        if (getenv ("SUDO_COMMAND")) {
565          fatal_error("Can't write DVDs as sudo because growisofs doesn't support this - please see the growisofs manpage for details.");
566        }
567        log_msg(2, "call_make_iso (DVD res) is ... %s",
568                bkpinfo->call_make_iso);
569    }                           // end of DVD code
570
571// CD-R or CD-RW
572    if (bkpinfo->backup_media_type == cdrw
573        || bkpinfo->backup_media_type == cdr) {
574        extra_cdrom_params[0] = '\0';
575        if (!bkpinfo->manual_cd_tray) {
576            strcat(extra_cdrom_params, "-waiti ");
577        }
578        if (bkpinfo->backup_media_type == cdrw) {
579            strcat(extra_cdrom_params, "blank=fast ");
580        }
581        if (find_home_of_exe("cdrecord")) {
582            strcpy(cdr_exe, "cdrecord");
583        } else if (find_home_of_exe("dvdrecord")) {
584            strcpy(cdr_exe, "dvdrecord");
585        } else {
586            fatal_error("Please install either cdrecord or dvdrecord.");
587        }
588        if (bkpinfo->nonbootable_backup) {
589            strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_NONBOOT);
590        } else if
591#ifdef __FreeBSD__
592            (TRUE)
593#else
594            (bkpinfo->make_cd_use_lilo)
595#endif
596#ifdef __IA64__
597    {
598        strcat(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_ELILO);
599    }
600#else
601    {
602        strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_LILO);
603    }
604#endif
605        else
606        {
607            strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_SYSLINUX);
608        }
609        if (bkpinfo->manual_cd_tray) {
610            sprintf(bkpinfo->call_before_iso,
611                    "%s -o %s/temporary.iso . 2>> _ERR_", mondo_mkisofs_sz,
612                    bkpinfo->tmpdir);
613            sprintf(bkpinfo->call_make_iso,
614                    "%s %s -v %s fs=4m dev=%s speed=%d %s/temporary.iso",
615                    cdr_exe, (bkpinfo->please_dont_eject) ? " " : "-eject",
616                    extra_cdrom_params, bkpinfo->media_device,
617                    bkpinfo->cdrw_speed, bkpinfo->tmpdir);
618        } else {
619            sprintf(bkpinfo->call_make_iso,
620                    "%s . 2>> _ERR_ | %s %s %s fs=4m dev=%s speed=%d -",
621                    mondo_mkisofs_sz, cdr_exe,
622                    (bkpinfo->please_dont_eject) ? " " : "-eject",
623                    extra_cdrom_params, bkpinfo->media_device,
624                    bkpinfo->cdrw_speed);
625        }
626    }                           // end of CD code
627
628    /*
629       if (bkpinfo->backup_data && bkpinfo->backup_media_type == tape)
630       {
631       sprintf (tmp,
632       "dd if=/dev/zero of=%s bs=%ld count=32 2> /dev/null",
633       bkpinfo->media_device, bkpinfo->internal_tape_block_size);
634       if (system(tmp))
635       {
636       retval++;
637       fprintf (stderr,
638       "Cannot write to tape device. Is the tape set read-only?\n");
639       }
640       } // end of tape code
641     */
642
643
644    if (bkpinfo->backup_media_type == iso) {
645
646/* Patch by Conor Daly <conor.daly@met.ie>
647 * 23-june-2004
648 * Break up isodir into iso_mnt and iso_path
649 * These will be used along with iso-dev at restore time
650 * to locate the ISOs where ever they're mounted
651 */
652
653        log_it("isodir = %s", bkpinfo->isodir);
654        sprintf(command, "df %s | tail -n1 | cut -d' ' -f1",
655                bkpinfo->isodir);
656        log_it("command = %s", command);
657        log_it("res of it = %s",
658               call_program_and_get_last_line_of_output(command));
659        sprintf(iso_dev, "%s",
660                call_program_and_get_last_line_of_output(command));
661        sprintf(tmp, "%s/ISO-DEV", bkpinfo->tmpdir);
662        write_one_liner_data_file(tmp,
663                                  call_program_and_get_last_line_of_output
664                                  (command));
665
666        sprintf(command, "mount | grep -w %s | tail -n1 | cut -d' ' -f3",
667                iso_dev);
668        log_it("command = %s", command);
669        log_it("res of it = %s",
670               call_program_and_get_last_line_of_output(command));
671        sprintf(iso_mnt, "%s",
672                call_program_and_get_last_line_of_output(command));
673        sprintf(tmp, "%s/ISO-MNT", bkpinfo->tmpdir);
674        write_one_liner_data_file(tmp,
675                                  call_program_and_get_last_line_of_output
676                                  (command));
677        log_it("isomnt: %s, %d", iso_mnt, strlen(iso_mnt));
678        sprintf(iso_tmp, "%s", bkpinfo->isodir);
679        if (strlen(iso_tmp) < strlen(iso_mnt)) {
680            iso_path[0] = '\0';
681        } else {
682            sprintf(iso_path, "%s", iso_tmp + strlen(iso_mnt));
683        }
684        sprintf(tmp, "%s/ISODIR", bkpinfo->tmpdir);
685        write_one_liner_data_file(tmp, iso_path);
686        log_it("isodir: %s", iso_path);
687
688/* End patch */
689    }                           // end of iso code
690
691    if (bkpinfo->backup_media_type == nfs) {
692        strcpy(hostname, bkpinfo->nfs_mount);
693        colon = strchr(hostname, ':');
694        if (!colon) {
695            log_it("nfs mount doesn't have a colon in it");
696            retval++;
697        } else {
698            struct hostent *hent;
699
700            *colon = '\0';
701            hent = gethostbyname(hostname);
702            if (!hent) {
703                log_it("Can't resolve NFS mount (%s): %s", hostname,
704                       hstrerror(h_errno));
705                retval++;
706            } else {
707                strcpy(ip_address, inet_ntoa((struct in_addr)
708                                             *((struct in_addr *) hent->
709                                               h_addr)));
710                strcat(ip_address, strchr(bkpinfo->nfs_mount, ':'));
711                strcpy(bkpinfo->nfs_mount, ip_address);
712            }
713        }
714        store_nfs_config (bkpinfo);
715    }
716
717    log_it("Finished processing incoming params");
718    if (retval) {
719        fprintf(stderr, "Type 'man mondoarchive' for help.\n");
720    }
721    sprintf(tmp, "%s", MONDO_TMPISOS);  /* added #define 22 apr 2002 */
722    if (does_file_exist(tmp)) {
723        unlink(tmp);
724    }
725    if (strlen(bkpinfo->tmpdir) < 2 || strlen(bkpinfo->scratchdir) < 2) {
726        log_it("tmpdir or scratchdir are blank/missing");
727        retval++;
728    }
729    if (bkpinfo->include_paths[0] == '\0') {
730        //      fatal_error ("Why no backup path?");
731        strcpy(bkpinfo->include_paths, "/");
732    }
733    chmod(bkpinfo->scratchdir, 0700);
734    chmod(bkpinfo->tmpdir, 0700);
735    g_backup_media_type = bkpinfo->backup_media_type;
736    paranoid_free(mtpt);
737    paranoid_free(extra_cdrom_params);
738    paranoid_free(mondo_mkisofs_sz);
739    paranoid_free(command);
740    paranoid_free(hostname);
741    paranoid_free(ip_address);
742    paranoid_free(cdr_exe);
743    paranoid_free(tmp);
744    paranoid_free(iso_dev);
745    paranoid_free(iso_mnt);
746    paranoid_free(iso_tmp);
747    paranoid_free(iso_path);
748    return (retval);
749}
750
751
752
753/**
754 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
755 * Seeds the random-number generator, loads important modules, checks the sanity
756 * of the user's Linux distribution, and deletes logfile.
757 * @param bkpinfo The backup information structure. Will be initialized.
758 * @return number of errors (0 for success)
759 */
760int pre_param_configuration(struct s_bkpinfo *bkpinfo)
761{
762    int res = 0;
763
764    make_hole_for_dir(MNT_CDROM);
765    assert(bkpinfo != NULL);
766    srandom((unsigned long) (time(NULL)));
767    insmod_crucial_modules();
768    reset_bkpinfo(bkpinfo);     // also sets defaults ('/'=backup path, 3=compression level)
769    if (bkpinfo->disaster_recovery) {
770        if (!does_nonMS_partition_exist()) {
771            fatal_error
772                ("I am in disaster recovery mode\nPlease don't run mondoarchive.");
773        }
774    }
775
776    unlink(MONDO_TRACEFILE);
777    run_program_and_log_output("rm -Rf /tmp/changed.files*", FALSE);
778    if (find_and_store_mondoarchives_home(g_mondo_home)) {
779        fprintf(stderr,
780                "Cannot find Mondo's homedir. I think you have >1 'mondo' directory on your hard disk. Please delete the superfluous 'mondo' directories and try again\n");
781        res++;
782        return (res);
783    }
784    res += some_basic_system_sanity_checks();
785    if (res) {
786        log_it("Your distribution did not pass Mondo's sanity test.");
787    }
788    g_current_media_number = 1;
789    bkpinfo->postnuke_tarball[0] = bkpinfo->nfs_mount[0] = '\0';
790    return (res);
791}
792
793
794
795
796/**
797 * Reset all fields of the backup information structure to a sensible default.
798 * @param bkpinfo The @c bkpinfo to reset.
799 */
800void reset_bkpinfo(struct s_bkpinfo *bkpinfo)
801{
802    int i;
803
804    log_msg(1, "Hi");
805    assert(bkpinfo != NULL);
806    memset((void *) bkpinfo, 0, sizeof(struct s_bkpinfo));
807    bkpinfo->manual_cd_tray = FALSE;
808    bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
809    bkpinfo->media_device[0] = '\0';
810    for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
811        bkpinfo->media_size[i] = -1;
812    }
813    bkpinfo->boot_loader = '\0';
814    bkpinfo->boot_device[0] = '\0';
815    bkpinfo->zip_exe[0] = '\0';
816    bkpinfo->zip_suffix[0] = '\0';
817    bkpinfo->restore_path[0] = '\0';
818    bkpinfo->use_lzo = FALSE;
819    bkpinfo->do_not_compress_these[0] = '\0';
820    bkpinfo->verify_data = FALSE;
821    bkpinfo->backup_data = FALSE;
822    bkpinfo->restore_data = FALSE;
823    bkpinfo->disaster_recovery =
824        (am_I_in_disaster_recovery_mode()? TRUE : FALSE);
825    if (bkpinfo->disaster_recovery) {
826        strcpy(bkpinfo->isodir, "/");
827    } else {
828        strcpy(bkpinfo->isodir, "/root/images/mondo");
829    }
830    strcpy(bkpinfo->prefix, "mondorescue");
831
832    bkpinfo->scratchdir[0] = '\0';
833    bkpinfo->make_filelist = TRUE;  // unless -J supplied to mondoarchive
834    sprintf(bkpinfo->tmpdir, "/tmp/tmpfs/mondo.tmp.%d", (int) (random() % 32768));  // for mondorestore
835    bkpinfo->optimal_set_size = 0;
836    bkpinfo->backup_media_type = none;
837    strcpy(bkpinfo->include_paths, "/");
838    bkpinfo->exclude_paths[0] = '\0';
839    bkpinfo->call_before_iso[0] = '\0';
840    bkpinfo->call_make_iso[0] = '\0';
841    bkpinfo->call_burn_iso[0] = '\0';
842    bkpinfo->call_after_iso[0] = '\0';
843    bkpinfo->image_devs[0] = '\0';
844    bkpinfo->postnuke_tarball[0] = '\0';
845    bkpinfo->kernel_path[0] = '\0';
846    bkpinfo->nfs_mount[0] = '\0';
847    bkpinfo->nfs_remote_dir[0] = '\0';
848    bkpinfo->wipe_media_first = FALSE;
849    bkpinfo->differential = FALSE;
850    bkpinfo->cdrw_speed = 0;
851// patch by Herman Kuster 
852    bkpinfo->differential = 0;
853// patch end
854    bkpinfo->compression_level = 3;
855}
856
857
858
859
860/**
861 * Get the remaining free space (in MB) on @p partition.
862 * @param partition The partition to check free space on (either a device or a mountpoint).
863 * @return The free space on @p partition, in MB.
864 */
865long free_space_on_given_partition(char *partition)
866{
867    char command[MAX_STR_LEN], out_sz[MAX_STR_LEN];
868    long res;
869
870    assert_string_is_neither_NULL_nor_zerolength(partition);
871
872    sprintf(command, "df -m %s &> /dev/null", partition);
873    if (system(command)) {
874        return (-1);
875    }                           // partition does not exist
876    sprintf(command, "df -m %s | tail -n1 | tr -s ' ' '\t' | cut -f4",
877            partition);
878    strcpy(out_sz, call_program_and_get_last_line_of_output(command));
879    if (strlen(out_sz) == 0) {
880        return (-1);
881    }                           // error within df, probably
882    res = atol(out_sz);
883    return (res);
884}
885
886
887
888/**
889 * Check the user's system for sanity. Checks performed:
890 * - make sure user has enough RAM (32mb required, 64mb recommended)
891 * - make sure user has enough free space in @c /
892 * - check kernel for ramdisk support
893 * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
894 * - make sure CD-ROM is unmounted
895 * - make sure /etc/modules.conf exists
896 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
897 *
898 * @return number of problems with the user's setup (0 for success)
899 */
900int some_basic_system_sanity_checks()
901{
902
903    /*@ buffers ************ */
904    char tmp[MAX_STR_LEN];
905    //  char command[MAX_STR_LEN];
906
907    /*@ int's *************** */
908    int retval = 0;
909    long Lres;
910
911
912    mvaddstr_and_log_it(g_currentY, 0,
913                        "Checking sanity of your Linux distribution");
914#ifndef __FreeBSD__
915    if (system("which mkfs.vfat &> /dev/null")
916        && !system("which mkfs.msdos &> /dev/null")) {
917        log_it
918            ("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
919        run_program_and_log_output
920            ("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
921    }
922    strcpy(tmp,
923           call_program_and_get_last_line_of_output
924           ("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2"));
925    if (atol(tmp) < 35000) {
926        retval++;
927        log_to_screen("You must have at least 32MB of RAM to use Mondo.");
928    }
929    if (atol(tmp) < 66000) {
930        log_to_screen
931            ("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
932    }
933#endif
934
935    if ((Lres = free_space_on_given_partition("/root")) == -1) {
936        Lres = free_space_on_given_partition("/");
937    }
938    log_it("Free space on given partition = %ld MB", Lres);
939
940    if (Lres < 50) {
941        run_program_and_log_output
942            ("rm -Rf /root/images/mindi; mkdir -p /home/root/images/mindi; mkdir -p /root/images; ln -sf /home/root/images/mindi /root/images/mindi",
943             3);
944        //      fatal_error("Your / (or /root) partition has <50MB free. Please adjust your partition table to something saner.");
945    }
946
947    if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
948        retval++;
949        log_to_screen
950            ("Unable to find " MKE2FS_OR_NEWFS " in system path.");
951        fatal_error
952            ("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. :)");
953    }
954#ifndef __FreeBSD__
955    if (run_program_and_log_output
956        ("cat /proc/devices | grep ramdisk", FALSE)) {
957        if (!ask_me_yes_or_no
958            ("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?"))
959        {
960            //          retval++;
961            log_to_screen
962                ("It looks as if your kernel lacks ramdisk and initrd support.");
963            log_to_screen
964                ("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
965        }
966    }
967#endif
968    retval += whine_if_not_found(MKE2FS_OR_NEWFS);
969    retval += whine_if_not_found("mkisofs");
970    if (system("which dvdrecord > /dev/null 2> /dev/null")) {
971        retval += whine_if_not_found("cdrecord");
972    }
973    retval += whine_if_not_found("bzip2");
974    retval += whine_if_not_found("awk");
975    retval += whine_if_not_found("md5sum");
976    retval += whine_if_not_found("strings");
977    retval += whine_if_not_found("mindi");
978    retval += whine_if_not_found("buffer");
979
980    // abort if Windows partition but no ms-sys and parted
981    if (!run_program_and_log_output
982        ("mount | grep -w vfat | grep -v /dev/fd | grep -v nexdisk", 0)
983        ||
984        !run_program_and_log_output
985        ("mount | grep -w dos | grep -v /dev/fd | grep -v nexdisk", 0)) {
986        log_to_screen("I think you have a Windows 9x partition.");
987        retval += whine_if_not_found("parted");
988#ifndef __IA64__
989        /* IA64 always has one vfat partition for EFI even without Windows */
990        // retval +=
991        if (!find_home_of_exe("ms-sys")) {
992            log_to_screen("Please install ms-sys just in case.");
993        }
994#endif
995    }
996
997    if (!find_home_of_exe("cmp")) {
998        if (!find_home_of_exe("true")) {
999            whine_if_not_found("cmp");
1000        } else {
1001            log_to_screen
1002                ("Your system lacks the 'cmp' binary. I'll create a dummy cmp for you.");
1003            if (run_program_and_log_output
1004                ("cp -f `which true` /usr/bin/cmp", 0)) {
1005                fatal_error("Failed to create dummy 'cmp' file.");
1006            }
1007        }
1008    }
1009    run_program_and_log_output
1010        ("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
1011    strcpy(tmp,
1012           call_program_and_get_last_line_of_output
1013           ("mount | grep -E \"cdr(om|w)\""));
1014    if (strcmp("", tmp)) {
1015        if (strstr(tmp, "autofs")) {
1016            log_to_screen
1017                ("Your CD-ROM is mounted via autofs. I therefore cannot tell");
1018            log_to_screen
1019                ("if a CD actually is inserted. If a CD is inserted, please");
1020            log_to_screen("eject it. Thank you.");
1021            log_it
1022                ("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
1023        } else
1024            if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
1025            retval++;
1026            fatal_error
1027                ("Your CD-ROM drive is mounted. Please unmount it.");
1028        }
1029    }
1030#ifndef __FreeBSD__
1031    if (!does_file_exist("/etc/modules.conf")) {
1032        if (does_file_exist("/etc/conf.modules")) {
1033            log_it("Linking /etc/modules.conf to /etc/conf.modules");
1034            run_program_and_log_output
1035                ("ln -sf /etc/conf.modules /etc/modules.conf", 5);
1036        } else if (does_file_exist("/etc/modprobe.d")) {
1037            log_it
1038                ("Directory /etc/modprobe.d found. mindi will use its contents.");
1039        } else if (does_file_exist("/etc/modprobe.conf")) {
1040            log_it("Linking /etc/modules.conf to /etc/modprobe.conf");
1041            run_program_and_log_output
1042                ("ln -sf /etc/modprobe.conf /etc/modules.conf", 5);
1043        } else {
1044            retval++;
1045            log_to_screen
1046                ("Please find out what happened to /etc/modules.conf");
1047        }
1048    }
1049#endif
1050
1051    run_program_and_log_output("cat /etc/fstab", 5);
1052#ifdef __FreeBSD__
1053    run_program_and_log_output("vinum printconfig", 5);
1054#else
1055    run_program_and_log_output("cat /etc/raidtab", 5);
1056#endif
1057
1058    if (run_program_and_log_output("mindi -V", 1)) {
1059        log_to_screen("Could not ascertain mindi's version number.");
1060        log_to_screen
1061            ("You have not installed Mondo and/or Mindi properly.");
1062        log_to_screen("Please uninstall and reinstall them both.");
1063        fatal_error("Please reinstall Mondo and Mindi.");
1064    }
1065    if (run_program_and_log_output
1066        ("mindi --makemountlist /tmp/mountlist.txt.test", 5)) {
1067        log_to_screen
1068            ("Mindi --makemountlist /tmp/mountlist.txt.test failed for some reason.");
1069        log_to_screen
1070            ("Please run that command by hand and examine /var/log/mindi.log");
1071        log_to_screen
1072            ("for more information. Perhaps your /etc/fstab file is insane.");
1073        log_to_screen
1074            ("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
1075        retval++;
1076    }
1077
1078    if (!run_program_and_log_output("fdisk -l | grep -i raid", 1)
1079        && !does_file_exist("/etc/raidtab")) {
1080        log_to_screen
1081            ("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
1082        create_raidtab_from_mdstat("/etc/raidtab", "/proc/mdstat");
1083    }
1084
1085    if (retval) {
1086        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1087    } else {
1088        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1089    }
1090    return (retval);
1091}
1092
1093/**
1094 * Retrieve the line containing @p label from the config file.
1095 * @param config_file The file to read from, usually @c /tmp/mondo-restore.cfg.
1096 * @param label What to read from the file.
1097 * @param value Where to put it.
1098 * @return 0 for success, 1 for failure.
1099 */
1100int read_cfg_var(char *config_file, char *label, char *value)
1101{
1102    /*@ buffer ****************************************************** */
1103    char command[MAX_STR_LEN * 2];
1104    char tmp[MAX_STR_LEN];
1105
1106    /*@ end vars *************************************************** */
1107
1108    assert_string_is_neither_NULL_nor_zerolength(config_file);
1109    assert_string_is_neither_NULL_nor_zerolength(label);
1110    if (!does_file_exist(config_file)) {
1111        sprintf(tmp, "(read_cfg_var) Cannot find %s config file",
1112                config_file);
1113        log_to_screen(tmp);
1114        value[0] = '\0';
1115        return (1);
1116    } else if (strstr(value, "/dev/") && strstr(value, "t0")
1117               && !strcmp(label, "media-dev")) {
1118        log_msg(2, "FYI, I shan't read new value for %s - already got %s",
1119                label, value);
1120        return (0);
1121    } else {
1122        sprintf(command, "cat %s | grep \"%s .*\" | cut -d' ' -f2,3,4,5",
1123                config_file, label);
1124        strcpy(value, call_program_and_get_last_line_of_output(command));
1125        if (strlen(value) == 0) {
1126            return (1);
1127        } else {
1128            return (0);
1129        }
1130    }
1131}
1132
1133
1134
1135/**
1136 * Remount @c supermount if it was unmounted earlier.
1137 */
1138void remount_supermounts_if_necessary()
1139{
1140    if (g_remount_cdrom_at_end) {
1141        run_program_and_log_output("mount " MNT_CDROM, FALSE);
1142    }
1143    if (g_remount_floppy_at_end) {
1144        run_program_and_log_output("mount " MNT_FLOPPY, FALSE);
1145    }
1146}
1147
1148/**
1149 * Unmount @c supermount if it's mounted.
1150 */
1151void unmount_supermounts_if_necessary()
1152{
1153    if (run_program_and_log_output
1154        ("mount | grep cdrom | grep super", FALSE) == 0) {
1155        g_remount_cdrom_at_end = TRUE;
1156        run_program_and_log_output("umount " MNT_CDROM, FALSE);
1157    }
1158    if (run_program_and_log_output
1159        ("mount | grep floppy | grep super", FALSE) == 0) {
1160        g_remount_floppy_at_end = TRUE;
1161        run_program_and_log_output("umount " MNT_FLOPPY, FALSE);
1162    }
1163}
1164
1165/**
1166 * Whether we had to stop autofs (if so, restart it at end).
1167 */
1168bool g_autofs_stopped = FALSE;
1169
1170/**
1171 * Path to the autofs initscript ("" if none exists).
1172 */
1173char g_autofs_exe[MAX_STR_LEN];
1174
1175/**
1176 * Autofs initscript in Xandros Linux distribution.
1177 */
1178#define XANDROS_AUTOFS_FNAME "/etc/init.d/xandros-autofs"
1179
1180/**
1181 * Autofs initscript in most Linux distributions.
1182 */
1183#define STOCK_AUTOFS_FNAME "/etc/rc.d/init.d/autofs"
1184
1185/**
1186 * If autofs is mounted, stop it (restart at end).
1187 */
1188void stop_autofs_if_necessary()
1189{
1190    char tmp[MAX_STR_LEN];
1191
1192    g_autofs_exe[0] = '\0';
1193    if (does_file_exist(XANDROS_AUTOFS_FNAME)) {
1194        strcpy(g_autofs_exe, XANDROS_AUTOFS_FNAME);
1195    } else if (does_file_exist(STOCK_AUTOFS_FNAME)) {
1196        strcpy(g_autofs_exe, STOCK_AUTOFS_FNAME);
1197    }
1198
1199    if (!g_autofs_exe[0]) {
1200        log_msg(3, "No autofs detected.");
1201    } else {
1202        log_msg(3, "%s --- autofs detected", g_autofs_exe);
1203// FIXME -- only disable it if it's running ---  sprintf(tmp, "%s status", autofs_exe);
1204        sprintf(tmp, "%s stop", g_autofs_exe);
1205        if (run_program_and_log_output(tmp, 2)) {
1206            log_it("Failed to stop autofs - I assume it wasn't running");
1207        } else {
1208            g_autofs_stopped = TRUE;
1209            log_it("Stopped autofs OK");
1210        }
1211    }
1212}
1213
1214/**
1215 * If autofs was stopped earlier, restart it.
1216 */
1217void restart_autofs_if_necessary()
1218{
1219    char tmp[MAX_STR_LEN];
1220
1221    if (!g_autofs_stopped || !g_autofs_exe[0]) {
1222        log_msg(3, "No autofs detected.");
1223        return;
1224    }
1225    sprintf(tmp, "%s start", g_autofs_exe);
1226    if (run_program_and_log_output(tmp, 2)) {
1227        log_it("Failed to start autofs");
1228    } else {
1229        g_autofs_stopped = FALSE;
1230        log_it("Started autofs OK");
1231    }
1232}
1233
1234
1235/**
1236 * If this is a distribution like Gentoo that doesn't keep /boot mounted, mount it.
1237 */
1238void mount_boot_if_necessary()
1239{
1240    char tmp[MAX_STR_LEN];
1241    char command[MAX_STR_LEN];
1242
1243    log_msg(1, "Started sub");
1244    log_msg(4, "About to set g_boot_mountpt[0] to '\\0'");
1245    g_boot_mountpt[0] = '\0';
1246    log_msg(4, "Done. Great. Seeting command to something");
1247    strcpy(command,
1248           "cat /etc/fstab | grep -v \":\" | grep -vx \"#.*\" | grep -w \"/boot\" | tr -s ' ' '\t' | cut -f1 | head -n1");
1249    log_msg(4, "Cool. Command = '%s'", command);
1250    strcpy(tmp, call_program_and_get_last_line_of_output(command));
1251    log_msg(4, "tmp = '%s'", tmp);
1252    if (tmp[0]) {
1253        log_it("/boot is at %s according to /etc/fstab", tmp);
1254        if (strstr(tmp, "LABEL=")) {
1255            if (!run_program_and_log_output("mount /boot", 5)) {
1256                strcpy(g_boot_mountpt, "/boot");
1257                log_msg(1, "Mounted /boot");
1258            } else {
1259                log_it("...ignored cos it's a label :-)");
1260            }
1261        } else {
1262            sprintf(command, "mount | grep -w \"%s\"", tmp);
1263            log_msg(3, "command = %s", command);
1264            if (run_program_and_log_output(command, 5)) {
1265                strcpy(g_boot_mountpt, tmp);
1266                sprintf(tmp,
1267                        "%s (your /boot partition) is not mounted. I'll mount it before backing up",
1268                        g_boot_mountpt);
1269                log_it(tmp);
1270                sprintf(tmp, "mount %s", g_boot_mountpt);
1271                if (run_program_and_log_output(tmp, 5)) {
1272                    g_boot_mountpt[0] = '\0';
1273                    log_msg(1, "Plan B");
1274                    if (!run_program_and_log_output("mount /boot", 5)) {
1275                        strcpy(g_boot_mountpt, "/boot");
1276                        log_msg(1, "Plan B worked");
1277                    } else {
1278                        log_msg(1,
1279                                "Plan B failed. Unable to mount /boot for backup purposes. This probably means /boot is mounted already, or doesn't have its own partition.");
1280                    }
1281                }
1282            }
1283        }
1284    }
1285    log_msg(1, "Ended sub");
1286}
1287
1288
1289/**
1290 * If we mounted /boot earlier, unmount it.
1291 */
1292void unmount_boot_if_necessary()
1293{
1294    char tmp[MAX_STR_LEN];
1295
1296    log_msg(3, "starting");
1297    if (g_boot_mountpt[0]) {
1298        sprintf(tmp, "umount %s", g_boot_mountpt);
1299        if (run_program_and_log_output(tmp, 5)) {
1300            log_it("WARNING - unable to unmount /boot");
1301        }
1302    }
1303    log_msg(3, "leaving");
1304}
1305
1306
1307
1308/**
1309 * Write a line to a configuration file. Writes a line of the form,
1310 * @c label @c value.
1311 * @param config_file The file to write to. Usually @c mondo-restore.cfg.
1312 * @param label What to call this bit of data you're writing.
1313 * @param value The bit of data you're writing.
1314 * @return 0 for success, 1 for failure.
1315 */
1316int write_cfg_var(char *config_file, char *label, char *value)
1317{
1318    /*@ buffers ***************************************************** */
1319    char command[MAX_STR_LEN * 2];
1320    char tempfile[MAX_STR_LEN];
1321    char tmp[MAX_STR_LEN];
1322
1323
1324    /*@ end vars *************************************************** */
1325    assert_string_is_neither_NULL_nor_zerolength(config_file);
1326    assert_string_is_neither_NULL_nor_zerolength(label);
1327    assert(value != NULL);
1328    if (!does_file_exist(config_file)) {
1329        sprintf(tmp, "(write_cfg_file) Cannot find %s config file",
1330                config_file);
1331        log_to_screen(tmp);
1332        return (1);
1333    }
1334    strcpy(tempfile,
1335           call_program_and_get_last_line_of_output
1336           ("mktemp -q /tmp/mojo-jojo.blah.XXXXXX"));
1337    if (does_file_exist(config_file)) {
1338        sprintf(command, "cat %s | grep -vx \"%s .*\" > %s", config_file,
1339                label, tempfile);
1340        paranoid_system(command);
1341    }
1342    sprintf(command, "echo \"%s %s\" >> %s", label, value, tempfile);
1343    paranoid_system(command);
1344    sprintf(command, "mv -f %s %s", tempfile, config_file);
1345    paranoid_system(command);
1346    unlink(tempfile);
1347    return (0);
1348}
1349
1350
1351/**
1352 * The standard log_debug_msg() (log_msg() also due to a macro). Writes some describing
1353 * information to the logfile.
1354 */
1355void standard_log_debug_msg(int debug_level, const char *szFile,
1356                            const char *szFunction, int nLine,
1357                            const char *fmt, ...)
1358{
1359    va_list args;
1360    int i;
1361    static int depth = 0;
1362    char *tmp;
1363    FILE *fout;
1364
1365    if (depth > 5) {
1366        depth--;
1367        return;
1368    }
1369    depth++;
1370
1371    malloc_string(tmp);
1372
1373    if (debug_level <= g_loglevel) {
1374        va_start(args, fmt);
1375        if (!(fout = fopen(MONDO_LOGFILE, "a"))) {
1376            return;
1377        }                       // fatal_error("Failed to openout to logfile - sheesh..."); }
1378
1379        // add tabs to distinguish log levels
1380        if (debug_level > 0) {
1381            for (i = 1; i < debug_level; i++)
1382                fprintf(fout, "\t");
1383            if (getpid() == g_main_pid)
1384                fprintf(fout, "[Main] %s->%s#%d: ", szFile, szFunction,
1385                        nLine);
1386            else if (getpid() == g_buffer_pid && g_buffer_pid > 0)
1387                fprintf(fout, "[Buff] %s->%s#%d: ", szFile, szFunction,
1388                        nLine);
1389            else
1390                fprintf(fout, "[TH=%d] %s->%s#%d: ", getpid(), szFile,
1391                        szFunction, nLine);
1392        }
1393        vfprintf(fout, fmt, args);
1394
1395        // do not slow down the progran if standard debug level
1396        // must be enabled: if no flush, the log won't be up-to-date if there
1397        // is a segfault
1398        //if (g_dwDebugLevel != 1)
1399
1400        va_end(args);
1401        fprintf(fout, "\n");
1402        paranoid_fclose(fout);
1403    }
1404    depth--;
1405    paranoid_free(tmp);
1406}
1407
1408/**
1409 * Function pointer to the @c log_debug_msg function to use. Points to standard_log_debug_msg() by default.
1410 */
1411void (*log_debug_msg) (int, const char *, const char *, int, const char *,
1412                       ...) = standard_log_debug_msg;
1413
1414
1415/**
1416 * If @p y, malloc @p x, else free @p x.
1417 * @bug This function seems orphaned. Please remove.
1418 */
1419#define do_alloc_or_free_depending(x,y) { if(y) {x=malloc(MAX_STR_LEN);} else {paranoid_free(x);} }
1420
1421/**
1422 * Allocate or free important globals, depending on @p mal.
1423 * @param mal If TRUE, malloc; if FALSE, free.
1424 */
1425void do_libmondo_global_strings_thing(int mal)
1426{
1427    if (mal) {
1428        iamhere("Malloc'ing globals");
1429        malloc_string(g_boot_mountpt);
1430        malloc_string(g_mondo_home);
1431        malloc_string(g_tmpfs_mountpt);
1432        malloc_string(g_erase_tmpdir_and_scratchdir);
1433        malloc_string(g_serial_string);
1434        malloc_string(g_magicdev_command);
1435    } else {
1436        iamhere("Freeing globals");
1437        paranoid_free(g_boot_mountpt);
1438        paranoid_free(g_mondo_home);
1439        paranoid_free(g_tmpfs_mountpt);
1440        paranoid_free(g_erase_tmpdir_and_scratchdir);
1441        paranoid_free(g_serial_string);
1442        paranoid_free(g_magicdev_command);
1443    }
1444
1445    /*
1446       char**list_of_arrays[] = {
1447       &g_boot_mountpt,
1448       &g_mondo_home,
1449       &g_tmpfs_mountpt,
1450       &g_erase_tmpdir_and_scratchdir,
1451       &g_serial_string,
1452       &g_magicdev_command,
1453       NULL};
1454
1455       char**ppcurr;
1456       int i;
1457
1458       for(i=0;list_of_arrays[i];i++)
1459       {
1460       log_msg(5, "Allocating %d", i);
1461       ppcurr = list_of_arrays[i];
1462       if (mal)
1463       { *ppcurr = malloc(MAX_STR_LEN); }
1464       else
1465       {
1466       if (*ppcurr)
1467       {
1468       free(*ppcurr);
1469       }
1470       }
1471       }
1472       log_msg(5, "Returning");
1473     */
1474}
1475
1476/**
1477 * Allocate important globals.
1478 * @see do_libmondo_global_strings_thing
1479 */
1480void malloc_libmondo_global_strings(void)
1481{
1482    do_libmondo_global_strings_thing(1);
1483}
1484
1485/**
1486 * Free important globals.
1487 * @see do_libmondo_global_strings_thing
1488 */
1489void free_libmondo_global_strings(void)
1490{
1491    do_libmondo_global_strings_thing(0);
1492}
1493
1494
1495
1496/**
1497 * Stop @c magicdev if it's running.
1498 * The command used to start it is saved in @p g_magicdev_command.
1499 */
1500void stop_magicdev_if_necessary()
1501{
1502    strcpy(g_magicdev_command,
1503           call_program_and_get_last_line_of_output
1504           ("ps ax | grep -w magicdev | grep -v grep | tr -s '\t' ' '| cut -d' ' -f6-99"));
1505    if (g_magicdev_command[0]) {
1506        log_msg(1, "g_magicdev_command = '%s'", g_magicdev_command);
1507        paranoid_system("killall magicdev");
1508    }
1509}
1510
1511
1512/**
1513 * Restart magicdev if it was stopped.
1514 */
1515void restart_magicdev_if_necessary()
1516{
1517    char *tmp;
1518
1519    malloc_string(tmp);
1520    if (g_magicdev_command && g_magicdev_command[0]) {
1521        sprintf(tmp, "%s &", g_magicdev_command);
1522        paranoid_system(tmp);
1523    }
1524    paranoid_free(tmp);
1525}
1526
1527/* @} - end of utilityGroup */
Note: See TracBrowser for help on using the repository browser.