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

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