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

Last change on this file since 2904 was 2904, checked in by Bruno Cornec, 9 years ago
  • Fix #511 now stabgrub is called also after conf file modifications
  • Property svn:keywords set to Id
File size: 72.2 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2904 2011-11-21 02:46:46Z 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, "/etc/lilo.conf");
1304    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1305    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1306    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1307    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1308    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1309    mr_asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1310    log_msg(2, tmp);
1311    paranoid_free(tmp);
1312    system("sync");
1313
1314    offer_to_make_initrd();
1315    if (!strcmp(name, "LILO")) {
1316        res = run_lilo(offer_to_hack_scripts);
1317    } else if (!strcmp(name, "ELILO")) {
1318        res = run_elilo(offer_to_hack_scripts);
1319    } else if (!strcmp(name, "GRUB")) {
1320        res = run_grub(offer_to_hack_scripts, device);
1321    } else if (!strcmp(name, "RAW")) {
1322        res = run_raw_mbr(offer_to_hack_scripts, device);
1323    }
1324#ifdef __FreeBSD__
1325    else if (!strcmp(name, "BOOT0")) {
1326        mr_asprintf(&tmp, "boot0cfg -B %s", device);
1327        res = run_program_and_log_output(tmp, FALSE);
1328        paranoid_free(tmp);
1329    } else {
1330        mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1331        if (!system(tmp)) {
1332            paranoid_free(tmp);
1333            mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1334            res = run_program_and_log_output(tmp, 3);
1335        } else {
1336            log_msg(1,
1337                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1338        }
1339        paranoid_free(tmp);
1340    }
1341#else
1342    else {
1343        log_to_screen
1344            ("Unable to determine type of boot loader. Defaulting to LILO.");
1345        res = run_lilo(offer_to_hack_scripts);
1346    }
1347#endif
1348    retval += res;
1349    if (res) {
1350        log_to_screen("Your boot loader returned an error");
1351    } else {
1352        log_to_screen("Your boot loader ran OK");
1353    }
1354    paranoid_free(device);
1355    paranoid_free(name);
1356    return (retval);
1357}
1358
1359/**************************************************************************
1360 *END_ RUN_BOOT_LOADER                                                    *
1361 **************************************************************************/
1362
1363
1364
1365/**
1366 * Attempt to find the user's editor.
1367 * @return The editor found ("vi" if none could be found).
1368 * @note The returned string points to static storage that will be overwritten with each call.
1369 */
1370char *find_my_editor(void)
1371{
1372    static char output[MAX_STR_LEN];
1373    if (find_home_of_exe("pico")) {
1374        strcpy(output, "pico");
1375    } else if (find_home_of_exe("nano")) {
1376        strcpy(output, "nano");
1377    } else if (find_home_of_exe("e3em")) {
1378        strcpy(output, "e3em");
1379    } else if (find_home_of_exe("e3vi")) {
1380        strcpy(output, "e3vi");
1381    } else {
1382        strcpy(output, "vi");
1383    }
1384    if (!find_home_of_exe(output)) {
1385        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1386    }
1387    return (output);
1388}
1389
1390
1391/**
1392 * Install GRUB on @p bd.
1393 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1394 * @param bd The boot device where GRUB is installed.
1395 * @return 0 for success, nonzero for failure.
1396 */
1397int run_grub(bool offer_to_run_stabgrub, char *bd)
1398{
1399  /** malloc **/
1400    char *command;
1401    char *boot_device;
1402    char *rootdev;
1403    char *rootdrive;
1404    char *conffile;
1405    char *tmp;
1406    char *editor;
1407
1408    int res;
1409    int done;
1410
1411    malloc_string(command);
1412    malloc_string(boot_device);
1413    malloc_string(tmp);
1414    malloc_string(editor);
1415    malloc_string(rootdev);
1416    malloc_string(rootdrive);
1417    malloc_string(conffile);
1418    assert_string_is_neither_NULL_nor_zerolength(bd);
1419    strcpy(editor, find_my_editor());
1420    strcpy(boot_device, bd);
1421
1422    if (!run_program_and_log_output("which grub-MR", FALSE)) {
1423        log_msg(1, "Yay! grub-MR found...");
1424        sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1425        log_msg(1, "command = %s", command);
1426    } else {
1427        sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1428                boot_device);
1429        log_msg(1, "WARNING - grub-MR not found; using grub-install");
1430    }
1431    if (offer_to_run_stabgrub
1432        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1433        /* interactive mode */
1434    {
1435        mvaddstr_and_log_it(g_currentY,
1436                            0,
1437                            "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB...                             ");
1438        for (done = FALSE; !done;) {
1439            popup_and_get_string("Boot device",
1440                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1441                                 boot_device, MAX_STR_LEN / 4);
1442            sprintf(command, "stabgrub-me %s", boot_device);
1443            res = run_program_and_log_output(command, 1);
1444            if (res) {
1445                popup_and_OK
1446                    ("GRUB installation failed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1447                if (!g_text_mode) {
1448                    newtSuspend();
1449                }
1450                sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1451                paranoid_system(tmp);
1452                sprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1453                paranoid_system(tmp);
1454                if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1455                    sprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1456                } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1457                    sprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1458                }
1459                paranoid_system(tmp);
1460                sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1461                paranoid_system(tmp);
1462                if (!g_text_mode) {
1463                    newtResume();
1464                }
1465                sprintf(command, "stabgrub-me %s", boot_device);
1466                res = run_program_and_log_output(command, 1);
1467                if (res) {
1468                    popup_and_OK
1469                        ("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.");
1470                    newtSuspend();
1471                    system("chroot " MNT_RESTORING);
1472                    newtResume();
1473                    popup_and_OK("Thank you.");
1474                } else {
1475                    popup_and_OK("GRUB is now installed correctly");
1476                    done = TRUE;
1477                }
1478            } else {
1479                done = TRUE;
1480            }
1481        }
1482    } else
1483        /* nuke mode */
1484    {
1485        mvaddstr_and_log_it(g_currentY,
1486                            0,
1487                            "Running GRUB...                                                 ");
1488        log_it("%s",command);
1489        res = run_program_and_log_output(command, 1);
1490        if (res) {
1491            popup_and_OK
1492                ("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.");
1493            newtSuspend();
1494            system("chroot " MNT_RESTORING);
1495            newtResume();
1496            popup_and_OK("Thank you.");
1497        }
1498    }
1499    if (res) {
1500        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1501        log_to_screen
1502            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1503        log_msg(1, "Type:-");
1504        log_msg(1, "    mount-me");
1505        log_msg(1, "    chroot " MNT_RESTORING);
1506        log_msg(1, "    mount /boot");
1507        log_msg(1, "    grub-install '(hd0)'");
1508        log_msg(1, "    exit");
1509        log_msg(1, "    unmount-me");
1510        log_msg(1,
1511                "If you're really stuck, please e-mail the mailing list.");
1512    } else {
1513        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1514    }
1515    paranoid_free(rootdev);
1516    paranoid_free(rootdrive);
1517    paranoid_free(conffile);
1518    paranoid_free(command);
1519    paranoid_free(boot_device);
1520    paranoid_free(tmp);
1521    paranoid_free(editor);
1522
1523    return (res);
1524}
1525
1526/**************************************************************************
1527 *END_RUN_GRUB                                                            *
1528 **************************************************************************/
1529
1530
1531/**
1532 * Install ELILO on the user's boot drive (determined by elilo.conf).
1533 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1534 * @return 0 for success, nonzero for failure.
1535 */
1536int run_elilo(bool offer_to_run_stabelilo)
1537{
1538  /** malloc **/
1539    char *command;
1540    char *tmp;
1541    char *editor;
1542
1543    int res;
1544    int done;
1545
1546    malloc_string(command);
1547    malloc_string(tmp);
1548    malloc_string(editor);
1549    strcpy(editor, find_my_editor());
1550    if (offer_to_run_stabelilo
1551        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1552
1553        /* interactive mode */
1554    {
1555        mvaddstr_and_log_it(g_currentY,
1556                            0,
1557                            "Modifying fstab and elilo.conf...                             ");
1558        sprintf(command, "stabelilo-me");
1559        res = run_program_and_log_output(command, 3);
1560        if (res) {
1561            popup_and_OK
1562                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1563            for (done = FALSE; !done;) {
1564                if (!g_text_mode) {
1565                    newtSuspend();
1566                }
1567                sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1568                paranoid_system(tmp);
1569                sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1570                paranoid_system(tmp);
1571                if (!g_text_mode) {
1572                    newtResume();
1573                }
1574//              newtCls();
1575                if (ask_me_yes_or_no("Edit them again?")) {
1576                    continue;
1577                }
1578                done = TRUE;
1579            }
1580        } else {
1581            log_to_screen("elilo.conf and fstab were modified OK");
1582        }
1583    } else
1584        /* nuke mode */
1585    {
1586        res = TRUE;
1587    }
1588    paranoid_free(command);
1589    paranoid_free(tmp);
1590    paranoid_free(editor);
1591    return (res);
1592}
1593
1594/**************************************************************************
1595 *END_RUN_ELILO                                                            *
1596 **************************************************************************/
1597
1598
1599/**
1600 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1601 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1602 * @return 0 for success, nonzero for failure.
1603 */
1604int run_lilo(bool offer_to_run_stablilo)
1605{
1606  /** malloc **/
1607    char *command;
1608    char *tmp;
1609    char *editor;
1610
1611    int res;
1612    int done;
1613    bool run_lilo_M = FALSE;
1614    malloc_string(command);
1615    malloc_string(tmp);
1616    malloc_string(editor);
1617
1618    if (!run_program_and_log_output
1619        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1620        run_lilo_M = TRUE;
1621    }
1622
1623    strcpy(editor, find_my_editor());
1624    if (offer_to_run_stablilo
1625        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1626
1627        /* interactive mode */
1628    {
1629        mvaddstr_and_log_it(g_currentY,
1630                            0,
1631                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1632        sprintf(command, "stablilo-me");
1633        res = run_program_and_log_output(command, 3);
1634        if (res) {
1635            popup_and_OK
1636                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1637            for (done = FALSE; !done;) {
1638                if (!g_text_mode) {
1639                    newtSuspend();
1640                }
1641                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1642                paranoid_system(tmp);
1643                sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1644                paranoid_system(tmp);
1645                if (!g_text_mode) {
1646                    newtResume();
1647                }
1648//              newtCls();
1649                if (ask_me_yes_or_no("Edit them again?")) {
1650                    continue;
1651                }
1652                res =
1653                    run_program_and_log_output("chroot " MNT_RESTORING
1654                                               " lilo -L", 3);
1655                if (res) {
1656                    res =
1657                        run_program_and_log_output("chroot " MNT_RESTORING
1658                                                   " lilo", 3);
1659                }
1660                if (res) {
1661                    done =
1662                        ask_me_yes_or_no
1663                        ("LILO failed. Re-edit system files?");
1664                } else {
1665                    done = TRUE;
1666                }
1667            }
1668        } else {
1669            log_to_screen("lilo.conf and fstab were modified OK");
1670        }
1671    } else
1672        /* nuke mode */
1673    {
1674        mvaddstr_and_log_it(g_currentY,
1675                            0,
1676                            "Running LILO...                                                 ");
1677        res =
1678            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1679                                       3);
1680        if (res) {
1681            res =
1682                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1683                                           3);
1684        }
1685        if (res) {
1686            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1687            log_to_screen
1688                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1689        } else {
1690            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1691        }
1692    }
1693    if (run_lilo_M) {
1694        run_program_and_log_output("chroot " MNT_RESTORING
1695                                   " lilo -M /dev/hda", 3);
1696        run_program_and_log_output("chroot " MNT_RESTORING
1697                                   " lilo -M /dev/sda", 3);
1698    }
1699    paranoid_free(command);
1700    paranoid_free(tmp);
1701    paranoid_free(editor);
1702    return (res);
1703}
1704
1705/**************************************************************************
1706 *END_RUN_LILO                                                            *
1707 **************************************************************************/
1708
1709
1710/**
1711 * Install a raw MBR onto @p bd.
1712 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1713 * @param bd The device to copy the stored MBR to.
1714 * @return 0 for success, nonzero for failure.
1715 */
1716int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1717{
1718  /** malloc **/
1719    char *command;
1720    char *boot_device;
1721    char *tmp;
1722    char *editor;
1723    int res;
1724    int done;
1725
1726    malloc_string(command);
1727    malloc_string(boot_device);
1728    malloc_string(tmp);
1729    malloc_string(editor);
1730    assert_string_is_neither_NULL_nor_zerolength(bd);
1731
1732    strcpy(editor, find_my_editor());
1733    strcpy(boot_device, bd);
1734    sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1735    log_msg(2, "run_raw_mbr() --- command='%s'", command);
1736
1737    if (offer_to_hack_scripts
1738        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1739        /* interactive mode */
1740    {
1741        mvaddstr_and_log_it(g_currentY, 0,
1742                            "Modifying fstab and restoring MBR...                           ");
1743        for (done = FALSE; !done;) {
1744            if (!run_program_and_log_output("which vi", FALSE)) {
1745                popup_and_OK("You will now edit fstab");
1746                if (!g_text_mode) {
1747                    newtSuspend();
1748                }
1749                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1750                paranoid_system(tmp);
1751                if (!g_text_mode) {
1752                    newtResume();
1753                }
1754//              newtCls();
1755            }
1756            popup_and_get_string("Boot device",
1757                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1758                                 boot_device, MAX_STR_LEN / 4);
1759            sprintf(command, "stabraw-me %s", boot_device);
1760            res = run_program_and_log_output(command, 3);
1761            if (res) {
1762                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1763            } else {
1764                done = TRUE;
1765            }
1766        }
1767    } else
1768        /* nuke mode */
1769    {
1770        mvaddstr_and_log_it(g_currentY, 0,
1771                            "Restoring MBR...                                               ");
1772        res = run_program_and_log_output(command, 3);
1773    }
1774    if (res) {
1775        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1776        log_to_screen
1777            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1778    } else {
1779        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1780    }
1781    paranoid_free(command);
1782    paranoid_free(boot_device);
1783    paranoid_free(tmp);
1784    paranoid_free(editor);
1785    return (res);
1786}
1787
1788/**************************************************************************
1789 *END_RUN_RAW_MBR                                                         *
1790 **************************************************************************/
1791
1792
1793
1794/**
1795 * malloc() and set sensible defaults for the mondorestore filename variables.
1796 * @param bkpinfo The backup information structure. Fields used:
1797 * - @c bkpinfo->tmpdir
1798 * - @c bkpinfo->disaster_recovery
1799 */
1800void setup_MR_global_filenames()
1801{
1802    char *temppath;
1803
1804    assert(bkpinfo != NULL);
1805
1806    malloc_string(g_biggielist_txt);
1807    malloc_string(g_filelist_full);
1808    malloc_string(g_filelist_imagedevs);
1809    malloc_string(g_imagedevs_restthese);
1810    malloc_string(g_mondo_cfg_file);
1811    malloc_string(g_mountlist_fname);
1812    malloc_string(g_mondo_home);
1813    /*
1814    malloc_string(g_tmpfs_mountpt);
1815    */
1816    malloc_string(g_isodir_device);
1817    malloc_string(g_isodir_format);
1818
1819    temppath = bkpinfo->tmpdir;
1820
1821    sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1822    sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1823    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1824//  sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1825    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1826            temppath);
1827    if (bkpinfo->disaster_recovery) {
1828        sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1829        sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1830    } else {
1831        sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1832        sprintf(g_mountlist_fname, "%s/%s", temppath,
1833                MOUNTLIST_FNAME_STUB);
1834    }
1835}
1836
1837/**************************************************************************
1838 *END_SET_GLOBAL_FILENAME                                                 *
1839 **************************************************************************/
1840
1841
1842/**
1843 * Copy @p input_file (containing the result of a compare) to @p output_file,
1844 * deleting spurious "changes" along the way.
1845 * @param output_file The output file to write with spurious changes removed.
1846 * @param input_file The input file, a list of changed files created by a compare.
1847 */
1848void streamline_changes_file(char *output_file, char *input_file)
1849{
1850    FILE *fin;
1851    FILE *fout;
1852  /** malloc **/
1853    char *incoming;
1854
1855    assert_string_is_neither_NULL_nor_zerolength(output_file);
1856    assert_string_is_neither_NULL_nor_zerolength(input_file);
1857    malloc_string(incoming);
1858
1859    if (!(fin = fopen(input_file, "r"))) {
1860        log_OS_error(input_file);
1861        return;
1862    }
1863    if (!(fout = fopen(output_file, "w"))) {
1864        fatal_error("cannot open output_file");
1865    }
1866    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1867         fgets(incoming, MAX_STR_LEN - 1, fin)) {
1868        if (strncmp(incoming, "etc/adjtime", 11)
1869            && strncmp(incoming, "etc/mtab", 8)
1870            && strncmp(incoming, "tmp/", 4)
1871            && strncmp(incoming, "boot/map", 8)
1872            && !strstr(incoming, "incheckentry")
1873            && strncmp(incoming, "etc/mail/statistics", 19)
1874            && strncmp(incoming, "var/", 4))
1875            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
1876    }
1877    paranoid_fclose(fout);
1878    paranoid_fclose(fin);
1879    paranoid_free(incoming);
1880}
1881
1882/**************************************************************************
1883 *END_STREAMLINE_CHANGES_FILE                                             *
1884 **************************************************************************/
1885
1886
1887/**
1888 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1889 */
1890void twenty_seconds_til_yikes()
1891{
1892    int i;
1893    /* MALLOC * */
1894    char *tmp;
1895
1896    malloc_string(tmp);
1897    if (does_file_exist("/tmp/NOPAUSE")) {
1898        return;
1899    }
1900    open_progress_form("CAUTION",
1901                       "Be advised: I am about to ERASE your hard disk(s)!",
1902                       "You may press Ctrl+Alt+Del to abort safely.",
1903                       "", 20);
1904    for (i = 0; i < 20; i++) {
1905        g_current_progress = i;
1906        sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1907        update_progress_form(tmp);
1908        sleep(1);
1909    }
1910    close_progress_form();
1911    paranoid_free(tmp);
1912}
1913
1914/**************************************************************************
1915 *END_TWENTY_SECONDS_TIL_YIKES                                            *
1916 **************************************************************************/
1917
1918
1919/**
1920 * Unmount all devices in @p p_external_copy_of_mountlist.
1921 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1922 * @return 0 for success, nonzero for failure.
1923 */
1924int unmount_all_devices(struct mountlist_itself
1925                        *p_external_copy_of_mountlist)
1926{
1927    struct mountlist_itself *mountlist;
1928    int retval = 0, lino, res = 0, i;
1929    char *command;
1930    char *tmp = NULL;
1931
1932    malloc_string(command);
1933    assert(p_external_copy_of_mountlist != NULL);
1934
1935    mountlist = malloc(sizeof(struct mountlist_itself));
1936    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1937           sizeof(struct mountlist_itself));
1938    sort_mountlist_by_mountpoint(mountlist, 0);
1939
1940    run_program_and_log_output("df -m", 3);
1941    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
1942    open_progress_form("Unmounting devices",
1943                       "Unmounting all devices that were mounted,",
1944                       "in preparation for the post-restoration reboot.",
1945                       "", mountlist->entries);
1946    chdir("/");
1947    for (i = 0;
1948         i < 10
1949         &&
1950         run_program_and_log_output
1951         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1952         i++) {
1953        sleep(1);
1954        log_msg(2, "Waiting for buffer() to finish");
1955    }
1956
1957    paranoid_system("sync");
1958
1959    mr_asprintf(&tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1960    if (run_program_and_log_output(tmp, FALSE)) {
1961        log_msg(1,
1962                "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1963    }
1964    paranoid_free(tmp);
1965    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1966        run_program_and_log_output("mkdir -p " MNT_RESTORING
1967                                   "/mnt/.boot.d", 5);
1968    }
1969
1970    /* Unmounting the local /proc and /sys first */
1971    run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1972    run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1973
1974    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1975        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1976            continue;
1977        }
1978        mr_asprintf(&tmp, "Unmounting device %s  ", mountlist->el[lino].device);
1979
1980        update_progress_form(tmp);
1981
1982        if (is_this_device_mounted(mountlist->el[lino].device)) {
1983            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1984                sprintf(command, "swapoff %s", mountlist->el[lino].device);
1985            } else {
1986                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1987                    sprintf(command, "umount %s/", MNT_RESTORING);
1988                    log_msg(3,
1989                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1990                } else {
1991                    sprintf(command, "umount " MNT_RESTORING "%s",
1992                            mountlist->el[lino].mountpoint);
1993
1994                    /* To support latest Ubuntu where /var is a separate FS
1995                     * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1996                     * we need to create some dirs under the real / before unmounting it */
1997                    if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1998                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1999                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
2000                    }
2001                }
2002            }
2003            log_msg(10, "The 'umount' command is '%s'", command);
2004            res = run_program_and_log_output(command, 3);
2005        } else {
2006            mr_strcat(tmp, "...not mounted anyway :-) OK");
2007            res = 0;
2008        }
2009        g_current_progress++;
2010        if (res) {
2011            mr_strcat(tmp, "...Failed");
2012            retval++;
2013            log_to_screen(tmp);
2014        } else {
2015            log_msg(2, tmp);
2016        }
2017        paranoid_free(tmp);
2018    }
2019    close_progress_form();
2020    if (retval) {
2021        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2022    } else {
2023        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2024    }
2025    if (retval) {
2026        log_to_screen("Unable to unmount some of your partitions.");
2027    } else {
2028        log_to_screen("All partitions were unmounted OK.");
2029    }
2030    free(mountlist);
2031    paranoid_free(command);
2032    return (retval);
2033}
2034
2035/**************************************************************************
2036 *END_UNMOUNT_ALL_DEVICES                                                 *
2037 **************************************************************************/
2038
2039
2040
2041/**
2042 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2043 * to the ./tmp/ directory.
2044 * @param dev The tape device to read from.
2045 * @return 0 for success, nonzero for failure.
2046 */
2047int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2048{
2049    char *command;
2050    int res = 0;
2051
2052    malloc_string(command);
2053
2054    if (bkpinfo->use_obdr) {
2055        skip_obdr();
2056    } else {
2057        // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2058        set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2059    }
2060
2061    sprintf(command,
2062            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s",
2063            dev,
2064            bkpinfo->internal_tape_block_size,
2065            1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2066            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2067            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2068    log_msg(2, "command = '%s'", command);
2069    res = run_program_and_log_output(command, -1);
2070    if (res != 0) {
2071        if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2072            res = 0;
2073        } else {
2074            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2075            log_msg(2, "pre-2.2.4 compatible mode on");
2076            sprintf(command,
2077                    "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2078                    dev,
2079                    bkpinfo->internal_tape_block_size,
2080                    1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2081                    MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2082                    BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2083            log_msg(2, "command = '%s'", command);
2084            res = run_program_and_log_output(command, -1);
2085            if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2086                res = 0;
2087            }
2088        }
2089    }
2090    paranoid_free(command);
2091    return (res);
2092}
2093
2094
2095
2096/**
2097 * Get the configuration file from the floppy, tape, or CD.
2098 * @param bkpinfo The backup information structure. Fields used:
2099 * - @c bkpinfo->backup_media_type
2100 * - @c bkpinfo->media_device
2101 * - @c bkpinfo->tmpdir
2102 * @return 0 for success, nonzero for failure.
2103 */
2104int get_cfg_file_from_archive()
2105{
2106    int retval = 0;
2107
2108   /** malloc *****/
2109    char *device;
2110    char *command;
2111    char *cfg_file;
2112    char *mounted_cfgf_path;
2113    char *tmp;
2114    char *mountpt;
2115    char *ramdisk_fname;
2116    char *mountlist_file;
2117    bool extract_mountlist_stub = FALSE;
2118    bool extract_i_want_my_lvm = FALSE;
2119
2120    bool try_plan_B;
2121
2122    assert(bkpinfo != NULL);
2123    malloc_string(cfg_file);
2124    malloc_string(mounted_cfgf_path);
2125    malloc_string(mountpt);
2126    malloc_string(ramdisk_fname);
2127    malloc_string(mountlist_file);
2128    malloc_string(device);
2129    malloc_string(command);
2130    malloc_string(tmp);
2131    log_msg(2, "gcffa --- starting");
2132    log_to_screen("I'm thinking...");
2133    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2134    device[0] = '\0';
2135    chdir(bkpinfo->tmpdir);
2136    strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2137    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
2138    unlink(FILELIST_FULL_STUB);
2139    unlink(BIGGIELIST_TXT_STUB);
2140    sprintf(command, "mkdir -p %s", mountpt);
2141    run_program_and_log_output(command, FALSE);
2142
2143    sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2144    sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2145    //   make_hole_for_file( cfg_file );
2146    //   make_hole_for_file( mountlist_file);
2147    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2148
2149    if (!does_file_exist(cfg_file)) {
2150        log_msg(2, "gcffa --- we don't have cfg file yet.");
2151        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2152            try_plan_B = TRUE;
2153        } else {
2154            log_msg(2, "gcffa --- calling mount_media now :)");
2155            if (!mount_media()) {
2156                log_msg(2,
2157                        "gcffa --- managed to mount CD; so, no need for Plan B");
2158                try_plan_B = FALSE;
2159            } else {
2160                try_plan_B = TRUE;
2161            }
2162            if (what_number_cd_is_this() > 1) {
2163                insist_on_this_cd_number((g_current_media_number = 1));
2164            }
2165        }
2166        if (try_plan_B) {
2167            log_msg(2, "gcffa --- OK, switching to Plan B");
2168            chdir(bkpinfo->tmpdir);
2169            run_program_and_log_output("mkdir -p tmp", FALSE);
2170
2171            if (strlen(bkpinfo->media_device) == 0) {
2172                strcpy(bkpinfo->media_device, "/dev/st0");
2173                log_msg(2, "media_device is blank; assuming %s");
2174            }
2175            strcpy(tmp, bkpinfo->media_device);
2176            if (extract_cfg_file_and_mountlist_from_tape_dev
2177                (bkpinfo->media_device)) {
2178                strcpy(bkpinfo->media_device, "/dev/st0");
2179                if (extract_cfg_file_and_mountlist_from_tape_dev
2180                    (bkpinfo->media_device)) {
2181                    strcpy(bkpinfo->media_device, "/dev/osst0");
2182                    if (extract_cfg_file_and_mountlist_from_tape_dev
2183                        (bkpinfo->media_device)) {
2184                        strcpy(bkpinfo->media_device, "/dev/ht0");
2185                        if (extract_cfg_file_and_mountlist_from_tape_dev
2186                            (bkpinfo->media_device)) {
2187                            log_msg(3,
2188                                    "I tried lots of devices but none worked.");
2189                            strcpy(bkpinfo->media_device, tmp);
2190                        }
2191                    }
2192                }
2193            }
2194
2195            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2196                log_to_screen("Cannot find config info on media");
2197                return (1);
2198            }
2199        } else {
2200                if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2201                    extract_mountlist_stub = FALSE;
2202                } else {
2203                    extract_mountlist_stub = TRUE;
2204                }
2205                if (does_file_exist("/"IWANTMYLVM_STUB)) {
2206                    extract_i_want_my_lvm = FALSE;
2207                } else {
2208                    extract_i_want_my_lvm = TRUE;
2209                }
2210
2211                log_msg(2,
2212                        "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2213                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
2214                run_program_and_log_output(command, TRUE);
2215                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2216                    /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2217                    log_msg(2, "pre-2.2.4 compatible mode on");
2218                    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
2219                    run_program_and_log_output(command, TRUE);
2220                    if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2221                        fatal_error
2222                            ("Please reinsert the disk/CD and try again.");
2223                    }
2224                }
2225        }
2226    }
2227    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2228        log_msg(1, "gcffa --- great! We've got the config file");
2229        sprintf(tmp, "%s/%s",
2230                call_program_and_get_last_line_of_output("pwd"),
2231                MONDO_CFG_FILE_STUB);
2232        sprintf(command, "cp -f %s %s", tmp, cfg_file);
2233        log_it("%s",command);
2234        if (strcmp(tmp, cfg_file)
2235            && run_program_and_log_output(command, 1)) {
2236            log_msg(1,
2237                    "... but an error occurred when I tried to move it to %s",
2238                    cfg_file);
2239        } else {
2240            log_msg(1, "... and I moved it successfully to %s", cfg_file);
2241        }
2242        sprintf(command, "cp -f %s/%s %s",
2243            call_program_and_get_last_line_of_output("pwd"),
2244            MOUNTLIST_FNAME_STUB, mountlist_file);
2245        log_it("%s",command);
2246        if (extract_mountlist_stub) {
2247            if (strcmp(tmp, cfg_file)
2248                && run_program_and_log_output(command, 1)) {
2249                log_msg(1, "Failed to get mountlist");
2250            } else {
2251                log_msg(1, "Got mountlist too");
2252                sprintf(command, "cp -f %s %s", mountlist_file,
2253                        g_mountlist_fname);
2254                if (run_program_and_log_output(command, 1)) {
2255                    log_msg(1, "Failed to copy mountlist to /tmp");
2256                } else {
2257                    log_msg(1, "Copied mountlist to /tmp as well OK");
2258                    sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2259                    run_program_and_log_output(command, 1);
2260                }
2261            }
2262        }
2263    }
2264    run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
2265    if (!does_file_exist(cfg_file)) {
2266        log_it("%s",cfg_file);
2267        log_msg(1, "%s not found", cfg_file);
2268        log_to_screen
2269            ("Oh dear. Unable to recover configuration file from boot disk");
2270        return (1);
2271    }
2272
2273    log_to_screen("Recovered mondo-restore.cfg");
2274    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2275        log_to_screen("...but not mountlist.txt - a pity, really...");
2276    }
2277    else {
2278            /* Is this code really useful ??? */
2279        if (extract_mountlist_stub) {
2280            sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2281                    bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2282            run_program_and_log_output(command, FALSE);
2283        }
2284    }
2285
2286    sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2287    run_program_and_log_output(command, FALSE);
2288    if (extract_mountlist_stub) {
2289        sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2290        run_program_and_log_output(command, FALSE);
2291    }
2292    sprintf(command, "cp -f etc/raidtab /etc/");
2293    run_program_and_log_output(command, FALSE);
2294    if (extract_i_want_my_lvm) {
2295        sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2296        run_program_and_log_output(command, FALSE);
2297    }
2298    g_backup_media_type = bkpinfo->backup_media_type;
2299    paranoid_free(device);
2300    paranoid_free(command);
2301    paranoid_free(tmp);
2302    paranoid_free(cfg_file);
2303    paranoid_free(mounted_cfgf_path);
2304    paranoid_free(mountpt);
2305    paranoid_free(ramdisk_fname);
2306    paranoid_free(mountlist_file);
2307    return (retval);
2308}
2309
2310/**************************************************************************
2311 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2312 **************************************************************************/
2313
2314/* @} - end restoreUtilityGroup */
2315
2316
2317/***************************************************************************
2318 * F@                                                                      *
2319 * () -- Hugo Rabson                                  *
2320 *                                                                         *
2321 * Purpose:                                                                *
2322 *                                                                         *
2323 * Called by:                                                              *
2324 * Params:    -                      -                                     *
2325 * Returns:   0=success; nonzero=failure                                   *
2326 ***************************************************************************/
2327
2328
2329
2330void wait_until_software_raids_are_prepped(char *mdstat_file,
2331                                           int wait_for_percentage)
2332{
2333    struct raidlist_itself *raidlist;
2334    int unfinished_mdstat_devices = 9999, i;
2335    char *screen_message;
2336
2337    malloc_string(screen_message);
2338    raidlist = malloc(sizeof(struct raidlist_itself));
2339
2340    assert(wait_for_percentage <= 100);
2341    log_it("wait_until_software_raids_are_prepped");
2342    while (unfinished_mdstat_devices > 0) {
2343            // FIXME: Prefix '/dev/' should really be dynamic!
2344        if (parse_mdstat(raidlist, "/dev/")) {
2345            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2346            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2347            return;
2348        }
2349        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2350            if (raidlist->el[i].progress < wait_for_percentage) {
2351                unfinished_mdstat_devices++;
2352                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2353                {
2354                    continue;
2355                }
2356                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2357                sprintf(screen_message, "Sync'ing %s",
2358                        raidlist->el[i].raid_device);
2359                open_evalcall_form(screen_message);
2360                while (raidlist->el[i].progress < wait_for_percentage) {
2361                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2362                    update_evalcall_form(raidlist->el[i].progress);
2363                    sleep(2);
2364                    // FIXME: Prefix '/dev/' should really be dynamic!
2365                    if (parse_mdstat(raidlist, "/dev/")) {
2366                        break;
2367                    }
2368                }
2369                close_evalcall_form();
2370            }
2371        }
2372    }
2373    paranoid_free(screen_message);
2374    paranoid_free(raidlist);
2375}
2376
2377
Note: See TracBrowser for help on using the repository browser.