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

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

merge -r938:954 $SVN_M/branches/stable

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