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

Last change on this file since 2242 was 2242, checked in by bruno, 10 years ago

r3145@localhost: bruno | 2009-06-29 17:18:58 +0200

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