source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondo-rstr-tools.c @ 2287

Last change on this file since 2287 was 2287, checked in by Bruno Cornec, 11 years ago

r3289@localhost: bruno | 2009-07-21 15:12:29 +0200

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