source: branches/stable/mondo/src/mondorestore/mondo-rstr-tools.c @ 1842

Last change on this file since 1842 was 1842, checked in by bruno, 12 years ago
  • Fix lack of /etc/raidtab at restore rime in the right place
  • Adds support for nls_utf8 and pata_serverworks Patches from Dirk Husung (husung_at_tu-harburg.de)
  • Add efibootmgr to deplist.txt in order to be able to modify EFI menu at restore time on ia64
  • Usage of the new testver param of pb 0.8.12 to deliver 2.2.5 packages in a test dir.
  • Update pbcl files for upcoming delivery of 2.2.5
  • Fix an issue on parted output (K instead of KB) in parted2fdisk at restore time
  • Adds support for alb/aft types of bonding on Intel cards (Mark Pinkerton <Mark.Pinkerton_at_emageon.com>)
  • Escape variables in a perl script like mindi-bkphw
  • Better Proliant support at restore time now.
  • Fix a label bug where the variable label should also be re-initialized at each loop
  • start-nfs should NOT do exit => kernel panix as init exits
  • some other fixes for init on denymods
  • Adds boot options denymods (for udev) and forcemods (if not udev)
  • kqemu is denied. Probably should also be done for kvm stuff
  • Fix again the bug on modules link at root of the initrd. Hopefully for good.
  • Wait more around the USB CD emulated by iLO as it takes up to 5 seconds to come up
  • Attempt to fix udev support for RHEL 5.1
  • Better support for automatic iLO Virtual Media with udev
  • Some VMWare support improvements (however, it seems that VMWare support won't be possible anytime soon)
  • during init at restore time, copy all static evices availble for udev, as some distro implementation are no

t yet supported correctly for udev. Not very elegant, but should solve our current issues

  • Fedora 8 now supported as a build target for pb
  • svn.log removed.
  • dependencies reviewd for rhel_3
  • Attempt to fix the lack of modules loaded at restore time - especially fs device drivers
  • removes bkphw dir before potential creation
  • render mount command more vebose at restore time
  • Should fix #217
  • Increase BOOT_SIZE and EXTRA_SIZE to support features such as HW recovery
  • Handles udev.files files which could be symlinks
  • Improve udev support for distro with compressed modules (mdv e.g.)
  • Fix modules.dep copy
  • /sbin/pam_console_apply is needed by mdv udev conf
  • Adds support for nohw boot option to avoid re-setuping the HW conf
  • Improved support for Proliant on cpqacuxe
  • RstHW should be called after driver initialization
  • For debian/ubuntu mindi dpends on mindi-busybox
  • Update mindi-busybox pbcl for correct debian changelog generation, and up2date infos
  • Should fix #215
  • Fix #214 (Thanks to xdelaruelle)
  • Fix again svn.log not used anymore with new pb version
  • Adaptation of build process to upcoming 0.8.12 version of pb
  • Remove MONOTONIC clock to continue to support 2.4 kernels (RHEL 3 e.g. or ESX)
  • Attempt to solve ia64 BMC access through the serial port
  • parted2fdisk binary no more generated
  • do not require perl modules (strict.pm) at restore time
  • try to avoid modprobe messages at restore time
  • on ia64 now use the perl script parted2fdisk at retore time also
  • Also modprobe modules for udev after decompressing the additional ones
  • replace gzip -v9 by gzip -c9. Fix a bug at least on ia64
  • For all modules supported, create symlinks under the mountpoint and extract dev files as some are not automat ically created at the moment
  • Support /vmfs/volumes for ESX
  • Finally do not use vdf for ESX. Only creates issues.
  • Avoids continuing hw support if no product name found
  • Improves ia64 support for bootable image build
  • Fix a potential problem with ramdisk_blocksize param
  • MAKEDEV should also be included in deplist.txt
  • More fixes for udev support for Debian
  • Do not mount /boot if it's already mounted - avoids ESX hang
  • Fix NICs renumbering on Debian at least
  • Udev startup improvement to support iLO + NFS so modprobing all modules seems required as of now
  • Update to version 1.7.3 of busybox for pb
  • Load USB earlier in order to support KBD such as with iLO
  • Do busybox ldd first in order to create a potential /lib64 link correctly and then use it later in the image
  • Use variable DF in mindi to be able to support the ESX vdf
  • Fix mindi for Debian x86_64 where /lib64 is a link
  • Fix issue at restore time for ext2fs params not reused (Fix from Klaus Ade Johnstad <klaus_at_skolelinux.no>)
  • Do not copy udev files if they do not exist In udev case do not insert modules at all (udev should do it alone) May avoid the issue with rhel4.5 kernel ? To be tested
  • Update dependencies for rpm base build as well
  • And also perl is a debian/ubuntu dep
  • Better debian/ubuntu dependecies requirements (mtools)
  • Fix modes on mindi-bkphw (Thanks Phil Walker phil.walker_at_hp.com)
  • Complete rev [1771] for upper case RESTORE cli with syslinux as well
  • Update mindi-busybox to 1.7.3
  • Use RESTORE consistently across mondo to restore without interaction (report from Takeshi Shoji t.shoji_at_tripodw.jp)

(merge -r1769:1841 $SVN_M/branches/2.2.5)

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