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

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

r3334@localhost: bruno | 2009-08-08 12:17:37 +0200

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