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

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

r3275@localhost: bruno | 2009-07-19 23:23:18 +0200

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