source: branches/3.0/mondo/src/mondorestore/mondo-rstr-tools.c @ 2944

Last change on this file since 2944 was 2944, checked in by Bruno Cornec, 9 years ago
  • Adds grub2 support (Michael Caerwyn mcaerwyn_at_gmail.com)
  • Property svn:keywords set to Id
File size: 72.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2944 2012-02-03 01:12:47Z 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 -d " 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 -d " 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, "netfs-server-user", value) == 0) {
704        mr_asprintf(&(bkpinfo->netfs_user),"%s", value);
705    }
706    if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
707            strcpy(bkpinfo->prefix,value);
708    } else {
709            strcpy(bkpinfo->prefix,STD_PREFIX);
710    }
711    if (strstr(call_program_and_get_last_line_of_output
712       ("cat /proc/cmdline"), "pxe")) {
713        /* We need to override prefix value in PXE mode as it's
714        * already done in start-netfs */
715        envtmp1 = getenv("imgname");
716        if (envtmp1 == NULL) {
717            fatal_error("no imgname variable in environment");
718        }
719        strcpy(bkpinfo->prefix,envtmp1);
720    }
721
722} else if (!strcmp(value, "tape")) {
723    bkpinfo->backup_media_type = tape;
724} else if (!strcmp(value, "udev")) {
725    bkpinfo->backup_media_type = udev;
726} else {
727    fatal_error("UNKNOWN bkp-media-type");
728}
729} else {
730fatal_error("backup-media-type not specified!");
731}
732if (bkpinfo->disaster_recovery) {
733    if (bkpinfo->backup_media_type == cdstream) {
734        sprintf(bkpinfo->media_device, "/dev/cdrom");
735//          bkpinfo->media_size[0] = -1;
736        bkpinfo->media_size[0] = 1999 * 1024;
737        bkpinfo->media_size[1] = 650;   /* good guess */
738    } else if (bkpinfo->backup_media_type == usb) {
739        envtmp1 = getenv("MRUSBDEV");
740        if (envtmp1 == NULL) {
741            if (read_cfg_var(cfg_file, "usb-dev", value)) {
742                fatal_error("Cannot get USB device name from cfg file");
743            }
744        } else {
745            strcpy(value,envtmp1);
746        }
747        sprintf(bkpinfo->media_device, "%s1", value);
748        sprintf(tmp, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
749        log_msg(2, tmp);
750    } else if (bkpinfo->backup_media_type == tape
751            || bkpinfo->backup_media_type == udev) {
752        if (read_cfg_var(cfg_file, "media-dev", value)) {
753            fatal_error("Cannot get tape device name from cfg file");
754        }
755        strcpy(bkpinfo->media_device, value);
756        read_cfg_var(cfg_file, "media-size", value);
757        bkpinfo->media_size[1] = atol(value);
758        sprintf(tmp, "Backup medium is TAPE --- dev=%s",
759                bkpinfo->media_device);
760        log_msg(2, tmp);
761    } else {
762        strcpy(bkpinfo->media_device, "/dev/cdrom");    /* we don't really need this var */
763        bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
764        bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
765        log_msg(2, "Backup medium is CD-R[W]");
766    }
767} else {
768    log_msg(2,
769        "Not in Disaster Recovery Mode. No need to derive device name from config file.");
770}
771
772read_cfg_var(cfg_file, "use-star", value);
773if (strstr(value, "yes")) {
774    bkpinfo->use_star = TRUE;
775    log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
776}
777
778read_cfg_var(cfg_file, "obdr", value);
779if (strstr(value, "TRUE")) {
780    bkpinfo->use_obdr = TRUE;
781    log_msg(1, "OBDR mode activated");
782}
783
784read_cfg_var(cfg_file, "acl", value);
785if (strstr(value, "TRUE")) {
786    mr_asprintf(&g_getfacl,"setfacl");
787    log_msg(1, "We will restore ACLs");
788    if (! find_home_of_exe("setfacl")) {
789        log_msg(1, "Unable to restore ACLs as no setfacl found");
790    }
791}
792read_cfg_var(cfg_file, "xattr", value);
793if (strstr(value, "TRUE")) {
794    mr_asprintf(&g_getfattr,"setfattr");
795    log_msg(1, "We will restore XATTRs");
796    if (! find_home_of_exe("setfattr")) {
797        log_msg(1, "Unable to restore XATTRs as no setfattr found");
798    }
799}
800
801if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
802bkpinfo->internal_tape_block_size = atol(value);
803log_msg(1, "Internal tape block size has been custom-set to %ld",
804        bkpinfo->internal_tape_block_size);
805} else {
806bkpinfo->internal_tape_block_size =
807    DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
808log_msg(1, "Internal tape block size = default (%ld)",
809        DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
810}
811
812read_cfg_var(cfg_file, "use-lzo", value);
813if (strstr(value, "yes")) {
814bkpinfo->use_lzo = TRUE;
815bkpinfo->use_gzip = FALSE;
816strcpy(bkpinfo->zip_exe, "lzop");
817strcpy(bkpinfo->zip_suffix, "lzo");
818} else {
819read_cfg_var(cfg_file, "use-gzip", value);
820if (strstr(value, "yes")) {
821    bkpinfo->use_lzo = FALSE;
822    bkpinfo->use_gzip = TRUE;
823    strcpy(bkpinfo->zip_exe, "gzip");
824    strcpy(bkpinfo->zip_suffix, "gz");
825} else {
826    read_cfg_var(cfg_file, "use-comp", value);
827    if (strstr(value, "yes")) {
828        bkpinfo->use_lzo = FALSE;
829        bkpinfo->use_gzip = FALSE;
830        strcpy(bkpinfo->zip_exe, "bzip2");
831        strcpy(bkpinfo->zip_suffix, "bz2");
832    } else {
833        bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
834    }
835}
836}
837
838value[0] = '\0';
839read_cfg_var(cfg_file, "differential", value);
840if (!strcmp(value, "yes") || !strcmp(value, "1")) {
841bkpinfo->differential = TRUE;
842}
843log_msg(2, "differential var = '%s'", value);
844if (bkpinfo->differential) {
845log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
846} else {
847log_msg(2, "This is a regular (full) backup");
848}
849
850read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
851if (tmp[0]
852||
853strstr(call_program_and_get_last_line_of_output
854       ("cat /proc/cmdline"), "donteject")) {
855bkpinfo->please_dont_eject = TRUE;
856log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
857}
858
859if (bkpinfo->backup_media_type == netfs) {
860    if (!cfgf) {
861        log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
862        log_msg(2, "netfs_remote_dir remains %s",
863                bkpinfo->netfs_remote_dir);
864        log_msg(2,
865                "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
866    } else {
867        read_cfg_var(g_mondo_cfg_file, "netfs-server-mount",
868                    bkpinfo->netfs_mount);
869        read_cfg_var(g_mondo_cfg_file, "netfs-server-path",
870                    bkpinfo->netfs_remote_dir);
871        log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
872        log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
873        if (bkpinfo->netfs_user) {
874            log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
875        }
876        log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
877    }
878    if (strstr(call_program_and_get_last_line_of_output
879        ("cat /proc/cmdline"), "pxe")) {
880        /* We need to override values in PXE mode as it's
881        * already done in start-netfs */
882        envtmp1 = getenv("netfsmount");
883        if (envtmp1 == NULL) {
884            fatal_error("no netfsmount variable in environment");
885        }
886        envtmp2 = getenv("dirimg");
887        if (envtmp2 == NULL) {
888            fatal_error("no dirimg variable in environment");
889        }
890        strcpy(bkpinfo->netfs_mount,envtmp1);
891        strcpy(bkpinfo->netfs_remote_dir,envtmp2);
892    }
893} else if (bkpinfo->backup_media_type == iso) {
894    /* Patch by Conor Daly 23-june-2004
895    * to correctly mount iso-dev and set a sensible
896    * isodir in disaster recovery mode
897    */
898    strcpy(old_isodir, bkpinfo->isodir);
899    read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
900    read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
901    sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
902    if (!bkpinfo->isodir[0]) {
903        strcpy(bkpinfo->isodir, old_isodir);
904    }
905    if (!bkpinfo->disaster_recovery) {
906        if (strcmp(old_isodir, bkpinfo->isodir)) {
907            log_it
908                ("user nominated isodir %s differs from archive %s, keeping user's choice\n",
909                old_isodir, bkpinfo->isodir);
910            strcpy(bkpinfo->isodir, old_isodir);
911        }
912    }
913    read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
914    log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir,
915            g_isodir_device);
916    if (bkpinfo->disaster_recovery) {
917        if (is_this_device_mounted(g_isodir_device)) {
918            log_msg(2, "NB: isodir is already mounted");
919            /* Find out where it's mounted */
920            sprintf(command,
921                    "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3",
922                    g_isodir_device);
923            log_it("command = %s", command);
924            log_it("res of it = %s",
925                call_program_and_get_last_line_of_output(command));
926            sprintf(iso_mnt, "%s",
927                    call_program_and_get_last_line_of_output(command));
928        } else {
929            sprintf(iso_mnt, "/tmp/isodir");
930            sprintf(tmp, "mkdir -p %s", iso_mnt);
931            run_program_and_log_output(tmp, 5);
932            sprintf(tmp, "mount %s %s", g_isodir_device, iso_mnt);
933            if (run_program_and_log_output(tmp, 3)) {
934                log_msg(1,
935                        "Unable to mount isodir. Perhaps this is really a CD backup?");
936                bkpinfo->backup_media_type = cdr;
937                strcpy(bkpinfo->media_device, "/dev/cdrom");    /* superfluous */
938                bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0';
939                if (mount_media()) {
940                    fatal_error
941                        ("Unable to mount isodir. Failed to mount CD-ROM as well.");
942                } else {
943                    log_msg(1,
944                            "You backed up to disk, then burned some CDs.");
945                }
946            }
947        }
948        /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
949        if (bkpinfo->backup_media_type == iso) {
950            sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
951        }
952    }
953}
954
955if (media_specified_by_user != none) {
956    if (g_restoring_live_from_cd) {
957        if (bkpinfo->backup_media_type != media_specified_by_user) {
958            log_msg(2,
959                    "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
960            interactively_obtain_media_parameters_from_user(FALSE);
961            media_specified_by_user = bkpinfo->backup_media_type;
962            get_cfg_file_from_archive();
963    /*
964        if (media_specified_by_user != cdr && media_specified_by_user == cdrw)
965            { g_restoring_live_from_cd = FALSE; }
966    */
967        }
968    }
969    bkpinfo->backup_media_type = media_specified_by_user;
970}
971g_backup_media_type = bkpinfo->backup_media_type;
972paranoid_free(value);
973paranoid_free(tmp);
974paranoid_free(command);
975paranoid_free(iso_mnt);
976paranoid_free(iso_path);
977paranoid_free(old_isodir);
978return (0);
979
980}
981
982/**************************************************************************
983*END_READ_CFG_FILE_INTO_BKPINFO                                          *
984**************************************************************************/
985
986
987
988
989/**
990 * Allow the user to edit the filelist and biggielist.
991 * The filelist is unlinked after it is read.
992 * @param bkpinfo The backup information structure. Fields used:
993 * - @c bkpinfo->backup_media_type
994 * - @c bkpinfo->isodir
995 * - @c bkpinfo->media_device
996 * - @c bkpinfo->tmpdir
997 * @return The filelist structure containing the information read from disk.
998 */
999struct
1000s_node *process_filelist_and_biggielist()
1001{
1002struct s_node *filelist;
1003
1004/** add mallocs**/
1005char *command;
1006char *tmp;
1007int res = 0;
1008pid_t pid;
1009bool extract_mountlist_stub = FALSE;
1010
1011assert(bkpinfo != NULL);
1012malloc_string(command);
1013malloc_string(tmp);
1014
1015/* If those files already exist, do not overwrite them later on */
1016if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
1017    extract_mountlist_stub = FALSE;
1018} else {
1019    extract_mountlist_stub = TRUE;
1020}
1021
1022if (does_file_exist(g_filelist_full)
1023&& does_file_exist(g_biggielist_txt)) {
1024    log_msg(1, "%s exists", g_filelist_full);
1025    log_msg(1, "%s exists", g_biggielist_txt);
1026    log_msg(2,
1027        "Filelist and biggielist already recovered from media. Yay!");
1028} else {
1029    getcwd(tmp, MAX_STR_LEN);
1030    chdir(bkpinfo->tmpdir);
1031    log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1032    log_to_screen("Extracting filelist and biggielist from media...");
1033    unlink("/tmp/filelist.full");
1034    unlink(FILELIST_FULL_STUB);
1035    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1036        sprintf(command,
1037            "tar -b %ld -zxf %s ./%s ./%s ./%s ./%s ./%s",
1038            bkpinfo->internal_tape_block_size,
1039            bkpinfo->media_device,
1040            MOUNTLIST_FNAME_STUB,
1041            BIGGIELIST_TXT_STUB,
1042            FILELIST_FULL_STUB,
1043            IWANTMYLVM_STUB,
1044            MONDO_CFG_FILE_STUB);
1045        log_msg(1, "tarcommand = %s", command);
1046        run_program_and_log_output(command, 1);
1047        if (!does_file_exist(FILELIST_FULL_STUB)) {
1048            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1049            log_msg(2, "pre-2.2.4 compatible mode on");
1050            sprintf(command,
1051                "tar -b %ld -zxf %s %s %s %s %s %s",
1052                bkpinfo->internal_tape_block_size,
1053                bkpinfo->media_device,
1054                MOUNTLIST_FNAME_STUB,
1055                BIGGIELIST_TXT_STUB,
1056                FILELIST_FULL_STUB,
1057                IWANTMYLVM_STUB,
1058                MONDO_CFG_FILE_STUB);
1059            log_msg(1, "tarcommand = %s", command);
1060            run_program_and_log_output(command, 1);
1061        }
1062    } else {
1063        log_msg(2,
1064            "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1065            bkpinfo->isodir);
1066        insist_on_this_cd_number(1);
1067        log_msg(2, "Back from iotcn");
1068        run_program_and_log_output("mount", 1);
1069        sprintf(command,
1070            "tar -zxf %s/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s",
1071            MNT_CDROM,
1072            MOUNTLIST_FNAME_STUB,
1073            BIGGIELIST_TXT_STUB,
1074            FILELIST_FULL_STUB,
1075            IWANTMYLVM_STUB,
1076            MONDO_CFG_FILE_STUB);
1077
1078        log_msg(1, "tarcommand = %s", command);
1079        run_program_and_log_output(command, 1);
1080        if (!does_file_exist(FILELIST_FULL_STUB)) {
1081            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1082            log_msg(2, "pre-2.2.4 compatible mode on");
1083            sprintf(command,
1084                "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1085                MNT_CDROM,
1086                MOUNTLIST_FNAME_STUB,
1087                BIGGIELIST_TXT_STUB,
1088                FILELIST_FULL_STUB,
1089                IWANTMYLVM_STUB,
1090                MONDO_CFG_FILE_STUB);
1091
1092            log_msg(1, "tarcommand = %s", command);
1093            run_program_and_log_output(command, 1);
1094        }
1095        if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1096            fatal_error
1097                ("all.tar.gz did not include " BIGGIELIST_TXT_STUB);
1098        }
1099        if (!does_file_exist(FILELIST_FULL_STUB)) {
1100            fatal_error
1101                ("all.tar.gz did not include " FILELIST_FULL_STUB);
1102        }
1103    }
1104    sprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1105        g_mondo_cfg_file);
1106    run_program_and_log_output(command, FALSE);
1107
1108    sprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1109        BIGGIELIST_TXT_STUB, g_biggielist_txt);
1110    log_msg(1, "command = %s", command);
1111    paranoid_system(command);
1112    sprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1113        FILELIST_FULL_STUB, g_filelist_full);
1114    log_msg(1, "command = %s", command);
1115    paranoid_system(command);
1116    }
1117
1118    if (am_I_in_disaster_recovery_mode()
1119    &&
1120    /* If it was there, do not overwrite it */
1121    (extract_mountlist_stub) 
1122    &&
1123    ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1124    {
1125        sprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1126            bkpinfo->tmpdir);
1127    paranoid_system(command);
1128    }
1129
1130    chdir(tmp);
1131
1132    if (!does_file_exist(g_biggielist_txt)) {
1133        log_msg(1, "Warning - %s not found", g_biggielist_txt);
1134    }
1135    if (!does_file_exist(g_filelist_full)) {
1136        log_msg(1, "Warning - %s does not exist", g_filelist_full);
1137    }
1138//  popup_and_OK("Wonderful.");
1139
1140    log_msg(2, "Forking");
1141    pid = fork();
1142    switch (pid) {
1143    case -1:
1144        fatal_error("Forking error");
1145        break;
1146
1147    case 0:
1148        log_to_screen("Pre-processing filelist");
1149        if (!does_file_exist(g_biggielist_txt)) {
1150            sprintf(command, "echo -n > %s", g_biggielist_txt);
1151            paranoid_system(command);
1152        }
1153        sprintf(command, "grep -E '^/dev/.*' %s > %s",
1154                g_biggielist_txt, g_filelist_imagedevs);
1155        paranoid_system(command);
1156        exit(0);
1157        break;
1158
1159    default:
1160        open_evalcall_form("Pre-processing filelist");
1161        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1162            usleep(100000);
1163            update_evalcall_form(0);
1164        }
1165    }
1166    close_evalcall_form();
1167
1168    log_msg(3, "loading filelist");
1169    filelist = load_filelist(g_filelist_full);
1170    log_msg(3, "deleting original filelist");
1171    unlink(g_filelist_full);
1172    if (g_text_mode) {
1173        printf("Restore which directory? --> ");
1174        fgets(tmp, sizeof(tmp), stdin);
1175        toggle_path_selection(filelist, tmp, TRUE);
1176        if (strlen(tmp) == 0) {
1177            res = 1;
1178        } else {
1179            res = 0;
1180        }
1181    } else {
1182        res = edit_filelist(filelist);
1183    }
1184    if (res) {
1185        log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1186        free_filelist(filelist);
1187        return (NULL);
1188    }
1189    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1190    close_evalcall_form();
1191
1192    // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1193    // file. The filelist.full file already contains the filename of EVERY
1194    // file backed up - regular and biggie files.
1195
1196    // However, we do want to make sure the imagedevs selected by the user
1197    // are flagged for restoring.
1198    if (length_of_file(g_imagedevs_restthese) > 2) {
1199        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1200                                      TRUE);
1201    }
1202
1203    paranoid_free(command);
1204    paranoid_free(tmp);
1205    return (filelist);
1206}
1207
1208/**************************************************************************
1209 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1210 **************************************************************************/
1211
1212
1213
1214
1215/**
1216 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1217 * The backup filename is the filename of the original with ".pristine" added.
1218 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1219 * @param filename The filename (absolute path) within @p path_root.
1220 * @return 0 for success, nonzero for failure.
1221 */
1222int backup_crucial_file(char *path_root, char *filename)
1223{
1224    char *tmp;
1225    char *command;
1226    int res;
1227
1228    malloc_string(tmp);
1229    malloc_string(command);
1230    assert(path_root != NULL);
1231    assert_string_is_neither_NULL_nor_zerolength(filename);
1232
1233    sprintf(tmp, "%s/%s", path_root, filename);
1234    sprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1235
1236    res = run_program_and_log_output(command, 5);
1237    paranoid_free(tmp);
1238    paranoid_free(command);
1239    return (res);
1240}
1241
1242void offer_to_make_initrd() {
1243
1244if (bkpinfo->restore_mode != nuke) {
1245    if (ask_me_yes_or_no
1246        ("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 ?")) {
1247        log_msg(1,"Launching shell for manual initrd recreation");
1248        if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1249            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");
1250        } else {
1251            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.");
1252        }
1253        mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1254        if (!g_text_mode) {
1255            newtSuspend();
1256        }
1257        (void)system("chroot " MNT_RESTORING);
1258        if (!g_text_mode) {
1259            newtResume();
1260        }
1261        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1262    } else {
1263        return;
1264    }
1265} else {
1266    log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1267    log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1268}
1269}
1270
1271
1272/**
1273 * Install the user's boot loader in the MBR.
1274 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1275 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1276 * @return 0 for success, nonzero for failure.
1277 */
1278int run_boot_loader(bool offer_to_hack_scripts)
1279{
1280    int res;
1281    int retval = 0;
1282
1283  /** malloc *******/
1284    char *device;
1285    char *tmp = NULL;
1286    char *name;
1287    char *cmd = NULL;
1288
1289    malloc_string(device);
1290    malloc_string(name);
1291
1292    /* In order to have a working bootloader, we need to have all devices
1293     * ready in the chroot. If they are not there (udev) then copy them from
1294     * the current /dev location
1295     */
1296    mr_asprintf(&cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1297    run_program_and_log_output(cmd, 3);
1298    paranoid_free(cmd);
1299
1300    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1301    backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1302    backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1303    backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
1304    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1305    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1306    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1307    backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
1308    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1309    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1310    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1311    mr_asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1312    log_msg(2, tmp);
1313    paranoid_free(tmp);
1314    system("sync");
1315
1316    offer_to_make_initrd();
1317    if (!strcmp(name, "LILO")) {
1318        res = run_lilo(offer_to_hack_scripts);
1319    } else if (!strcmp(name, "ELILO")) {
1320        res = run_elilo(offer_to_hack_scripts);
1321    } else if (!strcmp(name, "GRUB")) {
1322        res = run_grub(offer_to_hack_scripts, device);
1323    } else if (!strcmp(name, "RAW")) {
1324        res = run_raw_mbr(offer_to_hack_scripts, device);
1325    }
1326#ifdef __FreeBSD__
1327    else if (!strcmp(name, "BOOT0")) {
1328        mr_asprintf(&tmp, "boot0cfg -B %s", device);
1329        res = run_program_and_log_output(tmp, FALSE);
1330        paranoid_free(tmp);
1331    } else {
1332        mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1333        if (!system(tmp)) {
1334            paranoid_free(tmp);
1335            mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1336            res = run_program_and_log_output(tmp, 3);
1337        } else {
1338            log_msg(1,
1339                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1340        }
1341        paranoid_free(tmp);
1342    }
1343#else
1344    else {
1345        log_to_screen
1346            ("Unable to determine type of boot loader. Defaulting to LILO.");
1347        res = run_lilo(offer_to_hack_scripts);
1348    }
1349#endif
1350    retval += res;
1351    if (res) {
1352        log_to_screen("Your boot loader returned an error");
1353    } else {
1354        log_to_screen("Your boot loader ran OK");
1355    }
1356    paranoid_free(device);
1357    paranoid_free(name);
1358    return (retval);
1359}
1360
1361/**************************************************************************
1362 *END_ RUN_BOOT_LOADER                                                    *
1363 **************************************************************************/
1364
1365
1366
1367/**
1368 * Attempt to find the user's editor.
1369 * @return The editor found ("vi" if none could be found).
1370 * @note The returned string points to static storage that will be overwritten with each call.
1371 */
1372char *find_my_editor(void)
1373{
1374    static char output[MAX_STR_LEN];
1375    if (find_home_of_exe("pico")) {
1376        strcpy(output, "pico");
1377    } else if (find_home_of_exe("nano")) {
1378        strcpy(output, "nano");
1379    } else if (find_home_of_exe("e3em")) {
1380        strcpy(output, "e3em");
1381    } else if (find_home_of_exe("e3vi")) {
1382        strcpy(output, "e3vi");
1383    } else {
1384        strcpy(output, "vi");
1385    }
1386    if (!find_home_of_exe(output)) {
1387        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1388    }
1389    return (output);
1390}
1391
1392
1393/**
1394 * Install GRUB on @p bd.
1395 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1396 * @param bd The boot device where GRUB is installed.
1397 * @return 0 for success, nonzero for failure.
1398 */
1399int run_grub(bool offer_to_run_stabgrub, char *bd)
1400{
1401  /** malloc **/
1402    char *command;
1403    char *boot_device;
1404    char *rootdev;
1405    char *rootdrive;
1406    char *conffile;
1407    char *tmp;
1408    char *editor;
1409
1410    int res;
1411    int done;
1412
1413    malloc_string(command);
1414    malloc_string(boot_device);
1415    malloc_string(tmp);
1416    malloc_string(editor);
1417    malloc_string(rootdev);
1418    malloc_string(rootdrive);
1419    malloc_string(conffile);
1420    assert_string_is_neither_NULL_nor_zerolength(bd);
1421    strcpy(editor, find_my_editor());
1422    strcpy(boot_device, bd);
1423
1424    if (!run_program_and_log_output("which grub-MR", FALSE)) {
1425        log_msg(1, "Yay! grub-MR found...");
1426        sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1427        log_msg(1, "command = %s", command);
1428    } else {
1429        sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1430                boot_device);
1431        log_msg(1, "WARNING - grub-MR not found; using grub-install");
1432    }
1433    if (offer_to_run_stabgrub
1434        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1435        /* interactive mode */
1436    {
1437        mvaddstr_and_log_it(g_currentY,
1438                            0,
1439                            "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB...                             ");
1440        for (done = FALSE; !done;) {
1441            popup_and_get_string("Boot device",
1442                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1443                                 boot_device, MAX_STR_LEN / 4);
1444            sprintf(command, "stabgrub-me %s", boot_device);
1445            res = run_program_and_log_output(command, 1);
1446            if (res) {
1447                popup_and_OK
1448                    ("GRUB installation failed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
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                } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1461                    sprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1462                }
1463                paranoid_system(tmp);
1464                if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1465                    sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1466                } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1467                    sprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1468                                }
1469                paranoid_system(tmp);
1470                if (!g_text_mode) {
1471                    newtResume();
1472                }
1473                sprintf(command, "stabgrub-me %s", boot_device);
1474                res = run_program_and_log_output(command, 1);
1475                if (res) {
1476                    popup_and_OK
1477                        ("GRUB installation failed. Please fix the conf files so that a manual install using 'grub-install' or similar command works. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1478                    newtSuspend();
1479                    system("chroot " MNT_RESTORING);
1480                    newtResume();
1481                    popup_and_OK("Thank you.");
1482                } else {
1483                    popup_and_OK("GRUB is now installed correctly");
1484                    done = TRUE;
1485                }
1486            } else {
1487                done = TRUE;
1488            }
1489        }
1490    } else
1491        /* nuke mode */
1492    {
1493        mvaddstr_and_log_it(g_currentY,
1494                            0,
1495                            "Running GRUB...                                                 ");
1496        log_it("%s",command);
1497        res = run_program_and_log_output(command, 1);
1498        if (res) {
1499            popup_and_OK
1500                ("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.");
1501            newtSuspend();
1502            system("chroot " MNT_RESTORING);
1503            newtResume();
1504            popup_and_OK("Thank you.");
1505        }
1506    }
1507    if (res) {
1508        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1509        log_to_screen
1510            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1511        log_msg(1, "Type:-");
1512        log_msg(1, "    mount-me");
1513        log_msg(1, "    chroot " MNT_RESTORING);
1514        log_msg(1, "    mount /boot");
1515        log_msg(1, "    grub-install '(hd0)'");
1516        log_msg(1, "    exit");
1517        log_msg(1, "    unmount-me");
1518        log_msg(1,
1519                "If you're really stuck, please e-mail the mailing list.");
1520    } else {
1521        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1522    }
1523    paranoid_free(rootdev);
1524    paranoid_free(rootdrive);
1525    paranoid_free(conffile);
1526    paranoid_free(command);
1527    paranoid_free(boot_device);
1528    paranoid_free(tmp);
1529    paranoid_free(editor);
1530
1531    return (res);
1532}
1533
1534/**************************************************************************
1535 *END_RUN_GRUB                                                            *
1536 **************************************************************************/
1537
1538
1539/**
1540 * Install ELILO on the user's boot drive (determined by elilo.conf).
1541 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1542 * @return 0 for success, nonzero for failure.
1543 */
1544int run_elilo(bool offer_to_run_stabelilo)
1545{
1546  /** malloc **/
1547    char *command;
1548    char *tmp;
1549    char *editor;
1550
1551    int res;
1552    int done;
1553
1554    malloc_string(command);
1555    malloc_string(tmp);
1556    malloc_string(editor);
1557    strcpy(editor, find_my_editor());
1558    if (offer_to_run_stabelilo
1559        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1560
1561        /* interactive mode */
1562    {
1563        mvaddstr_and_log_it(g_currentY,
1564                            0,
1565                            "Modifying fstab and elilo.conf...                             ");
1566        sprintf(command, "stabelilo-me");
1567        res = run_program_and_log_output(command, 3);
1568        if (res) {
1569            popup_and_OK
1570                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1571            for (done = FALSE; !done;) {
1572                if (!g_text_mode) {
1573                    newtSuspend();
1574                }
1575                sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1576                paranoid_system(tmp);
1577                sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1578                paranoid_system(tmp);
1579                if (!g_text_mode) {
1580                    newtResume();
1581                }
1582//              newtCls();
1583                if (ask_me_yes_or_no("Edit them again?")) {
1584                    continue;
1585                }
1586                done = TRUE;
1587            }
1588        } else {
1589            log_to_screen("elilo.conf and fstab were modified OK");
1590        }
1591    } else
1592        /* nuke mode */
1593    {
1594        res = TRUE;
1595    }
1596    paranoid_free(command);
1597    paranoid_free(tmp);
1598    paranoid_free(editor);
1599    return (res);
1600}
1601
1602/**************************************************************************
1603 *END_RUN_ELILO                                                            *
1604 **************************************************************************/
1605
1606
1607/**
1608 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1609 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1610 * @return 0 for success, nonzero for failure.
1611 */
1612int run_lilo(bool offer_to_run_stablilo)
1613{
1614  /** malloc **/
1615    char *command;
1616    char *tmp;
1617    char *editor;
1618
1619    int res;
1620    int done;
1621    bool run_lilo_M = FALSE;
1622    malloc_string(command);
1623    malloc_string(tmp);
1624    malloc_string(editor);
1625
1626    if (!run_program_and_log_output
1627        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1628        run_lilo_M = TRUE;
1629    }
1630
1631    strcpy(editor, find_my_editor());
1632    if (offer_to_run_stablilo
1633        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1634
1635        /* interactive mode */
1636    {
1637        mvaddstr_and_log_it(g_currentY,
1638                            0,
1639                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1640        sprintf(command, "stablilo-me");
1641        res = run_program_and_log_output(command, 3);
1642        if (res) {
1643            popup_and_OK
1644                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1645            for (done = FALSE; !done;) {
1646                if (!g_text_mode) {
1647                    newtSuspend();
1648                }
1649                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1650                paranoid_system(tmp);
1651                sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1652                paranoid_system(tmp);
1653                if (!g_text_mode) {
1654                    newtResume();
1655                }
1656//              newtCls();
1657                if (ask_me_yes_or_no("Edit them again?")) {
1658                    continue;
1659                }
1660                res =
1661                    run_program_and_log_output("chroot " MNT_RESTORING
1662                                               " lilo -L", 3);
1663                if (res) {
1664                    res =
1665                        run_program_and_log_output("chroot " MNT_RESTORING
1666                                                   " lilo", 3);
1667                }
1668                if (res) {
1669                    done =
1670                        ask_me_yes_or_no
1671                        ("LILO failed. Re-edit system files?");
1672                } else {
1673                    done = TRUE;
1674                }
1675            }
1676        } else {
1677            log_to_screen("lilo.conf and fstab were modified OK");
1678        }
1679    } else
1680        /* nuke mode */
1681    {
1682        mvaddstr_and_log_it(g_currentY,
1683                            0,
1684                            "Running LILO...                                                 ");
1685        res =
1686            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1687                                       3);
1688        if (res) {
1689            res =
1690                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1691                                           3);
1692        }
1693        if (res) {
1694            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1695            log_to_screen
1696                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1697        } else {
1698            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1699        }
1700    }
1701    if (run_lilo_M) {
1702        run_program_and_log_output("chroot " MNT_RESTORING
1703                                   " lilo -M /dev/hda", 3);
1704        run_program_and_log_output("chroot " MNT_RESTORING
1705                                   " lilo -M /dev/sda", 3);
1706    }
1707    paranoid_free(command);
1708    paranoid_free(tmp);
1709    paranoid_free(editor);
1710    return (res);
1711}
1712
1713/**************************************************************************
1714 *END_RUN_LILO                                                            *
1715 **************************************************************************/
1716
1717
1718/**
1719 * Install a raw MBR onto @p bd.
1720 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1721 * @param bd The device to copy the stored MBR to.
1722 * @return 0 for success, nonzero for failure.
1723 */
1724int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1725{
1726  /** malloc **/
1727    char *command;
1728    char *boot_device;
1729    char *tmp;
1730    char *editor;
1731    int res;
1732    int done;
1733
1734    malloc_string(command);
1735    malloc_string(boot_device);
1736    malloc_string(tmp);
1737    malloc_string(editor);
1738    assert_string_is_neither_NULL_nor_zerolength(bd);
1739
1740    strcpy(editor, find_my_editor());
1741    strcpy(boot_device, bd);
1742    sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1743    log_msg(2, "run_raw_mbr() --- command='%s'", command);
1744
1745    if (offer_to_hack_scripts
1746        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1747        /* interactive mode */
1748    {
1749        mvaddstr_and_log_it(g_currentY, 0,
1750                            "Modifying fstab and restoring MBR...                           ");
1751        for (done = FALSE; !done;) {
1752            if (!run_program_and_log_output("which vi", FALSE)) {
1753                popup_and_OK("You will now edit fstab");
1754                if (!g_text_mode) {
1755                    newtSuspend();
1756                }
1757                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1758                paranoid_system(tmp);
1759                if (!g_text_mode) {
1760                    newtResume();
1761                }
1762//              newtCls();
1763            }
1764            popup_and_get_string("Boot device",
1765                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1766                                 boot_device, MAX_STR_LEN / 4);
1767            sprintf(command, "stabraw-me %s", boot_device);
1768            res = run_program_and_log_output(command, 3);
1769            if (res) {
1770                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1771            } else {
1772                done = TRUE;
1773            }
1774        }
1775    } else
1776        /* nuke mode */
1777    {
1778        mvaddstr_and_log_it(g_currentY, 0,
1779                            "Restoring MBR...                                               ");
1780        res = run_program_and_log_output(command, 3);
1781    }
1782    if (res) {
1783        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1784        log_to_screen
1785            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1786    } else {
1787        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1788    }
1789    paranoid_free(command);
1790    paranoid_free(boot_device);
1791    paranoid_free(tmp);
1792    paranoid_free(editor);
1793    return (res);
1794}
1795
1796/**************************************************************************
1797 *END_RUN_RAW_MBR                                                         *
1798 **************************************************************************/
1799
1800
1801
1802/**
1803 * malloc() and set sensible defaults for the mondorestore filename variables.
1804 * @param bkpinfo The backup information structure. Fields used:
1805 * - @c bkpinfo->tmpdir
1806 * - @c bkpinfo->disaster_recovery
1807 */
1808void setup_MR_global_filenames()
1809{
1810    char *temppath;
1811
1812    assert(bkpinfo != NULL);
1813
1814    malloc_string(g_biggielist_txt);
1815    malloc_string(g_filelist_full);
1816    malloc_string(g_filelist_imagedevs);
1817    malloc_string(g_imagedevs_restthese);
1818    malloc_string(g_mondo_cfg_file);
1819    malloc_string(g_mountlist_fname);
1820    malloc_string(g_mondo_home);
1821    /*
1822    malloc_string(g_tmpfs_mountpt);
1823    */
1824    malloc_string(g_isodir_device);
1825    malloc_string(g_isodir_format);
1826
1827    temppath = bkpinfo->tmpdir;
1828
1829    sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1830    sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1831    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1832//  sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1833    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1834            temppath);
1835    if (bkpinfo->disaster_recovery) {
1836        sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1837        sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1838    } else {
1839        sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1840        sprintf(g_mountlist_fname, "%s/%s", temppath,
1841                MOUNTLIST_FNAME_STUB);
1842    }
1843}
1844
1845/**************************************************************************
1846 *END_SET_GLOBAL_FILENAME                                                 *
1847 **************************************************************************/
1848
1849
1850/**
1851 * Copy @p input_file (containing the result of a compare) to @p output_file,
1852 * deleting spurious "changes" along the way.
1853 * @param output_file The output file to write with spurious changes removed.
1854 * @param input_file The input file, a list of changed files created by a compare.
1855 */
1856void streamline_changes_file(char *output_file, char *input_file)
1857{
1858    FILE *fin;
1859    FILE *fout;
1860  /** malloc **/
1861    char *incoming;
1862
1863    assert_string_is_neither_NULL_nor_zerolength(output_file);
1864    assert_string_is_neither_NULL_nor_zerolength(input_file);
1865    malloc_string(incoming);
1866
1867    if (!(fin = fopen(input_file, "r"))) {
1868        log_OS_error(input_file);
1869        return;
1870    }
1871    if (!(fout = fopen(output_file, "w"))) {
1872        fatal_error("cannot open output_file");
1873    }
1874    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1875         fgets(incoming, MAX_STR_LEN - 1, fin)) {
1876        if (strncmp(incoming, "etc/adjtime", 11)
1877            && strncmp(incoming, "etc/mtab", 8)
1878            && strncmp(incoming, "tmp/", 4)
1879            && strncmp(incoming, "boot/map", 8)
1880            && !strstr(incoming, "incheckentry")
1881            && strncmp(incoming, "etc/mail/statistics", 19)
1882            && strncmp(incoming, "var/", 4))
1883            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
1884    }
1885    paranoid_fclose(fout);
1886    paranoid_fclose(fin);
1887    paranoid_free(incoming);
1888}
1889
1890/**************************************************************************
1891 *END_STREAMLINE_CHANGES_FILE                                             *
1892 **************************************************************************/
1893
1894
1895/**
1896 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1897 */
1898void twenty_seconds_til_yikes()
1899{
1900    int i;
1901    /* MALLOC * */
1902    char *tmp;
1903
1904    malloc_string(tmp);
1905    if (does_file_exist("/tmp/NOPAUSE")) {
1906        return;
1907    }
1908    open_progress_form("CAUTION",
1909                       "Be advised: I am about to ERASE your hard disk(s)!",
1910                       "You may press Ctrl+Alt+Del to abort safely.",
1911                       "", 20);
1912    for (i = 0; i < 20; i++) {
1913        g_current_progress = i;
1914        sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1915        update_progress_form(tmp);
1916        sleep(1);
1917    }
1918    close_progress_form();
1919    paranoid_free(tmp);
1920}
1921
1922/**************************************************************************
1923 *END_TWENTY_SECONDS_TIL_YIKES                                            *
1924 **************************************************************************/
1925
1926
1927/**
1928 * Unmount all devices in @p p_external_copy_of_mountlist.
1929 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1930 * @return 0 for success, nonzero for failure.
1931 */
1932int unmount_all_devices(struct mountlist_itself
1933                        *p_external_copy_of_mountlist)
1934{
1935    struct mountlist_itself *mountlist;
1936    int retval = 0, lino, res = 0, i;
1937    char *command;
1938    char *tmp = NULL;
1939
1940    malloc_string(command);
1941    assert(p_external_copy_of_mountlist != NULL);
1942
1943    mountlist = malloc(sizeof(struct mountlist_itself));
1944    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1945           sizeof(struct mountlist_itself));
1946    sort_mountlist_by_mountpoint(mountlist, 0);
1947
1948    run_program_and_log_output("df -m", 3);
1949    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
1950    open_progress_form("Unmounting devices",
1951                       "Unmounting all devices that were mounted,",
1952                       "in preparation for the post-restoration reboot.",
1953                       "", mountlist->entries);
1954    chdir("/");
1955    for (i = 0;
1956         i < 10
1957         &&
1958         run_program_and_log_output
1959         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1960         i++) {
1961        sleep(1);
1962        log_msg(2, "Waiting for buffer() to finish");
1963    }
1964
1965    paranoid_system("sync");
1966
1967    mr_asprintf(&tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1968    if (run_program_and_log_output(tmp, FALSE)) {
1969        log_msg(1,
1970                "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1971    }
1972    paranoid_free(tmp);
1973    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1974        run_program_and_log_output("mkdir -p " MNT_RESTORING
1975                                   "/mnt/.boot.d", 5);
1976    }
1977
1978    /* Unmounting the local /proc and /sys first */
1979    run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1980    run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1981
1982    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1983        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1984            continue;
1985        }
1986        mr_asprintf(&tmp, "Unmounting device %s  ", mountlist->el[lino].device);
1987
1988        update_progress_form(tmp);
1989
1990        if (is_this_device_mounted(mountlist->el[lino].device)) {
1991            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1992                sprintf(command, "swapoff %s", mountlist->el[lino].device);
1993            } else {
1994                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1995                    sprintf(command, "umount %s/", MNT_RESTORING);
1996                    log_msg(3,
1997                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1998                } else {
1999                    sprintf(command, "umount " MNT_RESTORING "%s",
2000                            mountlist->el[lino].mountpoint);
2001
2002                    /* To support latest Ubuntu where /var is a separate FS
2003                     * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
2004                     * we need to create some dirs under the real / before unmounting it */
2005                    if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
2006                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
2007                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
2008                    }
2009                }
2010            }
2011            log_msg(10, "The 'umount' command is '%s'", command);
2012            res = run_program_and_log_output(command, 3);
2013        } else {
2014            mr_strcat(tmp, "...not mounted anyway :-) OK");
2015            res = 0;
2016        }
2017        g_current_progress++;
2018        if (res) {
2019            mr_strcat(tmp, "...Failed");
2020            retval++;
2021            log_to_screen(tmp);
2022        } else {
2023            log_msg(2, tmp);
2024        }
2025        paranoid_free(tmp);
2026    }
2027    close_progress_form();
2028    if (retval) {
2029        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2030    } else {
2031        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2032    }
2033    if (retval) {
2034        log_to_screen("Unable to unmount some of your partitions.");
2035    } else {
2036        log_to_screen("All partitions were unmounted OK.");
2037    }
2038    free(mountlist);
2039    paranoid_free(command);
2040    return (retval);
2041}
2042
2043/**************************************************************************
2044 *END_UNMOUNT_ALL_DEVICES                                                 *
2045 **************************************************************************/
2046
2047
2048
2049/**
2050 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2051 * to the ./tmp/ directory.
2052 * @param dev The tape device to read from.
2053 * @return 0 for success, nonzero for failure.
2054 */
2055int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2056{
2057    char *command;
2058    int res = 0;
2059
2060    malloc_string(command);
2061
2062    if (bkpinfo->use_obdr) {
2063        skip_obdr();
2064    } else {
2065        // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2066        set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2067    }
2068
2069    sprintf(command,
2070            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s",
2071            dev,
2072            bkpinfo->internal_tape_block_size,
2073            1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2074            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2075            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2076    log_msg(2, "command = '%s'", command);
2077    res = run_program_and_log_output(command, -1);
2078    if (res != 0) {
2079        if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2080            res = 0;
2081        } else {
2082            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2083            log_msg(2, "pre-2.2.4 compatible mode on");
2084            sprintf(command,
2085                    "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2086                    dev,
2087                    bkpinfo->internal_tape_block_size,
2088                    1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2089                    MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2090                    BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2091            log_msg(2, "command = '%s'", command);
2092            res = run_program_and_log_output(command, -1);
2093            if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2094                res = 0;
2095            }
2096        }
2097    }
2098    paranoid_free(command);
2099    return (res);
2100}
2101
2102
2103
2104/**
2105 * Get the configuration file from the floppy, tape, or CD.
2106 * @param bkpinfo The backup information structure. Fields used:
2107 * - @c bkpinfo->backup_media_type
2108 * - @c bkpinfo->media_device
2109 * - @c bkpinfo->tmpdir
2110 * @return 0 for success, nonzero for failure.
2111 */
2112int get_cfg_file_from_archive()
2113{
2114    int retval = 0;
2115
2116   /** malloc *****/
2117    char *device;
2118    char *command;
2119    char *cfg_file;
2120    char *mounted_cfgf_path;
2121    char *tmp;
2122    char *mountpt;
2123    char *ramdisk_fname;
2124    char *mountlist_file;
2125    bool extract_mountlist_stub = FALSE;
2126    bool extract_i_want_my_lvm = FALSE;
2127
2128    bool try_plan_B;
2129
2130    assert(bkpinfo != NULL);
2131    malloc_string(cfg_file);
2132    malloc_string(mounted_cfgf_path);
2133    malloc_string(mountpt);
2134    malloc_string(ramdisk_fname);
2135    malloc_string(mountlist_file);
2136    malloc_string(device);
2137    malloc_string(command);
2138    malloc_string(tmp);
2139    log_msg(2, "gcffa --- starting");
2140    log_to_screen("I'm thinking...");
2141    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2142    device[0] = '\0';
2143    chdir(bkpinfo->tmpdir);
2144    strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2145    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
2146    unlink(FILELIST_FULL_STUB);
2147    unlink(BIGGIELIST_TXT_STUB);
2148    sprintf(command, "mkdir -p %s", mountpt);
2149    run_program_and_log_output(command, FALSE);
2150
2151    sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2152    sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2153    //   make_hole_for_file( cfg_file );
2154    //   make_hole_for_file( mountlist_file);
2155    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2156
2157    if (!does_file_exist(cfg_file)) {
2158        log_msg(2, "gcffa --- we don't have cfg file yet.");
2159        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2160            try_plan_B = TRUE;
2161        } else {
2162            log_msg(2, "gcffa --- calling mount_media now :)");
2163            if (!mount_media()) {
2164                log_msg(2,
2165                        "gcffa --- managed to mount CD; so, no need for Plan B");
2166                try_plan_B = FALSE;
2167            } else {
2168                try_plan_B = TRUE;
2169            }
2170            if (what_number_cd_is_this() > 1) {
2171                insist_on_this_cd_number((g_current_media_number = 1));
2172            }
2173        }
2174        if (try_plan_B) {
2175            log_msg(2, "gcffa --- OK, switching to Plan B");
2176            chdir(bkpinfo->tmpdir);
2177            run_program_and_log_output("mkdir -p tmp", FALSE);
2178
2179            if (strlen(bkpinfo->media_device) == 0) {
2180                strcpy(bkpinfo->media_device, "/dev/st0");
2181                log_msg(2, "media_device is blank; assuming %s");
2182            }
2183            strcpy(tmp, bkpinfo->media_device);
2184            if (extract_cfg_file_and_mountlist_from_tape_dev
2185                (bkpinfo->media_device)) {
2186                strcpy(bkpinfo->media_device, "/dev/st0");
2187                if (extract_cfg_file_and_mountlist_from_tape_dev
2188                    (bkpinfo->media_device)) {
2189                    strcpy(bkpinfo->media_device, "/dev/osst0");
2190                    if (extract_cfg_file_and_mountlist_from_tape_dev
2191                        (bkpinfo->media_device)) {
2192                        strcpy(bkpinfo->media_device, "/dev/ht0");
2193                        if (extract_cfg_file_and_mountlist_from_tape_dev
2194                            (bkpinfo->media_device)) {
2195                            log_msg(3,
2196                                    "I tried lots of devices but none worked.");
2197                            strcpy(bkpinfo->media_device, tmp);
2198                        }
2199                    }
2200                }
2201            }
2202
2203            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2204                log_to_screen("Cannot find config info on media");
2205                return (1);
2206            }
2207        } else {
2208                if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2209                    extract_mountlist_stub = FALSE;
2210                } else {
2211                    extract_mountlist_stub = TRUE;
2212                }
2213                if (does_file_exist("/"IWANTMYLVM_STUB)) {
2214                    extract_i_want_my_lvm = FALSE;
2215                } else {
2216                    extract_i_want_my_lvm = TRUE;
2217                }
2218
2219                log_msg(2,
2220                        "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2221                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
2222                run_program_and_log_output(command, TRUE);
2223                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2224                    /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2225                    log_msg(2, "pre-2.2.4 compatible mode on");
2226                    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
2227                    run_program_and_log_output(command, TRUE);
2228                    if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2229                        fatal_error
2230                            ("Please reinsert the disk/CD and try again.");
2231                    }
2232                }
2233        }
2234    }
2235    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2236        log_msg(1, "gcffa --- great! We've got the config file");
2237        sprintf(tmp, "%s/%s",
2238                call_program_and_get_last_line_of_output("pwd"),
2239                MONDO_CFG_FILE_STUB);
2240        sprintf(command, "cp -f %s %s", tmp, cfg_file);
2241        log_it("%s",command);
2242        if (strcmp(tmp, cfg_file)
2243            && run_program_and_log_output(command, 1)) {
2244            log_msg(1,
2245                    "... but an error occurred when I tried to move it to %s",
2246                    cfg_file);
2247        } else {
2248            log_msg(1, "... and I moved it successfully to %s", cfg_file);
2249        }
2250        sprintf(command, "cp -f %s/%s %s",
2251            call_program_and_get_last_line_of_output("pwd"),
2252            MOUNTLIST_FNAME_STUB, mountlist_file);
2253        log_it("%s",command);
2254        if (extract_mountlist_stub) {
2255            if (strcmp(tmp, cfg_file)
2256                && run_program_and_log_output(command, 1)) {
2257                log_msg(1, "Failed to get mountlist");
2258            } else {
2259                log_msg(1, "Got mountlist too");
2260                sprintf(command, "cp -f %s %s", mountlist_file,
2261                        g_mountlist_fname);
2262                if (run_program_and_log_output(command, 1)) {
2263                    log_msg(1, "Failed to copy mountlist to /tmp");
2264                } else {
2265                    log_msg(1, "Copied mountlist to /tmp as well OK");
2266                    sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2267                    run_program_and_log_output(command, 1);
2268                }
2269            }
2270        }
2271    }
2272    run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
2273    if (!does_file_exist(cfg_file)) {
2274        log_it("%s",cfg_file);
2275        log_msg(1, "%s not found", cfg_file);
2276        log_to_screen
2277            ("Oh dear. Unable to recover configuration file from boot disk");
2278        return (1);
2279    }
2280
2281    log_to_screen("Recovered mondo-restore.cfg");
2282    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2283        log_to_screen("...but not mountlist.txt - a pity, really...");
2284    }
2285    else {
2286            /* Is this code really useful ??? */
2287        if (extract_mountlist_stub) {
2288            sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2289                    bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2290            run_program_and_log_output(command, FALSE);
2291        }
2292    }
2293
2294    sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2295    run_program_and_log_output(command, FALSE);
2296    if (extract_mountlist_stub) {
2297        sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2298        run_program_and_log_output(command, FALSE);
2299    }
2300    sprintf(command, "cp -f etc/raidtab /etc/");
2301    run_program_and_log_output(command, FALSE);
2302    if (extract_i_want_my_lvm) {
2303        sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2304        run_program_and_log_output(command, FALSE);
2305    }
2306    g_backup_media_type = bkpinfo->backup_media_type;
2307    paranoid_free(device);
2308    paranoid_free(command);
2309    paranoid_free(tmp);
2310    paranoid_free(cfg_file);
2311    paranoid_free(mounted_cfgf_path);
2312    paranoid_free(mountpt);
2313    paranoid_free(ramdisk_fname);
2314    paranoid_free(mountlist_file);
2315    return (retval);
2316}
2317
2318/**************************************************************************
2319 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2320 **************************************************************************/
2321
2322/* @} - end restoreUtilityGroup */
2323
2324
2325/***************************************************************************
2326 * F@                                                                      *
2327 * () -- Hugo Rabson                                  *
2328 *                                                                         *
2329 * Purpose:                                                                *
2330 *                                                                         *
2331 * Called by:                                                              *
2332 * Params:    -                      -                                     *
2333 * Returns:   0=success; nonzero=failure                                   *
2334 ***************************************************************************/
2335
2336
2337
2338void wait_until_software_raids_are_prepped(char *mdstat_file,
2339                                           int wait_for_percentage)
2340{
2341    struct raidlist_itself *raidlist;
2342    int unfinished_mdstat_devices = 9999, i;
2343    char *screen_message;
2344
2345    malloc_string(screen_message);
2346    raidlist = malloc(sizeof(struct raidlist_itself));
2347
2348    assert(wait_for_percentage <= 100);
2349    log_it("wait_until_software_raids_are_prepped");
2350    while (unfinished_mdstat_devices > 0) {
2351            // FIXME: Prefix '/dev/' should really be dynamic!
2352        if (parse_mdstat(raidlist, "/dev/")) {
2353            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2354            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2355            return;
2356        }
2357        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2358            if (raidlist->el[i].progress < wait_for_percentage) {
2359                unfinished_mdstat_devices++;
2360                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2361                {
2362                    continue;
2363                }
2364                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2365                sprintf(screen_message, "Sync'ing %s",
2366                        raidlist->el[i].raid_device);
2367                open_evalcall_form(screen_message);
2368                while (raidlist->el[i].progress < wait_for_percentage) {
2369                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2370                    update_evalcall_form(raidlist->el[i].progress);
2371                    sleep(2);
2372                    // FIXME: Prefix '/dev/' should really be dynamic!
2373                    if (parse_mdstat(raidlist, "/dev/")) {
2374                        break;
2375                    }
2376                }
2377                close_evalcall_form();
2378            }
2379        }
2380    }
2381    paranoid_free(screen_message);
2382    paranoid_free(raidlist);
2383}
2384
2385
Note: See TracBrowser for help on using the repository browser.