source: branches/2.05/mondo/mondo/common/libmondo-tools.c @ 153

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

Added check for sudo when writing DVDs and terminate if sudo used
because growisofs does't support sudo.

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