source: trunk/mondo/src/mondorestore/mondo-rstr-tools.c @ 1043

Last change on this file since 1043 was 1043, checked in by bruno, 12 years ago

merge -r978:1042 $SVN_M/branches/stable

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