source: MondoRescue/branches/2.2.4/mondo/src/common/libmondo-tools.c @ 1437

Last change on this file since 1437 was 1437, checked in by andree, 13 years ago

New define 'MINDI_CACHE' set to '/var/cache/mindi' rather than
hardcoding this in the code. Makes it easy to change the location. Also
adjusted some of the messages related to boot floppies or CDs.

(Also added missing debug level to log_debug() call.)

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