source: branches/2.2.8/mondo/src/mondorestore/mondo-rstr-tools.c @ 2136

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

Fix a bug with Newt where a newtResume was missing after multipath.conf edit

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