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

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