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

Last change on this file since 1996 was 1996, checked in by Bruno Cornec, 13 years ago

small cleanup

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