source: branches/2.2.7/mondo/src/mondorestore/mondo-rstr-tools.c @ 2029

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