source: branches/2.2.9/mondo/src/mondorestore/mondo-rstr-tools.c @ 2143

Last change on this file since 2143 was 2143, checked in by bruno, 11 years ago

Really fix the Ubuntu issue with a separate /var this time

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