source: branches/2.2.9/mondo/src/mondorestore/mondo-rstr-tools.c @ 2770

Last change on this file since 2770 was 2770, checked in by Bruno Cornec, 9 years ago
  • Fix compilation issues due to level of visibility of functions
  • Property svn:keywords set to Id
File size: 71.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2770 2011-04-21 12:14:52Z bruno $
3***************************************************************************/
4
5#include <pthread.h>
6#include <linux/fd.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "../common/mondostructures.h"
10#include "../common/libmondo.h"
11#include "mr-externs.h"
12#include "mondo-rstr-tools.h"
13
14/**
15 * The biggielist stub (appended to the directory where all.tar.gz was unpacked).
16 */
17#define BIGGIELIST_TXT_STUB "tmp/biggielist.txt"
18
19/**
20 * The filelist stub (appended to the directory where all.tar.gz was unpacked).
21 */
22#define FILELIST_FULL_STUB "tmp/filelist.full.gz"
23
24/**
25 * The mountlist stub (appended to the directory where all.tar.gz was unpacked).
26 */
27#define MOUNTLIST_FNAME_STUB "tmp/mountlist.txt"
28
29/**
30 * The mondo-restore.cfg stub (appended to the directory where all.tar.gz was unpacked).
31 */
32#define MONDO_CFG_FILE_STUB "tmp/mondo-restore.cfg"
33/**
34 * The i-want-my-lvm stub
35 */
36#define IWANTMYLVM_STUB "tmp/i-want-my-lvm"
37
38extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
39extern bool g_I_have_just_nuked;
40/*
41extern char *g_tmpfs_mountpt;
42*/
43extern char *g_isodir_device;
44extern char *g_isodir_format;
45extern long g_current_progress, g_maximum_progress;
46extern char *g_biggielist_txt;  // where 'biggielist.txt' is stored, on ramdisk / tempdir;
47                  // biggielist.txt is the list of big files stored on the
48                  // backup media set in question
49extern char *g_filelist_full;   // filelist.full.gz is the list of all regular files
50                  // (excluding big files) stored on the backup media set
51extern char *g_biggielist_pot;  // list of big files which _could_ be restored, if the
52                  // user chooses them
53extern char *g_filelist_imagedevs;  // list of devices (e.g. /dev/hda1, /dev/sda5) which
54                     // were archived as images, not just /dev entries
55                     // ... e.g. NTFS, BeOS partitions
56extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
57                      // restore only these
58extern char *g_mondo_cfg_file;  // where m*ndo-restore.cfg (the config file) is stored
59extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
60extern char *g_mondo_home;      // homedir of Mondo; usually /usr/local/share/mondo
61
62extern t_bkptype g_backup_media_type;
63
64extern int g_partition_table_locked_up;
65extern char *MONDO_LOGFILE;
66
67/* Reference to global bkpinfo */
68extern struct s_bkpinfo *bkpinfo;
69
70/* Should we use or not extended attributes and acl when restoring */
71char *g_getfattr = NULL;
72char *g_getfacl = NULL;
73
74extern void kill_anything_like_this(char *str);
75extern int skip_obdr(void);
76extern int mount_media();
77extern int set_tape_block_size_with_mt(long internal_tape_block_size);
78
79/**
80* @addtogroup restoreUtilityGroup
81* @{
82*/
83/**
84* Free the malloc()s for the filename variables.
85*/
86void free_MR_global_filenames(void)
87{
88paranoid_free(g_biggielist_txt);
89paranoid_free(g_filelist_full);
90paranoid_free(g_filelist_imagedevs);
91paranoid_free(g_imagedevs_restthese);
92paranoid_free(g_mondo_cfg_file);
93paranoid_free(g_mountlist_fname);
94paranoid_free(g_mondo_home);
95/*
96paranoid_free(g_tmpfs_mountpt);
97*/
98paranoid_free(g_isodir_device);
99paranoid_free(g_isodir_format);
100
101}
102
103
104
105/**
106* Ask the user which imagedevs from the list contained in @p infname should
107* actually be restored.
108* @param infname The file containing a list of all imagedevs.
109* @param outfname The location of the output file containing the imagedevs the user wanted to restore.
110* @ingroup restoreUtilityGroup
111*/
112void ask_about_these_imagedevs(char *infname, char *outfname)
113{
114FILE *fin;
115FILE *fout;
116/************************************************************************
117* allocate memory regions. test and set  -sab 16 feb 2003              *
118************************************************************************/
119char *incoming_ptr;
120char *question_ptr;
121
122char incoming[MAX_STR_LEN] = "\0";
123char question[MAX_STR_LEN];
124
125assert_string_is_neither_NULL_nor_zerolength(infname);
126assert_string_is_neither_NULL_nor_zerolength(outfname);
127
128incoming_ptr = malloc(sizeof(incoming));
129if (incoming_ptr == NULL) {
130fprintf(stderr, "Out of Memory\n");
131exit(EXIT_FAILURE);
132}
133
134question_ptr = malloc(sizeof(question));
135if (question_ptr == NULL) {
136fprintf(stderr, "Out of Memory\n");
137exit(EXIT_FAILURE);
138}
139
140memset(incoming_ptr, '\0', sizeof(incoming));
141memset(question_ptr, '\0', sizeof(question));
142
143
144
145if (!(fin = fopen(infname, "r"))) {
146fatal_error("Cannot openin infname");
147}
148if (!(fout = fopen(outfname, "w"))) {
149fatal_error("Cannot openin outfname");
150}
151for (fgets(incoming_ptr, MAX_STR_LEN, fin);
152 !feof(fin); fgets(incoming_ptr, MAX_STR_LEN, fin)) {
153strip_spaces(incoming_ptr);
154
155if (incoming[0] == '\0') {
156    continue;
157}
158
159sprintf(question_ptr,
160        "Should I restore the image of %s ?", incoming_ptr);
161
162if (ask_me_yes_or_no(question_ptr)) {
163    fprintf(fout, "%s\n", incoming_ptr);
164}
165}
166
167/*** free memory ***********/
168paranoid_free(incoming_ptr);
169incoming_ptr = NULL;
170paranoid_free(question_ptr);
171question_ptr = NULL;
172
173
174paranoid_fclose(fout);
175paranoid_fclose(fin);
176}
177
178/**************************************************************************
179*ASK_ABOUT_THESE_IMAGEDEVS                                               *
180**************************************************************************/
181
182
183
184
185
186
187
188
189/**
190* Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname.
191* @param bkpinfo The backup information structure. @c tmpdir is the only field used.
192* @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
193* @param output_cfg_file Where to put the configuration file extracted.
194* @param output_mountlist_file Where to put the mountlist file extracted.
195* @return 0 for success, nonzero for failure.
196* @ingroup restoreUtilityGroup
197*/
198
199/**
200* Keep trying to get mondo-restore.cfg from the archive, until the user gives up.
201*/
202void get_cfg_file_from_archive_or_bust()
203{
204while (get_cfg_file_from_archive()) {
205if (!ask_me_yes_or_no
206    ("Failed to find config file/archives. Choose another source?"))
207{
208    fatal_error("Could not find config file/archives. Aborting.");
209}
210interactively_obtain_media_parameters_from_user(FALSE);
211}
212}
213
214
215/**
216* Determine whether @p list_fname contains a line containing @p f.
217* @param f The line to search for.
218* @param list_fname The file to search in.
219* @param preamble Ignore this beginning part of @p f ("" to disable).
220* @return TRUE if it's in the list, FALSE if it's not.
221*/
222bool is_file_in_list(char *f, char *list_fname, char *preamble)
223{
224
225/** needs malloc **/
226char *command;
227char *file;
228char *tmp;
229int res;
230
231malloc_string(command);
232malloc_string(file);
233malloc_string(tmp);
234assert_string_is_neither_NULL_nor_zerolength(f);
235assert_string_is_neither_NULL_nor_zerolength(list_fname);
236assert(preamble != NULL);
237
238if (strncmp(preamble, f, strlen(preamble)) == 0) {
239strcpy(file, f + strlen(preamble));
240} else {
241strcpy(file, f);
242}
243if (file[0] == '/' && file[1] == '/') {
244strcpy(tmp, file);
245strcpy(file, tmp + 1);
246}
247sprintf(tmp,
248    "Checking to see if f=%s, file=%s, is in the list of biggiefiles",
249    f, file);
250log_msg(2, tmp);
251sprintf(command, "grep -E '^%s$' %s", file, list_fname);
252res = run_program_and_log_output(command, FALSE);
253paranoid_free(command);
254paranoid_free(file);
255paranoid_free(tmp);
256if (res) {
257return (FALSE);
258} else {
259return (TRUE);
260}
261}
262
263/**************************************************************************
264*END_IS_FILE_IN_LIST                                                     *
265**************************************************************************/
266
267
268
269/**
270* Set up an ISO backup.
271* @param bkpinfo The backup information structure. Fields used:
272* - @c bkpinfo->backup_media_type
273* - @c bkpinfo->disaster_recovery
274* - @c bkpinfo->isodir
275* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
276* @return 0 for success, nonzero for failure.
277*/
278int iso_fiddly_bits(bool nuke_me_please)
279{
280char *mount_isodir_command = NULL;
281char *tmp, *command;
282char *mds = NULL;
283int retval = 0, i;
284bool already_mounted = FALSE;
285
286assert(bkpinfo != NULL);
287malloc_string(tmp);
288malloc_string(command);
289g_ISO_restore_mode = TRUE;
290read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
291if (bkpinfo->disaster_recovery) {
292    /* Patch Conor Daly 26-june-2004
293    * Don't let this clobber an existing bkpinfo->isodir */
294    if (!bkpinfo->isodir[0]) {
295        strcpy(bkpinfo->isodir, "/tmp/isodir");
296    }
297    /* End patch */
298    sprintf(command, "mkdir -p %s", bkpinfo->isodir);
299    run_program_and_log_output(command, 5);
300    log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
301}
302
303if (!get_isodir_info(g_isodir_device, g_isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
304    return (1);
305}
306paranoid_system("umount " MNT_CDROM " 2> /dev/null");   /* just in case */
307
308if (is_this_device_mounted(g_isodir_device)) {
309    log_to_screen("WARNING - isodir is already mounted");
310    already_mounted = TRUE;
311} else {
312    mr_asprintf(&mount_isodir_command, "mount %s", g_isodir_device);
313    if (strlen(g_isodir_format) > 1) {
314        mr_strcat(mount_isodir_command, " -t %s", g_isodir_format);
315    }
316    mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
317    run_program_and_log_output("df -m", FALSE);
318    sprintf(tmp,
319        "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?",
320        mount_isodir_command);
321    log_msg(1, tmp);
322    if (run_program_and_log_output(mount_isodir_command, FALSE)) {
323        popup_and_OK
324            ("Cannot mount the device where the ISO files are stored.");
325        return (1);
326    }
327    paranoid_free(mount_isodir_command);
328    log_to_screen
329    ("I have mounted the device where the ISO files are stored.");
330}
331if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
332    mount_media();
333}
334i = what_number_cd_is_this();   /* has the side-effect of calling mount_media() */
335mds = media_descriptor_string(bkpinfo->backup_media_type);
336sprintf(tmp, "%s #%d has been mounted via loopback mount", mds, i);
337mr_free(mds);
338
339log_msg(1, tmp);
340if (i < 0) {
341popup_and_OK
342    ("Cannot find ISO images in the directory you specified.");
343retval = 1;
344}
345log_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__,
346    bkpinfo->isodir);
347paranoid_free(tmp);
348paranoid_free(command);
349return (retval);
350}
351
352
353
354
355/**
356* Kill all Petris processes.
357*/
358void kill_petris(void) {
359    kill_anything_like_this("petris");
360}
361
362/**************************************************************************
363*END_KILL_PETRIS                                                         *
364**************************************************************************/
365
366
367/**
368 * Mount @p device at @p mpt as @p format.
369 * @param device The device (/dev entry) to mount.
370 * @param mpt The directory to mount it on.
371 * @param format The filesystem type of @p device.
372 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
373 * @return 0 for success, nonzero for failure.
374 */
375int mount_device(char *device, char *mpt, char *format, bool writeable)
376{
377int res = 0;
378
379/** malloc **/
380char *tmp, *command, *mountdir, *mountpoint;
381char *additional_parameters = NULL;
382
383assert_string_is_neither_NULL_nor_zerolength(device);
384assert_string_is_neither_NULL_nor_zerolength(mpt);
385assert(format != NULL);
386malloc_string(tmp);
387malloc_string(command);
388malloc_string(mountdir);
389malloc_string(mountpoint);
390
391    if (!strcmp(mpt, "/1")) {
392        strcpy(mountpoint, "/");
393        log_msg(3, "Mommm! SME is being a dildo!");
394    } else {
395        strcpy(mountpoint, mpt);
396    }
397
398    if (!strcmp(mountpoint, "lvm")) {
399        return (0);
400    }
401    if (!strcmp(mountpoint, "image")) {
402        return (0);
403    }
404    sprintf(tmp, "Mounting device %s   ", device);
405    log_msg(1, tmp);
406    /* Deal with additional params only if not /proc or /sys */
407    mr_asprintf(&additional_parameters, "");
408    if (strcmp(format, "proc") && strcmp(format, "sys")) {
409        if (writeable) {
410            mr_strcat(additional_parameters, "-o rw");
411        } else {
412            mr_strcat(additional_parameters, "-o ro");
413        }
414        if (find_home_of_exe("setfattr")) {
415            mr_strcat(additional_parameters, ",user_xattr");
416        }
417        if (find_home_of_exe("setfacl")) {
418            mr_strcat(additional_parameters, ",acl");
419        }
420    }
421
422    if (!strcmp(mountpoint, "swap")) {
423        sprintf(command, "swapon %s", device);
424    } else {
425        if (!strcmp(mountpoint, "/")) {
426            strcpy(mountdir, MNT_RESTORING);
427        } else {
428            sprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
429        }
430        sprintf(command, "mkdir -p %s", mountdir);
431        run_program_and_log_output(command, FALSE);
432        sprintf(command, "mount -t %s %s %s %s 2>> %s", format, device,
433                additional_parameters, mountdir, MONDO_LOGFILE);
434        log_msg(2, "command='%s'", command);
435    }
436    paranoid_free(additional_parameters);
437
438    res = run_program_and_log_output(command, TRUE);
439    if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
440        log_msg(1, "Re-trying without the fancy extra parameters");
441        sprintf(command, "mount -t %s %s %s 2>> %s", format, device,
442            mountdir, MONDO_LOGFILE);
443        res = run_program_and_log_output(command, TRUE);
444    }
445    if (res) {
446        log_msg(1, "Unable to mount device %s (type %s) at %s", device,
447                format, mountdir);
448        log_msg(1, "command was '%s'", command);
449        if (!strcmp(mountpoint, "swap")) {
450            log_to_screen(tmp);
451        } else {
452            log_msg(2, "Retrying w/o the '-t' switch");
453            sprintf(command, "mount %s %s 2>> %s", device, mountdir,
454                MONDO_LOGFILE);
455            log_msg(2, "2nd command = '%s'", command);
456            res = run_program_and_log_output(command, TRUE);
457            if (res == 0) {
458                log_msg(1,
459                    "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
460            } else {
461                log_to_screen(tmp);
462            }
463        }
464    }
465
466    if (res && !strcmp(mountpoint, "swap")) {
467        log_msg(2, "That's ok. It's just a swap partition.");
468        log_msg(2, "Non-fatal error. Returning 0.");
469        res = 0;
470    }
471
472paranoid_free(tmp);
473paranoid_free(command);
474paranoid_free(mountdir);
475paranoid_free(mountpoint);
476
477    return (res);
478}
479/**************************************************************************
480 *END_MOUNT_DEVICE                                                        *
481**************************************************************************/
482
483
484/**
485 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
486 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
487 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
488 * @return The number of errors encountered (0 for success).
489 */
490int mount_all_devices(struct mountlist_itself
491                      *p_external_copy_of_mountlist, bool writeable)
492{
493int retval = 0, lino, res;
494char *tmp;
495char *these_failed = NULL;
496char *format;
497struct mountlist_itself *mountlist = NULL;
498
499malloc_string(tmp);
500malloc_string(format);
501
502assert(p_external_copy_of_mountlist != NULL);
503mountlist = malloc(sizeof(struct mountlist_itself));
504memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
505   sizeof(struct mountlist_itself));
506    sort_mountlist_by_mountpoint(mountlist, 0);
507
508
509    mvaddstr_and_log_it(g_currentY, 0, "Mounting devices         ");
510    open_progress_form("Mounting devices",
511               "I am now mounting all the drives.",
512               "This should not take long.",
513               "", mountlist->entries);
514
515    mr_asprintf(&these_failed, "");
516    for (lino = 0; lino < mountlist->entries; lino++) {
517        if (!strcmp(mountlist->el[lino].device, "/proc")) {
518            log_msg(1,
519                "Again with the /proc - why is this in your mountlist?");
520        } else if (is_this_device_mounted(mountlist->el[lino].device)) {
521            sprintf(tmp, "%s is already mounted",
522                mountlist->el[lino].device);
523            log_to_screen(tmp);
524        } else if (strcmp(mountlist->el[lino].mountpoint, "none")
525           && strcmp(mountlist->el[lino].mountpoint, "lvm")
526           && strcmp(mountlist->el[lino].mountpoint, "raid")
527           && strcmp(mountlist->el[lino].mountpoint, "image")) {
528            sprintf(tmp, "Mounting %s", mountlist->el[lino].device);
529            update_progress_form(tmp);
530            strcpy(format, mountlist->el[lino].format);
531            res = mount_device(mountlist->el[lino].device,
532                       mountlist->el[lino].mountpoint,
533                       format, writeable);
534            retval += res;
535            if (res) {
536                mr_strcat(these_failed, "%s ",mountlist->el[lino].device);
537            }
538        }
539        g_current_progress++;
540    }
541    close_progress_form();
542    if (retval) {
543        if (g_partition_table_locked_up > 0) {
544            log_to_screen
545                ("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to");
546            log_to_screen
547                ("lock up the partition table. You might have to reboot and use Interactive Mode to");
548            log_to_screen
549                ("format and restore *without* partitioning first. Sorry for the inconvenience.");
550        }
551        sprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed);
552
553        if (!ask_me_yes_or_no(tmp)) {
554            retval = 0;
555            log_to_screen
556                ("Continuing, although some device(s) failed to be mounted");
557            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
558        } else {
559            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
560            log_to_screen
561        ("Unable to mount some or all of your partitions.");
562        }
563    } else {
564        log_to_screen("All partitions were mounted OK.");
565        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
566    }
567    paranoid_free(these_failed);
568
569    /* Also mounting under MNT_RESTORING  special FS */
570    (void)mount_device("/proc","/proc","proc",TRUE);
571    (void)mount_device("/sys","/sys","sysfs",TRUE);
572    run_program_and_log_output("df -m", 3);
573    paranoid_free(mountlist);
574    paranoid_free(tmp);
575    paranoid_free(format);
576    return (retval);
577}
578/**************************************************************************
579*END_MOUNT_ALL_DEVICES                                                   *
580**************************************************************************/
581
582
583
584
585/**
586* Fix some miscellaneous things in the filesystem so the system will come
587* up correctly on the first boot.
588*/
589void protect_against_braindead_sysadmins()
590{
591run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
592                       FALSE);
593run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
594                       FALSE);
595if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
596run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
597                           FALSE);
598}
599run_program_and_log_output("mkdir -p " MNT_RESTORING
600                       "/var/run/console", FALSE);
601run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
602                       FALSE);
603run_program_and_log_output("cd " MNT_RESTORING
604                       "; for i in `ls home/`; do echo \"Moving $i's spurious files to $i/.disabled\"; mkdir \"$i\"/.disabled ; mv -f \"$i\"/.DCOP* \"$i\"/.MCOP* \"$i\"/.*authority \"$i\"/.kde/tmp* \"$i\"/.kde/socket* \"$i\"/.disabled/ ; done",
605                       TRUE);
606run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
607                       TRUE);
608run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
609                       TRUE);
610}
611
612/**************************************************************************
613*END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS                                 *
614**************************************************************************/
615
616
617
618
619/**
620* Fill out @p bkpinfo based on @p cfg_file.
621* @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo.
622* @param bkpinfo The backup information structure to fill out with information
623* from @p cfg_file.
624* @return 0 for success, nonzero for failure.
625*/
626int read_cfg_file_into_bkpinfo(char *cfgf)
627{
628/** add mallocs **/
629char *value = NULL;
630char *tmp = NULL;
631char *envtmp1 = NULL;
632char *envtmp2 = NULL;
633char *command = NULL;
634char *iso_mnt = NULL;
635char *iso_path = NULL;
636char *old_isodir = NULL;
637char cfg_file[100];
638t_bkptype media_specified_by_user;
639
640malloc_string(command);
641malloc_string(iso_mnt);
642malloc_string(iso_path);
643malloc_string(old_isodir);
644malloc_string(value);
645malloc_string(tmp);
646//  assert_string_is_neither_NULL_nor_zerolength(cfg_file);
647assert(bkpinfo != NULL);
648
649if (!cfgf) {
650    strcpy(cfg_file, g_mondo_cfg_file);
651} else {
652    strcpy(cfg_file, cfgf);
653}
654
655media_specified_by_user = bkpinfo->backup_media_type;   // or 'none', if not specified
656
657if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
658if (!strcmp(value, "cdstream")) {
659    bkpinfo->backup_media_type = cdstream;
660} else if (!strcmp(value, "cdr")) {
661    bkpinfo->backup_media_type = cdr;
662} else if (!strcmp(value, "cdrw")) {
663    bkpinfo->backup_media_type = cdrw;
664} else if (!strcmp(value, "dvd")) {
665    bkpinfo->backup_media_type = dvd;
666} else if (!strcmp(value, "usb")) {
667    bkpinfo->backup_media_type = usb;
668    bkpinfo->please_dont_eject = TRUE;
669} else if (!strcmp(value, "iso")) {
670
671// Patch by Conor Daly - 2004/07/12
672    bkpinfo->backup_media_type = iso;
673    if (am_I_in_disaster_recovery_mode()) {
674        /* Check to see if CD is already mounted before mounting it... */
675        if (!is_this_device_mounted("/dev/cdrom")) {
676            log_msg(2,
677                    "NB: CDROM device not mounted, mounting...");
678            run_program_and_log_output("mount /dev/cdrom "
679                                       MNT_CDROM, 1);
680        }
681        if (does_file_exist(MNT_CDROM "/archives/filelist.0")) {
682            bkpinfo->backup_media_type = cdr;
683            run_program_and_log_output("umount " MNT_CDROM, 1);
684            log_it
685                ("Re-jigging configuration AGAIN. CD-R, not ISO.");
686        }
687    }
688    if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
689            strcpy(bkpinfo->prefix,value);
690    } else {
691            strcpy(bkpinfo->prefix,STD_PREFIX);
692    }
693} else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
694    /* Stay compatible with previous versions by allowing nfs as an entry here */
695    bkpinfo->backup_media_type = netfs;
696    bkpinfo->please_dont_eject = TRUE;
697    if (read_cfg_var(cfg_file, "netfs-proto", value) == 0) {
698        mr_asprintf(&(bkpinfo->netfs_proto),"%s", value);
699    } else {
700        /* For compatibility, force protocol in old nfs case to be transparent */
701        mr_asprintf(&(bkpinfo->netfs_proto), "nfs");
702    }
703    if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
704            strcpy(bkpinfo->prefix,value);
705    } else {
706            strcpy(bkpinfo->prefix,STD_PREFIX);
707    }
708    if (strstr(call_program_and_get_last_line_of_output
709       ("cat /proc/cmdline"), "pxe")) {
710        /* We need to override prefix value in PXE mode as it's
711        * already done in start-netfs */
712        envtmp1 = getenv("imgname");
713        if (envtmp1 == NULL) {
714            fatal_error("no imgname variable in environment");
715        }
716        strcpy(bkpinfo->prefix,envtmp1);
717    }
718
719} else if (!strcmp(value, "tape")) {
720    bkpinfo->backup_media_type = tape;
721} else if (!strcmp(value, "udev")) {
722    bkpinfo->backup_media_type = udev;
723} else {
724    fatal_error("UNKNOWN bkp-media-type");
725}
726} else {
727fatal_error("backup-media-type not specified!");
728}
729if (bkpinfo->disaster_recovery) {
730    if (bkpinfo->backup_media_type == cdstream) {
731        sprintf(bkpinfo->media_device, "/dev/cdrom");
732//          bkpinfo->media_size[0] = -1;
733        bkpinfo->media_size[0] = 1999 * 1024;
734        bkpinfo->media_size[1] = 650;   /* good guess */
735    } else if (bkpinfo->backup_media_type == usb) {
736        envtmp1 = getenv("MRUSBDEV");
737        if (envtmp1 == NULL) {
738            if (read_cfg_var(cfg_file, "usb-dev", value)) {
739                fatal_error("Cannot get USB device name from cfg file");
740            }
741        } else {
742            strcpy(value,envtmp1);
743        }
744        sprintf(bkpinfo->media_device, "%s1", value);
745        sprintf(tmp, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
746        log_msg(2, tmp);
747    } else if (bkpinfo->backup_media_type == tape
748            || bkpinfo->backup_media_type == udev) {
749        if (read_cfg_var(cfg_file, "media-dev", value)) {
750            fatal_error("Cannot get tape device name from cfg file");
751        }
752        strcpy(bkpinfo->media_device, value);
753        read_cfg_var(cfg_file, "media-size", value);
754        bkpinfo->media_size[1] = atol(value);
755        sprintf(tmp, "Backup medium is TAPE --- dev=%s",
756                bkpinfo->media_device);
757        log_msg(2, tmp);
758    } else {
759        strcpy(bkpinfo->media_device, "/dev/cdrom");    /* we don't really need this var */
760        bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
761        bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
762        log_msg(2, "Backup medium is CD-R[W]");
763    }
764} else {
765    log_msg(2,
766        "Not in Disaster Recovery Mode. No need to derive device name from config file.");
767}
768
769read_cfg_var(cfg_file, "use-star", value);
770if (strstr(value, "yes")) {
771    bkpinfo->use_star = TRUE;
772    log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
773}
774
775read_cfg_var(cfg_file, "obdr", value);
776if (strstr(value, "TRUE")) {
777    bkpinfo->use_obdr = TRUE;
778    log_msg(1, "OBDR mode activated");
779}
780
781read_cfg_var(cfg_file, "acl", value);
782if (strstr(value, "TRUE")) {
783    mr_asprintf(&g_getfacl,"setfacl");
784    log_msg(1, "We will restore ACLs");
785    if (! find_home_of_exe("setfacl")) {
786        log_msg(1, "Unable to restore ACLs as no setfacl found");
787    }
788}
789read_cfg_var(cfg_file, "xattr", value);
790if (strstr(value, "TRUE")) {
791    mr_asprintf(&g_getfattr,"setfattr");
792    log_msg(1, "We will restore XATTRs");
793    if (! find_home_of_exe("setfattr")) {
794        log_msg(1, "Unable to restore XATTRs as no setfattr found");
795    }
796}
797
798if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
799bkpinfo->internal_tape_block_size = atol(value);
800log_msg(1, "Internal tape block size has been custom-set to %ld",
801        bkpinfo->internal_tape_block_size);
802} else {
803bkpinfo->internal_tape_block_size =
804    DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
805log_msg(1, "Internal tape block size = default (%ld)",
806        DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
807}
808
809read_cfg_var(cfg_file, "use-lzo", value);
810if (strstr(value, "yes")) {
811bkpinfo->use_lzo = TRUE;
812bkpinfo->use_gzip = FALSE;
813strcpy(bkpinfo->zip_exe, "lzop");
814strcpy(bkpinfo->zip_suffix, "lzo");
815} else {
816read_cfg_var(cfg_file, "use-gzip", value);
817if (strstr(value, "yes")) {
818    bkpinfo->use_lzo = FALSE;
819    bkpinfo->use_gzip = TRUE;
820    strcpy(bkpinfo->zip_exe, "gzip");
821    strcpy(bkpinfo->zip_suffix, "gz");
822} else {
823    read_cfg_var(cfg_file, "use-comp", value);
824    if (strstr(value, "yes")) {
825        bkpinfo->use_lzo = FALSE;
826        bkpinfo->use_gzip = FALSE;
827        strcpy(bkpinfo->zip_exe, "bzip2");
828        strcpy(bkpinfo->zip_suffix, "bz2");
829    } else {
830        bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
831    }
832}
833}
834
835value[0] = '\0';
836read_cfg_var(cfg_file, "differential", value);
837if (!strcmp(value, "yes") || !strcmp(value, "1")) {
838bkpinfo->differential = TRUE;
839}
840log_msg(2, "differential var = '%s'", value);
841if (bkpinfo->differential) {
842log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
843} else {
844log_msg(2, "This is a regular (full) backup");
845}
846
847read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
848if (tmp[0]
849||
850strstr(call_program_and_get_last_line_of_output
851       ("cat /proc/cmdline"), "donteject")) {
852bkpinfo->please_dont_eject = TRUE;
853log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
854}
855
856if (bkpinfo->backup_media_type == netfs) {
857    if (!cfgf) {
858        log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
859        log_msg(2, "netfs_remote_dir remains %s",
860                bkpinfo->netfs_remote_dir);
861        log_msg(2,
862                "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
863    } else {
864        read_cfg_var(g_mondo_cfg_file, "netfs-server-mount",
865                    bkpinfo->netfs_mount);
866        read_cfg_var(g_mondo_cfg_file, "netfs-server-path",
867                    bkpinfo->netfs_remote_dir);
868        log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
869        log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
870        log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
871    }
872    if (strstr(call_program_and_get_last_line_of_output
873        ("cat /proc/cmdline"), "pxe")) {
874        /* We need to override values in PXE mode as it's
875        * already done in start-netfs */
876        envtmp1 = getenv("netfsmount");
877        if (envtmp1 == NULL) {
878            fatal_error("no netfsmount variable in environment");
879        }
880        envtmp2 = getenv("dirimg");
881        if (envtmp2 == NULL) {
882            fatal_error("no dirimg variable in environment");
883        }
884        strcpy(bkpinfo->netfs_mount,envtmp1);
885        strcpy(bkpinfo->netfs_remote_dir,envtmp2);
886    }
887} else if (bkpinfo->backup_media_type == iso) {
888    /* Patch by Conor Daly 23-june-2004
889    * to correctly mount iso-dev and set a sensible
890    * isodir in disaster recovery mode
891    */
892    strcpy(old_isodir, bkpinfo->isodir);
893    read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
894    read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
895    sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
896    if (!bkpinfo->isodir[0]) {
897        strcpy(bkpinfo->isodir, old_isodir);
898    }
899    if (!bkpinfo->disaster_recovery) {
900        if (strcmp(old_isodir, bkpinfo->isodir)) {
901            log_it
902                ("user nominated isodir %s differs from archive %s, keeping user's choice\n",
903                old_isodir, bkpinfo->isodir);
904            strcpy(bkpinfo->isodir, old_isodir);
905        }
906    }
907    read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
908    log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir,
909            g_isodir_device);
910    if (bkpinfo->disaster_recovery) {
911        if (is_this_device_mounted(g_isodir_device)) {
912            log_msg(2, "NB: isodir is already mounted");
913            /* Find out where it's mounted */
914            sprintf(command,
915                    "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3",
916                    g_isodir_device);
917            log_it("command = %s", command);
918            log_it("res of it = %s",
919                call_program_and_get_last_line_of_output(command));
920            sprintf(iso_mnt, "%s",
921                    call_program_and_get_last_line_of_output(command));
922        } else {
923            sprintf(iso_mnt, "/tmp/isodir");
924            sprintf(tmp, "mkdir -p %s", iso_mnt);
925            run_program_and_log_output(tmp, 5);
926            sprintf(tmp, "mount %s %s", g_isodir_device, iso_mnt);
927            if (run_program_and_log_output(tmp, 3)) {
928                log_msg(1,
929                        "Unable to mount isodir. Perhaps this is really a CD backup?");
930                bkpinfo->backup_media_type = cdr;
931                strcpy(bkpinfo->media_device, "/dev/cdrom");    /* superfluous */
932                bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0';
933                if (mount_media()) {
934                    fatal_error
935                        ("Unable to mount isodir. Failed to mount CD-ROM as well.");
936                } else {
937                    log_msg(1,
938                            "You backed up to disk, then burned some CDs.");
939                }
940            }
941        }
942        /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
943        if (bkpinfo->backup_media_type == iso) {
944            sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
945        }
946    }
947}
948
949if (media_specified_by_user != none) {
950    if (g_restoring_live_from_cd) {
951        if (bkpinfo->backup_media_type != media_specified_by_user) {
952            log_msg(2,
953                    "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
954            interactively_obtain_media_parameters_from_user(FALSE);
955            media_specified_by_user = bkpinfo->backup_media_type;
956            get_cfg_file_from_archive();
957    /*
958        if (media_specified_by_user != cdr && media_specified_by_user == cdrw)
959            { g_restoring_live_from_cd = FALSE; }
960    */
961        }
962    }
963    bkpinfo->backup_media_type = media_specified_by_user;
964}
965g_backup_media_type = bkpinfo->backup_media_type;
966paranoid_free(value);
967paranoid_free(tmp);
968paranoid_free(command);
969paranoid_free(iso_mnt);
970paranoid_free(iso_path);
971paranoid_free(old_isodir);
972return (0);
973
974}
975
976/**************************************************************************
977*END_READ_CFG_FILE_INTO_BKPINFO                                          *
978**************************************************************************/
979
980
981
982
983/**
984 * Allow the user to edit the filelist and biggielist.
985 * The filelist is unlinked after it is read.
986 * @param bkpinfo The backup information structure. Fields used:
987 * - @c bkpinfo->backup_media_type
988 * - @c bkpinfo->isodir
989 * - @c bkpinfo->media_device
990 * - @c bkpinfo->tmpdir
991 * @return The filelist structure containing the information read from disk.
992 */
993struct
994s_node *process_filelist_and_biggielist()
995{
996struct s_node *filelist;
997
998/** add mallocs**/
999char *command;
1000char *tmp;
1001int res = 0;
1002pid_t pid;
1003bool extract_mountlist_stub = FALSE;
1004
1005assert(bkpinfo != NULL);
1006malloc_string(command);
1007malloc_string(tmp);
1008
1009/* If those files already exist, do not overwrite them later on */
1010if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
1011    extract_mountlist_stub = FALSE;
1012} else {
1013    extract_mountlist_stub = TRUE;
1014}
1015
1016if (does_file_exist(g_filelist_full)
1017&& does_file_exist(g_biggielist_txt)) {
1018    log_msg(1, "%s exists", g_filelist_full);
1019    log_msg(1, "%s exists", g_biggielist_txt);
1020    log_msg(2,
1021        "Filelist and biggielist already recovered from media. Yay!");
1022} else {
1023    getcwd(tmp, MAX_STR_LEN);
1024    chdir(bkpinfo->tmpdir);
1025    log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1026    log_to_screen("Extracting filelist and biggielist from media...");
1027    unlink("/tmp/filelist.full");
1028    unlink(FILELIST_FULL_STUB);
1029    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1030        sprintf(command,
1031            "tar -b %ld -zxf %s ./%s ./%s ./%s ./%s ./%s",
1032            bkpinfo->internal_tape_block_size,
1033            bkpinfo->media_device,
1034            MOUNTLIST_FNAME_STUB,
1035            BIGGIELIST_TXT_STUB,
1036            FILELIST_FULL_STUB,
1037            IWANTMYLVM_STUB,
1038            MONDO_CFG_FILE_STUB);
1039        log_msg(1, "tarcommand = %s", command);
1040        run_program_and_log_output(command, 1);
1041        if (!does_file_exist(FILELIST_FULL_STUB)) {
1042            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1043            log_msg(2, "pre-2.2.4 compatible mode on");
1044            sprintf(command,
1045                "tar -b %ld -zxf %s %s %s %s %s %s",
1046                bkpinfo->internal_tape_block_size,
1047                bkpinfo->media_device,
1048                MOUNTLIST_FNAME_STUB,
1049                BIGGIELIST_TXT_STUB,
1050                FILELIST_FULL_STUB,
1051                IWANTMYLVM_STUB,
1052                MONDO_CFG_FILE_STUB);
1053            log_msg(1, "tarcommand = %s", command);
1054            run_program_and_log_output(command, 1);
1055        }
1056    } else {
1057        log_msg(2,
1058            "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1059            bkpinfo->isodir);
1060        insist_on_this_cd_number(1);
1061        log_msg(2, "Back from iotcn");
1062        run_program_and_log_output("mount", 1);
1063        sprintf(command,
1064            "tar -zxf %s/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s",
1065            MNT_CDROM,
1066            MOUNTLIST_FNAME_STUB,
1067            BIGGIELIST_TXT_STUB,
1068            FILELIST_FULL_STUB,
1069            IWANTMYLVM_STUB,
1070            MONDO_CFG_FILE_STUB);
1071
1072        log_msg(1, "tarcommand = %s", command);
1073        run_program_and_log_output(command, 1);
1074        if (!does_file_exist(FILELIST_FULL_STUB)) {
1075            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1076            log_msg(2, "pre-2.2.4 compatible mode on");
1077            sprintf(command,
1078                "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1079                MNT_CDROM,
1080                MOUNTLIST_FNAME_STUB,
1081                BIGGIELIST_TXT_STUB,
1082                FILELIST_FULL_STUB,
1083                IWANTMYLVM_STUB,
1084                MONDO_CFG_FILE_STUB);
1085
1086            log_msg(1, "tarcommand = %s", command);
1087            run_program_and_log_output(command, 1);
1088        }
1089        if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1090            fatal_error
1091                ("all.tar.gz did not include " BIGGIELIST_TXT_STUB);
1092        }
1093        if (!does_file_exist(FILELIST_FULL_STUB)) {
1094            fatal_error
1095                ("all.tar.gz did not include " FILELIST_FULL_STUB);
1096        }
1097    }
1098    sprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1099        g_mondo_cfg_file);
1100    run_program_and_log_output(command, FALSE);
1101
1102    sprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1103        BIGGIELIST_TXT_STUB, g_biggielist_txt);
1104    log_msg(1, "command = %s", command);
1105    paranoid_system(command);
1106    sprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1107        FILELIST_FULL_STUB, g_filelist_full);
1108    log_msg(1, "command = %s", command);
1109    paranoid_system(command);
1110    }
1111
1112    if (am_I_in_disaster_recovery_mode()
1113    &&
1114    /* If it was there, do not overwrite it */
1115    (extract_mountlist_stub) 
1116    &&
1117    ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1118    {
1119        sprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1120            bkpinfo->tmpdir);
1121    paranoid_system(command);
1122    }
1123
1124    chdir(tmp);
1125
1126    if (!does_file_exist(g_biggielist_txt)) {
1127        log_msg(1, "Warning - %s not found", g_biggielist_txt);
1128    }
1129    if (!does_file_exist(g_filelist_full)) {
1130        log_msg(1, "Warning - %s does not exist", g_filelist_full);
1131    }
1132//  popup_and_OK("Wonderful.");
1133
1134    log_msg(2, "Forking");
1135    pid = fork();
1136    switch (pid) {
1137    case -1:
1138        fatal_error("Forking error");
1139        break;
1140
1141    case 0:
1142        log_to_screen("Pre-processing filelist");
1143        if (!does_file_exist(g_biggielist_txt)) {
1144            sprintf(command, "echo -n > %s", g_biggielist_txt);
1145            paranoid_system(command);
1146        }
1147        sprintf(command, "grep -E '^/dev/.*' %s > %s",
1148                g_biggielist_txt, g_filelist_imagedevs);
1149        paranoid_system(command);
1150        exit(0);
1151        break;
1152
1153    default:
1154        open_evalcall_form("Pre-processing filelist");
1155        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1156            usleep(100000);
1157            update_evalcall_form(0);
1158        }
1159    }
1160    close_evalcall_form();
1161
1162    log_msg(3, "loading filelist");
1163    filelist = load_filelist(g_filelist_full);
1164    log_msg(3, "deleting original filelist");
1165    unlink(g_filelist_full);
1166    if (g_text_mode) {
1167        printf("Restore which directory? --> ");
1168        fgets(tmp, sizeof(tmp), stdin);
1169        toggle_path_selection(filelist, tmp, TRUE);
1170        if (strlen(tmp) == 0) {
1171            res = 1;
1172        } else {
1173            res = 0;
1174        }
1175    } else {
1176        res = edit_filelist(filelist);
1177    }
1178    if (res) {
1179        log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1180        free_filelist(filelist);
1181        return (NULL);
1182    }
1183    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1184    close_evalcall_form();
1185
1186    // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1187    // file. The filelist.full file already contains the filename of EVERY
1188    // file backed up - regular and biggie files.
1189
1190    // However, we do want to make sure the imagedevs selected by the user
1191    // are flagged for restoring.
1192    if (length_of_file(g_imagedevs_restthese) > 2) {
1193        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1194                                      TRUE);
1195    }
1196
1197    paranoid_free(command);
1198    paranoid_free(tmp);
1199    return (filelist);
1200}
1201
1202/**************************************************************************
1203 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1204 **************************************************************************/
1205
1206
1207
1208
1209/**
1210 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1211 * The backup filename is the filename of the original with ".pristine" added.
1212 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1213 * @param filename The filename (absolute path) within @p path_root.
1214 * @return 0 for success, nonzero for failure.
1215 */
1216int backup_crucial_file(char *path_root, char *filename)
1217{
1218    char *tmp;
1219    char *command;
1220    int res;
1221
1222    malloc_string(tmp);
1223    malloc_string(command);
1224    assert(path_root != NULL);
1225    assert_string_is_neither_NULL_nor_zerolength(filename);
1226
1227    sprintf(tmp, "%s/%s", path_root, filename);
1228    sprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1229
1230    res = run_program_and_log_output(command, 5);
1231    paranoid_free(tmp);
1232    paranoid_free(command);
1233    return (res);
1234}
1235
1236void offer_to_make_initrd() {
1237
1238if (bkpinfo->restore_mode != nuke) {
1239    if (ask_me_yes_or_no
1240        ("You will now be able to re-generate your initrd.\nThis is especially useful if you changed of hardware configuration, cloned, made P2V, used multipath...\nDo you need to do it ?")) {
1241        log_msg(1,"Launching shell for manual initrd recreation");
1242        if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1243            popup_and_OK("You'll now be chrooted under your future / partition.\nEdit /etc/mkinitcpio.conf if needed and rebuild your initrd with the kernel preset name e.g.\nmkinitcpio -p kernel26\nThen type exit to finish.\n");
1244        } else {
1245            popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your initrd with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nThen type exit to finish.");
1246        }
1247        mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1248        if (!g_text_mode) {
1249            newtSuspend();
1250        }
1251        (void)system("chroot " MNT_RESTORING);
1252        if (!g_text_mode) {
1253            newtResume();
1254        }
1255        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1256    } else {
1257        return;
1258    }
1259} else {
1260    log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1261    log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1262}
1263}
1264
1265
1266/**
1267 * Install the user's boot loader in the MBR.
1268 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1269 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1270 * @return 0 for success, nonzero for failure.
1271 */
1272int run_boot_loader(bool offer_to_hack_scripts)
1273{
1274    int res;
1275    int retval = 0;
1276
1277  /** malloc *******/
1278    char *device;
1279    char *tmp = NULL;
1280    char *name;
1281    char *cmd = NULL;
1282
1283    malloc_string(device);
1284    malloc_string(name);
1285
1286    /* In order to have a working bootloader, we need to have all devices
1287     * ready in the chroot. If they are not there (udev) then copy them from
1288     * the current /dev location
1289     */
1290    mr_asprintf(&cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1291    run_program_and_log_output(cmd, 3);
1292    paranoid_free(cmd);
1293
1294    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1295    backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1296    backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1297    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1298    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1299    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1300    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1301    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1302    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1303    mr_asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1304    log_msg(2, tmp);
1305    paranoid_free(tmp);
1306    system("sync");
1307
1308    offer_to_make_initrd();
1309    if (!strcmp(name, "LILO")) {
1310        res = run_lilo(offer_to_hack_scripts);
1311    } else if (!strcmp(name, "ELILO")) {
1312        res = run_elilo(offer_to_hack_scripts);
1313    } else if (!strcmp(name, "GRUB")) {
1314        res = run_grub(offer_to_hack_scripts, device);
1315    } else if (!strcmp(name, "RAW")) {
1316        res = run_raw_mbr(offer_to_hack_scripts, device);
1317    }
1318#ifdef __FreeBSD__
1319    else if (!strcmp(name, "BOOT0")) {
1320        mr_asprintf(&tmp, "boot0cfg -B %s", device);
1321        res = run_program_and_log_output(tmp, FALSE);
1322        paranoid_free(tmp);
1323    } else {
1324        mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1325        if (!system(tmp)) {
1326            paranoid_free(tmp);
1327            mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1328            res = run_program_and_log_output(tmp, 3);
1329        } else {
1330            log_msg(1,
1331                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1332        }
1333        paranoid_free(tmp);
1334    }
1335#else
1336    else {
1337        log_to_screen
1338            ("Unable to determine type of boot loader. Defaulting to LILO.");
1339        res = run_lilo(offer_to_hack_scripts);
1340    }
1341#endif
1342    retval += res;
1343    if (res) {
1344        log_to_screen("Your boot loader returned an error");
1345    } else {
1346        log_to_screen("Your boot loader ran OK");
1347    }
1348    paranoid_free(device);
1349    paranoid_free(name);
1350    return (retval);
1351}
1352
1353/**************************************************************************
1354 *END_ RUN_BOOT_LOADER                                                    *
1355 **************************************************************************/
1356
1357
1358
1359/**
1360 * Attempt to find the user's editor.
1361 * @return The editor found ("vi" if none could be found).
1362 * @note The returned string points to static storage that will be overwritten with each call.
1363 */
1364char *find_my_editor(void)
1365{
1366    static char output[MAX_STR_LEN];
1367    if (find_home_of_exe("pico")) {
1368        strcpy(output, "pico");
1369    } else if (find_home_of_exe("nano")) {
1370        strcpy(output, "nano");
1371    } else if (find_home_of_exe("e3em")) {
1372        strcpy(output, "e3em");
1373    } else if (find_home_of_exe("e3vi")) {
1374        strcpy(output, "e3vi");
1375    } else {
1376        strcpy(output, "vi");
1377    }
1378    if (!find_home_of_exe(output)) {
1379        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1380    }
1381    return (output);
1382}
1383
1384
1385/**
1386 * Install GRUB on @p bd.
1387 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1388 * @param bd The boot device where GRUB is installed.
1389 * @return 0 for success, nonzero for failure.
1390 */
1391int run_grub(bool offer_to_run_stabgrub, char *bd)
1392{
1393  /** malloc **/
1394    char *command;
1395    char *boot_device;
1396    char *rootdev;
1397    char *rootdrive;
1398    char *conffile;
1399    char *tmp;
1400    char *editor;
1401
1402    int res;
1403    int done;
1404
1405    malloc_string(command);
1406    malloc_string(boot_device);
1407    malloc_string(tmp);
1408    malloc_string(editor);
1409    malloc_string(rootdev);
1410    malloc_string(rootdrive);
1411    malloc_string(conffile);
1412    assert_string_is_neither_NULL_nor_zerolength(bd);
1413    strcpy(editor, find_my_editor());
1414    strcpy(boot_device, bd);
1415
1416    if (!run_program_and_log_output("which grub-MR", FALSE)) {
1417        log_msg(1, "Yay! grub-MR found...");
1418        sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1419        log_msg(1, "command = %s", command);
1420    } else {
1421        sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1422                boot_device);
1423        log_msg(1, "WARNING - grub-MR not found; using grub-install");
1424    }
1425    if (offer_to_run_stabgrub
1426        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1427        /* interactive mode */
1428    {
1429        mvaddstr_and_log_it(g_currentY,
1430                            0,
1431                            "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB...                             ");
1432        for (done = FALSE; !done;) {
1433            popup_and_get_string("Boot device",
1434                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1435                                 boot_device, MAX_STR_LEN / 4);
1436            sprintf(command, "stabgrub-me %s", boot_device);
1437            res = run_program_and_log_output(command, 1);
1438            if (res) {
1439                popup_and_OK
1440                    ("GRUB installation failed. Please install manually using 'grub-install' or similar command. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1441                newtSuspend();
1442                system("chroot " MNT_RESTORING);
1443                newtResume();
1444                popup_and_OK("Thank you.");
1445            } else {
1446                done = TRUE;
1447            }
1448            popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
1449            if (!g_text_mode) {
1450                newtSuspend();
1451            }
1452            sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1453            paranoid_system(tmp);
1454            sprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1455            paranoid_system(tmp);
1456            if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1457                sprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1458            } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1459                sprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1460            }
1461            paranoid_system(tmp);
1462            sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1463            paranoid_system(tmp);
1464            if (!g_text_mode) {
1465                newtResume();
1466            }
1467        }
1468    } else
1469        /* nuke mode */
1470    {
1471        mvaddstr_and_log_it(g_currentY,
1472                            0,
1473                            "Running GRUB...                                                 ");
1474        log_it("%s",command);
1475        res = run_program_and_log_output(command, 1);
1476        if (res) {
1477            popup_and_OK
1478                ("Because of bugs in GRUB's own installer, GRUB was not installed properly. Please install the boot loader manually now, using this chroot()'ed shell prompt. Type 'exit' when you have finished.");
1479            newtSuspend();
1480            system("chroot " MNT_RESTORING);
1481            newtResume();
1482            popup_and_OK("Thank you.");
1483        }
1484    }
1485    if (res) {
1486        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1487        log_to_screen
1488            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1489        log_msg(1, "Type:-");
1490        log_msg(1, "    mount-me");
1491        log_msg(1, "    chroot " MNT_RESTORING);
1492        log_msg(1, "    mount /boot");
1493        log_msg(1, "    grub-install '(hd0)'");
1494        log_msg(1, "    exit");
1495        log_msg(1, "    unmount-me");
1496        log_msg(1,
1497                "If you're really stuck, please e-mail the mailing list.");
1498    } else {
1499        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1500    }
1501    paranoid_free(rootdev);
1502    paranoid_free(rootdrive);
1503    paranoid_free(conffile);
1504    paranoid_free(command);
1505    paranoid_free(boot_device);
1506    paranoid_free(tmp);
1507    paranoid_free(editor);
1508
1509    return (res);
1510}
1511
1512/**************************************************************************
1513 *END_RUN_GRUB                                                            *
1514 **************************************************************************/
1515
1516
1517/**
1518 * Install ELILO on the user's boot drive (determined by elilo.conf).
1519 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1520 * @return 0 for success, nonzero for failure.
1521 */
1522int run_elilo(bool offer_to_run_stabelilo)
1523{
1524  /** malloc **/
1525    char *command;
1526    char *tmp;
1527    char *editor;
1528
1529    int res;
1530    int done;
1531
1532    malloc_string(command);
1533    malloc_string(tmp);
1534    malloc_string(editor);
1535    strcpy(editor, find_my_editor());
1536    if (offer_to_run_stabelilo
1537        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1538
1539        /* interactive mode */
1540    {
1541        mvaddstr_and_log_it(g_currentY,
1542                            0,
1543                            "Modifying fstab and elilo.conf...                             ");
1544        sprintf(command, "stabelilo-me");
1545        res = run_program_and_log_output(command, 3);
1546        if (res) {
1547            popup_and_OK
1548                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1549            for (done = FALSE; !done;) {
1550                if (!g_text_mode) {
1551                    newtSuspend();
1552                }
1553                sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1554                paranoid_system(tmp);
1555                sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1556                paranoid_system(tmp);
1557                if (!g_text_mode) {
1558                    newtResume();
1559                }
1560//              newtCls();
1561                if (ask_me_yes_or_no("Edit them again?")) {
1562                    continue;
1563                }
1564                done = TRUE;
1565            }
1566        } else {
1567            log_to_screen("elilo.conf and fstab were modified OK");
1568        }
1569    } else
1570        /* nuke mode */
1571    {
1572        res = TRUE;
1573    }
1574    paranoid_free(command);
1575    paranoid_free(tmp);
1576    paranoid_free(editor);
1577    return (res);
1578}
1579
1580/**************************************************************************
1581 *END_RUN_ELILO                                                            *
1582 **************************************************************************/
1583
1584
1585/**
1586 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1587 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1588 * @return 0 for success, nonzero for failure.
1589 */
1590int run_lilo(bool offer_to_run_stablilo)
1591{
1592  /** malloc **/
1593    char *command;
1594    char *tmp;
1595    char *editor;
1596
1597    int res;
1598    int done;
1599    bool run_lilo_M = FALSE;
1600    malloc_string(command);
1601    malloc_string(tmp);
1602    malloc_string(editor);
1603
1604    if (!run_program_and_log_output
1605        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1606        run_lilo_M = TRUE;
1607    }
1608
1609    strcpy(editor, find_my_editor());
1610    if (offer_to_run_stablilo
1611        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1612
1613        /* interactive mode */
1614    {
1615        mvaddstr_and_log_it(g_currentY,
1616                            0,
1617                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1618        sprintf(command, "stablilo-me");
1619        res = run_program_and_log_output(command, 3);
1620        if (res) {
1621            popup_and_OK
1622                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1623            for (done = FALSE; !done;) {
1624                if (!g_text_mode) {
1625                    newtSuspend();
1626                }
1627                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1628                paranoid_system(tmp);
1629                sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1630                paranoid_system(tmp);
1631                if (!g_text_mode) {
1632                    newtResume();
1633                }
1634//              newtCls();
1635                if (ask_me_yes_or_no("Edit them again?")) {
1636                    continue;
1637                }
1638                res =
1639                    run_program_and_log_output("chroot " MNT_RESTORING
1640                                               " lilo -L", 3);
1641                if (res) {
1642                    res =
1643                        run_program_and_log_output("chroot " MNT_RESTORING
1644                                                   " lilo", 3);
1645                }
1646                if (res) {
1647                    done =
1648                        ask_me_yes_or_no
1649                        ("LILO failed. Re-edit system files?");
1650                } else {
1651                    done = TRUE;
1652                }
1653            }
1654        } else {
1655            log_to_screen("lilo.conf and fstab were modified OK");
1656        }
1657    } else
1658        /* nuke mode */
1659    {
1660        mvaddstr_and_log_it(g_currentY,
1661                            0,
1662                            "Running LILO...                                                 ");
1663        res =
1664            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1665                                       3);
1666        if (res) {
1667            res =
1668                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1669                                           3);
1670        }
1671        if (res) {
1672            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1673            log_to_screen
1674                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1675        } else {
1676            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1677        }
1678    }
1679    if (run_lilo_M) {
1680        run_program_and_log_output("chroot " MNT_RESTORING
1681                                   " lilo -M /dev/hda", 3);
1682        run_program_and_log_output("chroot " MNT_RESTORING
1683                                   " lilo -M /dev/sda", 3);
1684    }
1685    paranoid_free(command);
1686    paranoid_free(tmp);
1687    paranoid_free(editor);
1688    return (res);
1689}
1690
1691/**************************************************************************
1692 *END_RUN_LILO                                                            *
1693 **************************************************************************/
1694
1695
1696/**
1697 * Install a raw MBR onto @p bd.
1698 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1699 * @param bd The device to copy the stored MBR to.
1700 * @return 0 for success, nonzero for failure.
1701 */
1702int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1703{
1704  /** malloc **/
1705    char *command;
1706    char *boot_device;
1707    char *tmp;
1708    char *editor;
1709    int res;
1710    int done;
1711
1712    malloc_string(command);
1713    malloc_string(boot_device);
1714    malloc_string(tmp);
1715    malloc_string(editor);
1716    assert_string_is_neither_NULL_nor_zerolength(bd);
1717
1718    strcpy(editor, find_my_editor());
1719    strcpy(boot_device, bd);
1720    sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1721    log_msg(2, "run_raw_mbr() --- command='%s'", command);
1722
1723    if (offer_to_hack_scripts
1724        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1725        /* interactive mode */
1726    {
1727        mvaddstr_and_log_it(g_currentY, 0,
1728                            "Modifying fstab and restoring MBR...                           ");
1729        for (done = FALSE; !done;) {
1730            if (!run_program_and_log_output("which vi", FALSE)) {
1731                popup_and_OK("You will now edit fstab");
1732                if (!g_text_mode) {
1733                    newtSuspend();
1734                }
1735                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1736                paranoid_system(tmp);
1737                if (!g_text_mode) {
1738                    newtResume();
1739                }
1740//              newtCls();
1741            }
1742            popup_and_get_string("Boot device",
1743                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1744                                 boot_device, MAX_STR_LEN / 4);
1745            sprintf(command, "stabraw-me %s", boot_device);
1746            res = run_program_and_log_output(command, 3);
1747            if (res) {
1748                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1749            } else {
1750                done = TRUE;
1751            }
1752        }
1753    } else
1754        /* nuke mode */
1755    {
1756        mvaddstr_and_log_it(g_currentY, 0,
1757                            "Restoring MBR...                                               ");
1758        res = run_program_and_log_output(command, 3);
1759    }
1760    if (res) {
1761        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1762        log_to_screen
1763            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1764    } else {
1765        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1766    }
1767    paranoid_free(command);
1768    paranoid_free(boot_device);
1769    paranoid_free(tmp);
1770    paranoid_free(editor);
1771    return (res);
1772}
1773
1774/**************************************************************************
1775 *END_RUN_RAW_MBR                                                         *
1776 **************************************************************************/
1777
1778
1779
1780/**
1781 * malloc() and set sensible defaults for the mondorestore filename variables.
1782 * @param bkpinfo The backup information structure. Fields used:
1783 * - @c bkpinfo->tmpdir
1784 * - @c bkpinfo->disaster_recovery
1785 */
1786void setup_MR_global_filenames()
1787{
1788    char *temppath;
1789
1790    assert(bkpinfo != NULL);
1791
1792    malloc_string(g_biggielist_txt);
1793    malloc_string(g_filelist_full);
1794    malloc_string(g_filelist_imagedevs);
1795    malloc_string(g_imagedevs_restthese);
1796    malloc_string(g_mondo_cfg_file);
1797    malloc_string(g_mountlist_fname);
1798    malloc_string(g_mondo_home);
1799    /*
1800    malloc_string(g_tmpfs_mountpt);
1801    */
1802    malloc_string(g_isodir_device);
1803    malloc_string(g_isodir_format);
1804
1805    temppath = bkpinfo->tmpdir;
1806
1807    sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1808    sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1809    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1810//  sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1811    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1812            temppath);
1813    if (bkpinfo->disaster_recovery) {
1814        sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1815        sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1816    } else {
1817        sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1818        sprintf(g_mountlist_fname, "%s/%s", temppath,
1819                MOUNTLIST_FNAME_STUB);
1820    }
1821}
1822
1823/**************************************************************************
1824 *END_SET_GLOBAL_FILENAME                                                 *
1825 **************************************************************************/
1826
1827
1828/**
1829 * Copy @p input_file (containing the result of a compare) to @p output_file,
1830 * deleting spurious "changes" along the way.
1831 * @param output_file The output file to write with spurious changes removed.
1832 * @param input_file The input file, a list of changed files created by a compare.
1833 */
1834void streamline_changes_file(char *output_file, char *input_file)
1835{
1836    FILE *fin;
1837    FILE *fout;
1838  /** malloc **/
1839    char *incoming;
1840
1841    assert_string_is_neither_NULL_nor_zerolength(output_file);
1842    assert_string_is_neither_NULL_nor_zerolength(input_file);
1843    malloc_string(incoming);
1844
1845    if (!(fin = fopen(input_file, "r"))) {
1846        log_OS_error(input_file);
1847        return;
1848    }
1849    if (!(fout = fopen(output_file, "w"))) {
1850        fatal_error("cannot open output_file");
1851    }
1852    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1853         fgets(incoming, MAX_STR_LEN - 1, fin)) {
1854        if (strncmp(incoming, "etc/adjtime", 11)
1855            && strncmp(incoming, "etc/mtab", 8)
1856            && strncmp(incoming, "tmp/", 4)
1857            && strncmp(incoming, "boot/map", 8)
1858            && !strstr(incoming, "incheckentry")
1859            && strncmp(incoming, "etc/mail/statistics", 19)
1860            && strncmp(incoming, "var/", 4))
1861            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
1862    }
1863    paranoid_fclose(fout);
1864    paranoid_fclose(fin);
1865    paranoid_free(incoming);
1866}
1867
1868/**************************************************************************
1869 *END_STREAMLINE_CHANGES_FILE                                             *
1870 **************************************************************************/
1871
1872
1873/**
1874 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1875 */
1876void twenty_seconds_til_yikes()
1877{
1878    int i;
1879    /* MALLOC * */
1880    char *tmp;
1881
1882    malloc_string(tmp);
1883    if (does_file_exist("/tmp/NOPAUSE")) {
1884        return;
1885    }
1886    open_progress_form("CAUTION",
1887                       "Be advised: I am about to ERASE your hard disk(s)!",
1888                       "You may press Ctrl+Alt+Del to abort safely.",
1889                       "", 20);
1890    for (i = 0; i < 20; i++) {
1891        g_current_progress = i;
1892        sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1893        update_progress_form(tmp);
1894        sleep(1);
1895    }
1896    close_progress_form();
1897    paranoid_free(tmp);
1898}
1899
1900/**************************************************************************
1901 *END_TWENTY_SECONDS_TIL_YIKES                                            *
1902 **************************************************************************/
1903
1904
1905/**
1906 * Unmount all devices in @p p_external_copy_of_mountlist.
1907 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1908 * @return 0 for success, nonzero for failure.
1909 */
1910int unmount_all_devices(struct mountlist_itself
1911                        *p_external_copy_of_mountlist)
1912{
1913    struct mountlist_itself *mountlist;
1914    int retval = 0, lino, res = 0, i;
1915    char *command;
1916    char *tmp = NULL;
1917
1918    malloc_string(command);
1919    assert(p_external_copy_of_mountlist != NULL);
1920
1921    mountlist = malloc(sizeof(struct mountlist_itself));
1922    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1923           sizeof(struct mountlist_itself));
1924    sort_mountlist_by_mountpoint(mountlist, 0);
1925
1926    run_program_and_log_output("df -m", 3);
1927    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
1928    open_progress_form("Unmounting devices",
1929                       "Unmounting all devices that were mounted,",
1930                       "in preparation for the post-restoration reboot.",
1931                       "", mountlist->entries);
1932    chdir("/");
1933    for (i = 0;
1934         i < 10
1935         &&
1936         run_program_and_log_output
1937         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1938         i++) {
1939        sleep(1);
1940        log_msg(2, "Waiting for buffer() to finish");
1941    }
1942
1943    paranoid_system("sync");
1944
1945    mr_asprintf(&tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1946    if (run_program_and_log_output(tmp, FALSE)) {
1947        log_msg(1,
1948                "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1949    }
1950    paranoid_free(tmp);
1951    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1952        run_program_and_log_output("mkdir -p " MNT_RESTORING
1953                                   "/mnt/.boot.d", 5);
1954    }
1955
1956    /* Unmounting the local /proc and /sys first */
1957    run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1958    run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1959
1960    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1961        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1962            continue;
1963        }
1964        mr_asprintf(&tmp, "Unmounting device %s  ", mountlist->el[lino].device);
1965
1966        update_progress_form(tmp);
1967
1968        if (is_this_device_mounted(mountlist->el[lino].device)) {
1969            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1970                sprintf(command, "swapoff %s", mountlist->el[lino].device);
1971            } else {
1972                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1973                    sprintf(command, "umount %s/", MNT_RESTORING);
1974                    log_msg(3,
1975                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1976                } else {
1977                    sprintf(command, "umount " MNT_RESTORING "%s",
1978                            mountlist->el[lino].mountpoint);
1979
1980                    /* To support latest Ubuntu where /var is a separate FS
1981                     * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1982                     * we need to create some dirs under the real / before unmounting it */
1983                    if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1984                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1985                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1986                    }
1987                }
1988            }
1989            log_msg(10, "The 'umount' command is '%s'", command);
1990            res = run_program_and_log_output(command, 3);
1991        } else {
1992            mr_strcat(tmp, "...not mounted anyway :-) OK");
1993            res = 0;
1994        }
1995        g_current_progress++;
1996        if (res) {
1997            mr_strcat(tmp, "...Failed");
1998            retval++;
1999            log_to_screen(tmp);
2000        } else {
2001            log_msg(2, tmp);
2002        }
2003        paranoid_free(tmp);
2004    }
2005    close_progress_form();
2006    if (retval) {
2007        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2008    } else {
2009        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2010    }
2011    if (retval) {
2012        log_to_screen("Unable to unmount some of your partitions.");
2013    } else {
2014        log_to_screen("All partitions were unmounted OK.");
2015    }
2016    free(mountlist);
2017    paranoid_free(command);
2018    return (retval);
2019}
2020
2021/**************************************************************************
2022 *END_UNMOUNT_ALL_DEVICES                                                 *
2023 **************************************************************************/
2024
2025
2026
2027/**
2028 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2029 * to the ./tmp/ directory.
2030 * @param dev The tape device to read from.
2031 * @return 0 for success, nonzero for failure.
2032 */
2033int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2034{
2035    char *command;
2036    int res = 0;
2037
2038    malloc_string(command);
2039
2040    if (bkpinfo->use_obdr) {
2041        skip_obdr();
2042    } else {
2043        // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2044        set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2045    }
2046
2047    sprintf(command,
2048            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s",
2049            dev,
2050            bkpinfo->internal_tape_block_size,
2051            1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2052            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2053            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2054    log_msg(2, "command = '%s'", command);
2055    res = run_program_and_log_output(command, -1);
2056    if (res != 0) {
2057        if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2058            res = 0;
2059        } else {
2060            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2061            log_msg(2, "pre-2.2.4 compatible mode on");
2062            sprintf(command,
2063                    "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2064                    dev,
2065                    bkpinfo->internal_tape_block_size,
2066                    1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2067                    MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2068                    BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2069            log_msg(2, "command = '%s'", command);
2070            res = run_program_and_log_output(command, -1);
2071            if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2072                res = 0;
2073            }
2074        }
2075    }
2076    paranoid_free(command);
2077    return (res);
2078}
2079
2080
2081
2082/**
2083 * Get the configuration file from the floppy, tape, or CD.
2084 * @param bkpinfo The backup information structure. Fields used:
2085 * - @c bkpinfo->backup_media_type
2086 * - @c bkpinfo->media_device
2087 * - @c bkpinfo->tmpdir
2088 * @return 0 for success, nonzero for failure.
2089 */
2090int get_cfg_file_from_archive()
2091{
2092    int retval = 0;
2093
2094   /** malloc *****/
2095    char *device;
2096    char *command;
2097    char *cfg_file;
2098    char *mounted_cfgf_path;
2099    char *tmp;
2100    char *mountpt;
2101    char *ramdisk_fname;
2102    char *mountlist_file;
2103    bool extract_mountlist_stub = FALSE;
2104    bool extract_i_want_my_lvm = FALSE;
2105
2106    bool try_plan_B;
2107
2108    assert(bkpinfo != NULL);
2109    malloc_string(cfg_file);
2110    malloc_string(mounted_cfgf_path);
2111    malloc_string(mountpt);
2112    malloc_string(ramdisk_fname);
2113    malloc_string(mountlist_file);
2114    malloc_string(device);
2115    malloc_string(command);
2116    malloc_string(tmp);
2117    log_msg(2, "gcffa --- starting");
2118    log_to_screen("I'm thinking...");
2119    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2120    device[0] = '\0';
2121    chdir(bkpinfo->tmpdir);
2122    strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2123    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
2124    unlink(FILELIST_FULL_STUB);
2125    unlink(BIGGIELIST_TXT_STUB);
2126    sprintf(command, "mkdir -p %s", mountpt);
2127    run_program_and_log_output(command, FALSE);
2128
2129    sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2130    sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2131    //   make_hole_for_file( cfg_file );
2132    //   make_hole_for_file( mountlist_file);
2133    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2134
2135    if (!does_file_exist(cfg_file)) {
2136        log_msg(2, "gcffa --- we don't have cfg file yet.");
2137        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2138            try_plan_B = TRUE;
2139        } else {
2140            log_msg(2, "gcffa --- calling mount_media now :)");
2141            if (!mount_media()) {
2142                log_msg(2,
2143                        "gcffa --- managed to mount CD; so, no need for Plan B");
2144                try_plan_B = FALSE;
2145            } else {
2146                try_plan_B = TRUE;
2147            }
2148            if (what_number_cd_is_this() > 1) {
2149                insist_on_this_cd_number((g_current_media_number = 1));
2150            }
2151        }
2152        if (try_plan_B) {
2153            log_msg(2, "gcffa --- OK, switching to Plan B");
2154            chdir(bkpinfo->tmpdir);
2155            run_program_and_log_output("mkdir -p tmp", FALSE);
2156
2157            if (strlen(bkpinfo->media_device) == 0) {
2158                strcpy(bkpinfo->media_device, "/dev/st0");
2159                log_msg(2, "media_device is blank; assuming %s");
2160            }
2161            strcpy(tmp, bkpinfo->media_device);
2162            if (extract_cfg_file_and_mountlist_from_tape_dev
2163                (bkpinfo->media_device)) {
2164                strcpy(bkpinfo->media_device, "/dev/st0");
2165                if (extract_cfg_file_and_mountlist_from_tape_dev
2166                    (bkpinfo->media_device)) {
2167                    strcpy(bkpinfo->media_device, "/dev/osst0");
2168                    if (extract_cfg_file_and_mountlist_from_tape_dev
2169                        (bkpinfo->media_device)) {
2170                        strcpy(bkpinfo->media_device, "/dev/ht0");
2171                        if (extract_cfg_file_and_mountlist_from_tape_dev
2172                            (bkpinfo->media_device)) {
2173                            log_msg(3,
2174                                    "I tried lots of devices but none worked.");
2175                            strcpy(bkpinfo->media_device, tmp);
2176                        }
2177                    }
2178                }
2179            }
2180
2181            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2182                log_to_screen("Cannot find config info on media");
2183                return (1);
2184            }
2185        } else {
2186                if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2187                    extract_mountlist_stub = FALSE;
2188                } else {
2189                    extract_mountlist_stub = TRUE;
2190                }
2191                if (does_file_exist("/"IWANTMYLVM_STUB)) {
2192                    extract_i_want_my_lvm = FALSE;
2193                } else {
2194                    extract_i_want_my_lvm = TRUE;
2195                }
2196
2197                log_msg(2,
2198                        "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2199                sprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);    // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
2200                run_program_and_log_output(command, TRUE);
2201                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2202                    /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2203                    log_msg(2, "pre-2.2.4 compatible mode on");
2204                    sprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);  // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
2205                    run_program_and_log_output(command, TRUE);
2206                    if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2207                        fatal_error
2208                            ("Please reinsert the disk/CD and try again.");
2209                    }
2210                }
2211        }
2212    }
2213    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2214        log_msg(1, "gcffa --- great! We've got the config file");
2215        sprintf(tmp, "%s/%s",
2216                call_program_and_get_last_line_of_output("pwd"),
2217                MONDO_CFG_FILE_STUB);
2218        sprintf(command, "cp -f %s %s", tmp, cfg_file);
2219        log_it("%s",command);
2220        if (strcmp(tmp, cfg_file)
2221            && run_program_and_log_output(command, 1)) {
2222            log_msg(1,
2223                    "... but an error occurred when I tried to move it to %s",
2224                    cfg_file);
2225        } else {
2226            log_msg(1, "... and I moved it successfully to %s", cfg_file);
2227        }
2228        sprintf(command, "cp -f %s/%s %s",
2229            call_program_and_get_last_line_of_output("pwd"),
2230            MOUNTLIST_FNAME_STUB, mountlist_file);
2231        log_it("%s",command);
2232        if (extract_mountlist_stub) {
2233            if (strcmp(tmp, cfg_file)
2234                && run_program_and_log_output(command, 1)) {
2235                log_msg(1, "Failed to get mountlist");
2236            } else {
2237                log_msg(1, "Got mountlist too");
2238                sprintf(command, "cp -f %s %s", mountlist_file,
2239                        g_mountlist_fname);
2240                if (run_program_and_log_output(command, 1)) {
2241                    log_msg(1, "Failed to copy mountlist to /tmp");
2242                } else {
2243                    log_msg(1, "Copied mountlist to /tmp as well OK");
2244                    sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2245                    run_program_and_log_output(command, 1);
2246                }
2247            }
2248        }
2249    }
2250    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2251    if (!does_file_exist(cfg_file)) {
2252        log_it("%s",cfg_file);
2253        log_msg(1, "%s not found", cfg_file);
2254        log_to_screen
2255            ("Oh dear. Unable to recover configuration file from boot disk");
2256        return (1);
2257    }
2258
2259    log_to_screen("Recovered mondo-restore.cfg");
2260    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2261        log_to_screen("...but not mountlist.txt - a pity, really...");
2262    }
2263    else {
2264            /* Is this code really useful ??? */
2265        if (extract_mountlist_stub) {
2266            sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2267                    bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2268            run_program_and_log_output(command, FALSE);
2269        }
2270    }
2271
2272    sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2273    run_program_and_log_output(command, FALSE);
2274    if (extract_mountlist_stub) {
2275        sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2276        run_program_and_log_output(command, FALSE);
2277    }
2278    sprintf(command, "cp -f etc/raidtab /etc/");
2279    run_program_and_log_output(command, FALSE);
2280    if (extract_i_want_my_lvm) {
2281        sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2282        run_program_and_log_output(command, FALSE);
2283    }
2284    g_backup_media_type = bkpinfo->backup_media_type;
2285    paranoid_free(device);
2286    paranoid_free(command);
2287    paranoid_free(tmp);
2288    paranoid_free(cfg_file);
2289    paranoid_free(mounted_cfgf_path);
2290    paranoid_free(mountpt);
2291    paranoid_free(ramdisk_fname);
2292    paranoid_free(mountlist_file);
2293    return (retval);
2294}
2295
2296/**************************************************************************
2297 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2298 **************************************************************************/
2299
2300/* @} - end restoreUtilityGroup */
2301
2302
2303/***************************************************************************
2304 * F@                                                                      *
2305 * () -- Hugo Rabson                                  *
2306 *                                                                         *
2307 * Purpose:                                                                *
2308 *                                                                         *
2309 * Called by:                                                              *
2310 * Params:    -                      -                                     *
2311 * Returns:   0=success; nonzero=failure                                   *
2312 ***************************************************************************/
2313
2314
2315
2316void wait_until_software_raids_are_prepped(char *mdstat_file,
2317                                           int wait_for_percentage)
2318{
2319    struct raidlist_itself *raidlist;
2320    int unfinished_mdstat_devices = 9999, i;
2321    char *screen_message;
2322
2323    malloc_string(screen_message);
2324    raidlist = malloc(sizeof(struct raidlist_itself));
2325
2326    assert(wait_for_percentage <= 100);
2327    log_it("wait_until_software_raids_are_prepped");
2328    while (unfinished_mdstat_devices > 0) {
2329            // FIXME: Prefix '/dev/' should really be dynamic!
2330        if (parse_mdstat(raidlist, "/dev/")) {
2331            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2332            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2333            return;
2334        }
2335        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2336            if (raidlist->el[i].progress < wait_for_percentage) {
2337                unfinished_mdstat_devices++;
2338                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2339                {
2340                    continue;
2341                }
2342                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2343                sprintf(screen_message, "Sync'ing %s",
2344                        raidlist->el[i].raid_device);
2345                open_evalcall_form(screen_message);
2346                while (raidlist->el[i].progress < wait_for_percentage) {
2347                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2348                    update_evalcall_form(raidlist->el[i].progress);
2349                    sleep(2);
2350                    // FIXME: Prefix '/dev/' should really be dynamic!
2351                    if (parse_mdstat(raidlist, "/dev/")) {
2352                        break;
2353                    }
2354                }
2355                close_evalcall_form();
2356            }
2357        }
2358    }
2359    paranoid_free(screen_message);
2360    paranoid_free(raidlist);
2361}
2362
2363
Note: See TracBrowser for help on using the repository browser.