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

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

r3333@localhost: bruno | 2009-08-08 01:58:31 +0200

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