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

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

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