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

Last change on this file since 196 was 196, checked in by bcornec, 14 years ago

Usage of parted2fdisk instead of fdisk everywhere.
on ia64 this is mandatory, and simplifies the infrastructure
on other archs, it doesn't change anything as parted2fdisk here is a link to fdisk

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