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

Last change on this file since 1086 was 1086, checked in by bruno, 13 years ago

log_msg => mr_msg in trunk

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