source: branches/3.0/mondo/src/common/libmondo-tools.c @ 3154

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