source: branches/2.2.6/mondo/src/mondorestore/mondo-rstr-tools.c @ 1948

Last change on this file since 1948 was 1948, checked in by bruno, 9 years ago
  • Adds OBDR support (use_obdr field in bkpinfo added, -o option changed to mean OBDR - LILO not usable anyway as a bootloader for ISO images)
  • Property svn:keywords set to Id
File size: 76.9 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);
171
172/**
173* @addtogroup restoreUtilityGroup
174* @{
175*/
176/**
177* Free the malloc()s for the filename variables.
178*/
179void free_MR_global_filenames()
180{
181paranoid_free(g_biggielist_txt);
182paranoid_free(g_filelist_full);
183paranoid_free(g_filelist_imagedevs);
184//  paranoid_free (g_imagedevs_pot );
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)) {
1281log_msg(1, "%s exists", g_filelist_full);
1282log_msg(1, "%s exists", g_biggielist_txt);
1283log_msg(2,
1284        "Filelist and biggielist already recovered from media. Yay!");
1285} else {
1286getcwd(tmp, MAX_STR_LEN);
1287chdir(bkpinfo->tmpdir);
1288log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1289log_to_screen("Extracting filelist and biggielist from media...");
1290unlink("/tmp/filelist.full");
1291unlink("/" FILELIST_FULL_STUB);
1292unlink("/tmp/i-want-my-lvm");
1293if (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//    popup_and_OK("Press ENTER to continue");
1322    if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1323        fatal_error
1324            ("all.tar.gz did not include ./tmp/biggielist.txt");
1325    }
1326    if (!does_file_exist(FILELIST_FULL_STUB)) {
1327        fatal_error
1328            ("all.tar.gz did not include ./tmp/filelist.full.gz");
1329    }
1330}
1331sprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1332        g_mondo_cfg_file);
1333run_program_and_log_output(command, FALSE);
1334
1335sprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1336        BIGGIELIST_TXT_STUB, g_biggielist_txt);
1337log_msg(1, "command = %s", command);
1338paranoid_system(command);
1339sprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1340        FILELIST_FULL_STUB, g_filelist_full);
1341log_msg(1, "command = %s", command);
1342paranoid_system(command);
1343}
1344
1345if (am_I_in_disaster_recovery_mode()
1346&&
1347ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1348{
1349//      sprintf(command, "cp -f tmp/mountlist.txt /tmp");
1350sprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1351        bkpinfo->tmpdir);
1352paranoid_system(command);
1353}
1354
1355chdir(tmp);
1356
1357if (!does_file_exist(g_biggielist_txt)) {
1358log_msg(1, "Warning - %s not found", g_biggielist_txt);
1359}
1360if (!does_file_exist(g_filelist_full)) {
1361log_msg(1, "Warning - %s does not exist", g_filelist_full);
1362}
1363//  popup_and_OK("Wonderful.");
1364
1365log_msg(2, "Forking");
1366pid = fork();
1367switch (pid) {
1368case -1:
1369fatal_error("Forking error");
1370break;
1371
1372case 0:
1373log_to_screen("Pre-processing filelist");
1374if (!does_file_exist(g_biggielist_txt)) {
1375            sprintf(command, "echo -n > %s", g_biggielist_txt);
1376            paranoid_system(command);
1377        }
1378        sprintf(command, "grep -E '^/dev/.*' %s > %s",
1379                g_biggielist_txt, g_filelist_imagedevs);
1380        paranoid_system(command);
1381        exit(0);
1382        break;
1383
1384    default:
1385        open_evalcall_form("Pre-processing filelist");
1386        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1387            usleep(100000);
1388            update_evalcall_form(0);
1389        }
1390    }
1391    close_evalcall_form();
1392
1393    log_msg(3, "loading filelist");
1394    filelist = load_filelist(g_filelist_full);
1395    log_msg(3, "deleting original filelist");
1396    unlink(g_filelist_full);
1397    if (g_text_mode) {
1398        printf("Restore which directory? --> ");
1399        fgets(tmp, sizeof(tmp), stdin);
1400        toggle_path_selection(filelist, tmp, TRUE);
1401        if (strlen(tmp) == 0) {
1402            res = 1;
1403        } else {
1404            res = 0;
1405        }
1406    } else {
1407        res = edit_filelist(filelist);
1408    }
1409    if (res) {
1410        log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1411        free_filelist(filelist);
1412        return (NULL);
1413    }
1414    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1415    close_evalcall_form();
1416
1417    // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1418    // file. The filelist.full file already contains the filename of EVERY
1419    // file backed up - regular and biggie files.
1420
1421    // However, we do want to make sure the imagedevs selected by the user
1422    // are flagged for restoring.
1423    if (length_of_file(g_imagedevs_restthese) > 2) {
1424        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1425                                      TRUE);
1426    }
1427
1428    paranoid_free(command);
1429    paranoid_free(tmp);
1430    return (filelist);
1431}
1432
1433/**************************************************************************
1434 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1435 **************************************************************************/
1436
1437
1438
1439
1440/**
1441 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1442 * The backup filename is the filename of the original with ".pristine" added.
1443 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1444 * @param filename The filename (absolute path) within @p path_root.
1445 * @return 0 for success, nonzero for failure.
1446 */
1447int backup_crucial_file(char *path_root, char *filename)
1448{
1449    char *tmp;
1450    char *command;
1451    int res;
1452
1453    malloc_string(tmp);
1454    malloc_string(command);
1455    assert(path_root != NULL);
1456    assert_string_is_neither_NULL_nor_zerolength(filename);
1457
1458    sprintf(tmp, "%s/%s", path_root, filename);
1459    sprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1460
1461    res = run_program_and_log_output(command, 5);
1462    paranoid_free(tmp);
1463    paranoid_free(command);
1464    return (res);
1465}
1466
1467
1468/**
1469 * Install the user's boot loader in the MBR.
1470 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1471 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1472 * @return 0 for success, nonzero for failure.
1473 */
1474int run_boot_loader(bool offer_to_hack_scripts)
1475{
1476    int res;
1477    int retval = 0;
1478
1479  /** malloc *******/
1480    char *device;
1481    char *tmp = NULL;
1482    char *name;
1483    char *cmd = NULL;
1484
1485    malloc_string(device);
1486    malloc_string(name);
1487
1488    /* In order to have a working bootloader, we need to have all devices
1489     * ready in the chroot. If they are not there (udev) then copy them from
1490     * the current /dev location
1491     */
1492    asprintf(&cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1493    run_program_and_log_output(cmd, 3);
1494    paranoid_free(cmd);
1495
1496    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1497    backup_crucial_file(MNT_RESTORING, "/etc/grub.conf");
1498    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1499    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1500    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1501    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1502    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1503    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1504    asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1505    log_msg(2, tmp);
1506    paranoid_free(tmp);
1507    system("sync");
1508    if (!strcmp(name, "LILO")) {
1509        res = run_lilo(offer_to_hack_scripts);
1510    } else if (!strcmp(name, "ELILO")) {
1511        res = run_elilo(offer_to_hack_scripts);
1512    } else if (!strcmp(name, "GRUB")) {
1513        res = run_grub(offer_to_hack_scripts, device);
1514    } else if (!strcmp(name, "RAW")) {
1515        res = run_raw_mbr(offer_to_hack_scripts, device);
1516    }
1517#ifdef __FreeBSD__
1518    else if (!strcmp(name, "BOOT0")) {
1519        asprintf(&tmp, "boot0cfg -B %s", device);
1520        res = run_program_and_log_output(tmp, FALSE);
1521        paranoid_free(tmp);
1522    } else {
1523        asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1524        if (!system(tmp)) {
1525            paranoid_free(tmp);
1526            asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1527            res = run_program_and_log_output(tmp, 3);
1528        } else {
1529            log_msg(1,
1530                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1531        }
1532        paranoid_free(tmp);
1533    }
1534#else
1535    else {
1536        log_to_screen
1537            ("Unable to determine type of boot loader. Defaulting to LILO.");
1538        res = run_lilo(offer_to_hack_scripts);
1539    }
1540#endif
1541    retval += res;
1542    if (res) {
1543        log_to_screen("Your boot loader returned an error");
1544    } else {
1545        log_to_screen("Your boot loader ran OK");
1546    }
1547    paranoid_free(device);
1548    paranoid_free(name);
1549    return (retval);
1550}
1551
1552/**************************************************************************
1553 *END_ RUN_BOOT_LOADER                                                    *
1554 **************************************************************************/
1555
1556
1557
1558/**
1559 * Attempt to find the user's editor.
1560 * @return The editor found ("vi" if none could be found).
1561 * @note The returned string points to static storage that will be overwritten with each call.
1562 */
1563char *find_my_editor(void)
1564{
1565    static char output[MAX_STR_LEN];
1566    if (find_home_of_exe("pico")) {
1567        strcpy(output, "pico");
1568    } else if (find_home_of_exe("nano")) {
1569        strcpy(output, "nano");
1570    } else if (find_home_of_exe("e3em")) {
1571        strcpy(output, "e3em");
1572    } else if (find_home_of_exe("e3vi")) {
1573        strcpy(output, "e3vi");
1574    } else {
1575        strcpy(output, "vi");
1576    }
1577    if (!find_home_of_exe(output)) {
1578        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1579    }
1580    return (output);
1581}
1582
1583
1584/**
1585 * Install GRUB on @p bd.
1586 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1587 * @param bd The boot device where GRUB is installed.
1588 * @return 0 for success, nonzero for failure.
1589 */
1590int run_grub(bool offer_to_run_stabgrub, char *bd)
1591{
1592  /** malloc **/
1593    char *command;
1594    char *boot_device;
1595    char *rootdev;
1596    char *rootdrive;
1597    char *conffile;
1598    char *tmp;
1599    char *editor;
1600
1601    int res;
1602    int done;
1603
1604    malloc_string(command);
1605    malloc_string(boot_device);
1606    malloc_string(tmp);
1607    malloc_string(editor);
1608    malloc_string(rootdev);
1609    malloc_string(rootdrive);
1610    malloc_string(conffile);
1611    assert_string_is_neither_NULL_nor_zerolength(bd);
1612    strcpy(editor, find_my_editor());
1613    strcpy(boot_device, bd);
1614
1615    if (!run_program_and_log_output("which grub-MR", FALSE)) {
1616        log_msg(1, "Yay! grub-MR found...");
1617        sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1618        log_msg(1, "command = %s", command);
1619    } else {
1620        sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1621                boot_device);
1622        log_msg(1, "WARNING - grub-MR not found; using grub-install");
1623    }
1624    if (offer_to_run_stabgrub
1625        && ask_me_yes_or_no("Did you change the mountlist?"))
1626        /* interactive mode */
1627    {
1628        mvaddstr_and_log_it(g_currentY,
1629                            0,
1630                            "Modifying fstab, mtab, device.map and grub.conf, and running GRUB...                             ");
1631        for (done = FALSE; !done;) {
1632            popup_and_get_string("Boot device",
1633                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1634                                 boot_device, MAX_STR_LEN / 4);
1635            sprintf(command, "stabgrub-me %s", boot_device);
1636            res = run_program_and_log_output(command, 1);
1637            if (res) {
1638                popup_and_OK
1639                    ("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.");
1640                newtSuspend();
1641                system("chroot " MNT_RESTORING);
1642                newtResume();
1643                popup_and_OK("Thank you.");
1644            } else {
1645                done = TRUE;
1646            }
1647            popup_and_OK("You will now edit fstab, mtab, device.map and grub.conf");
1648            if (!g_text_mode) {
1649                newtSuspend();
1650            }
1651            sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1652            paranoid_system(tmp);
1653            sprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1654            paranoid_system(tmp);
1655            sprintf(tmp, "chroot %s %s /etc/grub.conf", MNT_RESTORING, editor);
1656            paranoid_system(tmp);
1657            sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1658            paranoid_system(tmp);
1659            if (!g_text_mode) {
1660                newtResume();
1661            }
1662        }
1663    } else
1664        /* nuke mode */
1665    {
1666        mvaddstr_and_log_it(g_currentY,
1667                            0,
1668                            "Running GRUB...                                                 ");
1669        iamhere(command);
1670        res = run_program_and_log_output(command, 1);
1671        if (res) {
1672            popup_and_OK
1673                ("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.");
1674            newtSuspend();
1675            system("chroot " MNT_RESTORING);
1676            newtResume();
1677            popup_and_OK("Thank you.");
1678        }
1679    }
1680    if (res) {
1681        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1682        log_to_screen
1683            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1684        log_msg(1, "Type:-");
1685        log_msg(1, "    mount-me");
1686        log_msg(1, "    chroot " MNT_RESTORING);
1687        log_msg(1, "    mount /boot");
1688        log_msg(1, "    grub-install '(hd0)'");
1689        log_msg(1, "    exit");
1690        log_msg(1, "    unmount-me");
1691        log_msg(1,
1692                "If you're really stuck, please e-mail the mailing list.");
1693    } else {
1694        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1695    }
1696    paranoid_free(rootdev);
1697    paranoid_free(rootdrive);
1698    paranoid_free(conffile);
1699    paranoid_free(command);
1700    paranoid_free(boot_device);
1701    paranoid_free(tmp);
1702    paranoid_free(editor);
1703
1704    return (res);
1705}
1706
1707/**************************************************************************
1708 *END_RUN_GRUB                                                            *
1709 **************************************************************************/
1710
1711
1712/**
1713 * Install ELILO on the user's boot drive (determined by elilo.conf).
1714 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1715 * @return 0 for success, nonzero for failure.
1716 */
1717int run_elilo(bool offer_to_run_stabelilo)
1718{
1719  /** malloc **/
1720    char *command;
1721    char *tmp;
1722    char *editor;
1723
1724    int res;
1725    int done;
1726
1727    malloc_string(command);
1728    malloc_string(tmp);
1729    malloc_string(editor);
1730    strcpy(editor, find_my_editor());
1731    if (offer_to_run_stabelilo
1732        && ask_me_yes_or_no("Did you change the mountlist?"))
1733
1734        /* interactive mode */
1735    {
1736        mvaddstr_and_log_it(g_currentY,
1737                            0,
1738                            "Modifying fstab and elilo.conf...                             ");
1739        sprintf(command, "stabelilo-me");
1740        res = run_program_and_log_output(command, 3);
1741        if (res) {
1742            popup_and_OK
1743                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1744            for (done = FALSE; !done;) {
1745                if (!g_text_mode) {
1746                    newtSuspend();
1747                }
1748                sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1749                paranoid_system(tmp);
1750                sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1751                paranoid_system(tmp);
1752                if (!g_text_mode) {
1753                    newtResume();
1754                }
1755//              newtCls();
1756                if (ask_me_yes_or_no("Edit them again?")) {
1757                    continue;
1758                }
1759                done = TRUE;
1760            }
1761        } else {
1762            log_to_screen("elilo.conf and fstab were modified OK");
1763        }
1764    } else
1765        /* nuke mode */
1766    {
1767        res = TRUE;
1768    }
1769    paranoid_free(command);
1770    paranoid_free(tmp);
1771    paranoid_free(editor);
1772    return (res);
1773}
1774
1775/**************************************************************************
1776 *END_RUN_ELILO                                                            *
1777 **************************************************************************/
1778
1779
1780/**
1781 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1782 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1783 * @return 0 for success, nonzero for failure.
1784 */
1785int run_lilo(bool offer_to_run_stablilo)
1786{
1787  /** malloc **/
1788    char *command;
1789    char *tmp;
1790    char *editor;
1791
1792    int res;
1793    int done;
1794    bool run_lilo_M = FALSE;
1795    malloc_string(command);
1796    malloc_string(tmp);
1797    malloc_string(editor);
1798
1799    if (!run_program_and_log_output
1800        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1801        run_lilo_M = TRUE;
1802    }
1803
1804    strcpy(editor, find_my_editor());
1805    if (offer_to_run_stablilo
1806        && ask_me_yes_or_no("Did you change the mountlist?"))
1807
1808        /* interactive mode */
1809    {
1810        mvaddstr_and_log_it(g_currentY,
1811                            0,
1812                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1813        sprintf(command, "stablilo-me");
1814        res = run_program_and_log_output(command, 3);
1815        if (res) {
1816            popup_and_OK
1817                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1818            for (done = FALSE; !done;) {
1819                if (!g_text_mode) {
1820                    newtSuspend();
1821                }
1822                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1823                paranoid_system(tmp);
1824                sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1825                paranoid_system(tmp);
1826                if (!g_text_mode) {
1827                    newtResume();
1828                }
1829//              newtCls();
1830                if (ask_me_yes_or_no("Edit them again?")) {
1831                    continue;
1832                }
1833                res =
1834                    run_program_and_log_output("chroot " MNT_RESTORING
1835                                               " lilo -L", 3);
1836                if (res) {
1837                    res =
1838                        run_program_and_log_output("chroot " MNT_RESTORING
1839                                                   " lilo", 3);
1840                }
1841                if (res) {
1842                    done =
1843                        ask_me_yes_or_no
1844                        ("LILO failed. Re-edit system files?");
1845                } else {
1846                    done = TRUE;
1847                }
1848            }
1849        } else {
1850            log_to_screen("lilo.conf and fstab were modified OK");
1851        }
1852    } else
1853        /* nuke mode */
1854    {
1855        mvaddstr_and_log_it(g_currentY,
1856                            0,
1857                            "Running LILO...                                                 ");
1858        res =
1859            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1860                                       3);
1861        if (res) {
1862            res =
1863                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1864                                           3);
1865        }
1866        if (res) {
1867            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1868            log_to_screen
1869                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1870        } else {
1871            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1872        }
1873    }
1874    if (run_lilo_M) {
1875        run_program_and_log_output("chroot " MNT_RESTORING
1876                                   " lilo -M /dev/hda", 3);
1877        run_program_and_log_output("chroot " MNT_RESTORING
1878                                   " lilo -M /dev/sda", 3);
1879    }
1880    paranoid_free(command);
1881    paranoid_free(tmp);
1882    paranoid_free(editor);
1883    return (res);
1884}
1885
1886/**************************************************************************
1887 *END_RUN_LILO                                                            *
1888 **************************************************************************/
1889
1890
1891/**
1892 * Install a raw MBR onto @p bd.
1893 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1894 * @param bd The device to copy the stored MBR to.
1895 * @return 0 for success, nonzero for failure.
1896 */
1897int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1898{
1899  /** malloc **/
1900    char *command;
1901    char *boot_device;
1902    char *tmp;
1903    char *editor;
1904    int res;
1905    int done;
1906
1907    malloc_string(command);
1908    malloc_string(boot_device);
1909    malloc_string(tmp);
1910    malloc_string(editor);
1911    assert_string_is_neither_NULL_nor_zerolength(bd);
1912
1913    strcpy(editor, find_my_editor());
1914    strcpy(boot_device, bd);
1915    sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1916    log_msg(2, "run_raw_mbr() --- command='%s'", command);
1917
1918    if (offer_to_hack_scripts
1919        && ask_me_yes_or_no("Did you change the mountlist?"))
1920        /* interactive mode */
1921    {
1922        mvaddstr_and_log_it(g_currentY, 0,
1923                            "Modifying fstab and restoring MBR...                           ");
1924        for (done = FALSE; !done;) {
1925            if (!run_program_and_log_output("which vi", FALSE)) {
1926                popup_and_OK("You will now edit fstab");
1927                if (!g_text_mode) {
1928                    newtSuspend();
1929                }
1930                sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1931                paranoid_system(tmp);
1932                if (!g_text_mode) {
1933                    newtResume();
1934                }
1935//              newtCls();
1936            }
1937            popup_and_get_string("Boot device",
1938                                 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1939                                 boot_device, MAX_STR_LEN / 4);
1940            sprintf(command, "stabraw-me %s", boot_device);
1941            res = run_program_and_log_output(command, 3);
1942            if (res) {
1943                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1944            } else {
1945                done = TRUE;
1946            }
1947        }
1948    } else
1949        /* nuke mode */
1950    {
1951        mvaddstr_and_log_it(g_currentY, 0,
1952                            "Restoring MBR...                                               ");
1953        res = run_program_and_log_output(command, 3);
1954    }
1955    if (res) {
1956        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1957        log_to_screen
1958            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1959    } else {
1960        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1961    }
1962    paranoid_free(command);
1963    paranoid_free(boot_device);
1964    paranoid_free(tmp);
1965    paranoid_free(editor);
1966    return (res);
1967}
1968
1969/**************************************************************************
1970 *END_RUN_RAW_MBR                                                         *
1971 **************************************************************************/
1972
1973
1974
1975
1976
1977/**
1978 * Turn signal trapping on or off.
1979 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1980 * print a message and exit immediately.
1981 */
1982void set_signals(int on)
1983{
1984    int signals[] =
1985        { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1986SIGSTOP, 0 };
1987    int i;
1988    for (i = 0; signals[i]; i++) {
1989        if (on) {
1990            signal(signals[i], terminate_daemon);
1991        } else {
1992            signal(signals[i], termination_in_progress);
1993        }
1994    }
1995}
1996
1997/**************************************************************************
1998 *END_SET_SIGNALS                                                         *
1999 **************************************************************************/
2000
2001
2002/**
2003 * malloc() and set sensible defaults for the mondorestore filename variables.
2004 * @param bkpinfo The backup information structure. Fields used:
2005 * - @c bkpinfo->tmpdir
2006 * - @c bkpinfo->disaster_recovery
2007 */
2008void setup_MR_global_filenames()
2009{
2010    char *temppath;
2011
2012    assert(bkpinfo != NULL);
2013
2014    malloc_string(g_biggielist_txt);
2015    malloc_string(g_filelist_full);
2016    malloc_string(g_filelist_imagedevs);
2017    malloc_string(g_imagedevs_restthese);
2018    malloc_string(g_mondo_cfg_file);
2019    malloc_string(g_mountlist_fname);
2020    malloc_string(g_mondo_home);
2021    malloc_string(g_tmpfs_mountpt);
2022    malloc_string(g_isodir_device);
2023    malloc_string(g_isodir_format);
2024
2025    temppath = bkpinfo->tmpdir;
2026
2027    sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
2028    sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
2029    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
2030//  sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
2031    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
2032            temppath);
2033    if (bkpinfo->disaster_recovery) {
2034        sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
2035        sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
2036    } else {
2037        sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
2038        sprintf(g_mountlist_fname, "%s/%s", temppath,
2039                MOUNTLIST_FNAME_STUB);
2040    }
2041}
2042
2043/**************************************************************************
2044 *END_SET_GLOBAL_FILENAME                                                 *
2045 **************************************************************************/
2046
2047
2048/**
2049 * Copy @p input_file (containing the result of a compare) to @p output_file,
2050 * deleting spurious "changes" along the way.
2051 * @param output_file The output file to write with spurious changes removed.
2052 * @param input_file The input file, a list of changed files created by a compare.
2053 */
2054void streamline_changes_file(char *output_file, char *input_file)
2055{
2056    FILE *fin;
2057    FILE *fout;
2058  /** malloc **/
2059    char *incoming;
2060
2061    assert_string_is_neither_NULL_nor_zerolength(output_file);
2062    assert_string_is_neither_NULL_nor_zerolength(input_file);
2063    malloc_string(incoming);
2064
2065    if (!(fin = fopen(input_file, "r"))) {
2066        log_OS_error(input_file);
2067        return;
2068    }
2069    if (!(fout = fopen(output_file, "w"))) {
2070        fatal_error("cannot open output_file");
2071    }
2072    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
2073         fgets(incoming, MAX_STR_LEN - 1, fin)) {
2074        if (strncmp(incoming, "etc/adjtime", 11)
2075            && strncmp(incoming, "etc/mtab", 8)
2076            && strncmp(incoming, "tmp/", 4)
2077            && strncmp(incoming, "boot/map", 8)
2078            && !strstr(incoming, "incheckentry")
2079            && strncmp(incoming, "etc/mail/statistics", 19)
2080            && strncmp(incoming, "var/", 4))
2081            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
2082    }
2083    paranoid_fclose(fout);
2084    paranoid_fclose(fin);
2085    paranoid_free(incoming);
2086}
2087
2088/**************************************************************************
2089 *END_STREAMLINE_CHANGES_FILE                                             *
2090 **************************************************************************/
2091
2092
2093/**
2094 * Exit due to a signal (normal cleanup).
2095 * @param sig The signal we're exiting due to.
2096 */
2097void terminate_daemon(int sig)
2098{
2099    log_to_screen
2100        ("Mondorestore is terminating in response to a signal from the OS");
2101    paranoid_MR_finish(254);
2102}
2103
2104/**************************************************************************
2105 *END_TERMINATE_DAEMON                                                    *
2106 **************************************************************************/
2107
2108
2109/**
2110 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
2111 */
2112void twenty_seconds_til_yikes()
2113{
2114    int i;
2115    /* MALLOC * */
2116    char *tmp;
2117
2118    malloc_string(tmp);
2119    if (does_file_exist("/tmp/NOPAUSE")) {
2120        return;
2121    }
2122    open_progress_form("CAUTION",
2123                       "Be advised: I am about to ERASE your hard disk(s)!",
2124                       "You may press Ctrl+Alt+Del to abort safely.",
2125                       "", 20);
2126    for (i = 0; i < 20; i++) {
2127        g_current_progress = i;
2128        sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
2129        update_progress_form(tmp);
2130        sleep(1);
2131    }
2132    close_progress_form();
2133    paranoid_free(tmp);
2134}
2135
2136/**************************************************************************
2137 *END_TWENTY_SECONDS_TIL_YIKES                                            *
2138 **************************************************************************/
2139
2140
2141
2142
2143
2144/**
2145 * Exit due to a signal (no cleanup).
2146 * @param sig The signal we're exiting due to.
2147 */
2148void termination_in_progress(int sig)
2149{
2150    log_msg(1, "Termination in progress");
2151    usleep(1000);
2152    pthread_exit(0);
2153}
2154
2155/**************************************************************************
2156 *END_TERMINATION_IN_PROGRESS                                             *
2157 **************************************************************************/
2158
2159
2160
2161/**
2162 * Unmount all devices in @p p_external_copy_of_mountlist.
2163 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
2164 * @return 0 for success, nonzero for failure.
2165 */
2166int unmount_all_devices(struct mountlist_itself
2167                        *p_external_copy_of_mountlist)
2168{
2169    struct mountlist_itself *mountlist;
2170    int retval = 0, lino, res = 0, i;
2171    char *command;
2172    char *tmp;
2173
2174    malloc_string(command);
2175    malloc_string(tmp);
2176    assert(p_external_copy_of_mountlist != NULL);
2177
2178    mountlist = malloc(sizeof(struct mountlist_itself));
2179    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
2180           sizeof(struct mountlist_itself));
2181    sort_mountlist_by_mountpoint(mountlist, 0);
2182
2183    run_program_and_log_output("df -m", 3);
2184    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
2185    open_progress_form("Unmounting devices",
2186                       "Unmounting all devices that were mounted,",
2187                       "in preparation for the post-restoration reboot.",
2188                       "", mountlist->entries);
2189    chdir("/");
2190    for (i = 0;
2191         i < 10
2192         &&
2193         run_program_and_log_output
2194         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
2195         i++) {
2196        sleep(1);
2197        log_msg(2, "Waiting for buffer() to finish");
2198    }
2199
2200    paranoid_system("sync");
2201
2202    sprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
2203    if (run_program_and_log_output(tmp, FALSE)) {
2204        log_msg(1,
2205                "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
2206    }
2207    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
2208        run_program_and_log_output("mkdir -p " MNT_RESTORING
2209                                   "/mnt/.boot.d", 5);
2210    }
2211    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
2212        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2213            continue;
2214        }
2215        sprintf(tmp, "Unmounting device %s  ", mountlist->el[lino].device);
2216
2217        update_progress_form(tmp);
2218        if (is_this_device_mounted(mountlist->el[lino].device)) {
2219            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2220                sprintf(command, "swapoff %s", mountlist->el[lino].device);
2221            } else {
2222                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2223                    sprintf(command, "umount %s/", MNT_RESTORING);
2224                    log_msg(3,
2225                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2226                } else {
2227                    sprintf(command, "umount " MNT_RESTORING "%s",
2228                            mountlist->el[lino].mountpoint);
2229                }
2230            }
2231            log_msg(10, "The 'umount' command is '%s'", command);
2232            res = run_program_and_log_output(command, 3);
2233        } else {
2234            strcat(tmp, "...not mounted anyway :-) OK");
2235            res = 0;
2236        }
2237        g_current_progress++;
2238        if (res) {
2239            strcat(tmp, "...Failed");
2240            retval++;
2241            log_to_screen(tmp);
2242        } else {
2243            log_msg(2, tmp);
2244        }
2245    }
2246    close_progress_form();
2247    if (retval) {
2248        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2249    } else {
2250        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2251    }
2252    if (retval) {
2253        log_to_screen("Unable to unmount some of your partitions.");
2254    } else {
2255        log_to_screen("All partitions were unmounted OK.");
2256    }
2257    free(mountlist);
2258    paranoid_free(command);
2259    paranoid_free(tmp);
2260    return (retval);
2261}
2262
2263/**************************************************************************
2264 *END_UNMOUNT_ALL_DEVICES                                                 *
2265 **************************************************************************/
2266
2267
2268
2269/**
2270 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2271 * to the ./tmp/ directory.
2272 * @param dev The tape device to read from.
2273 * @return 0 for success, nonzero for failure.
2274 */
2275int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2276{
2277    char *command;
2278    int res = 0;
2279    // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2280    long tape_block_size = 32768;
2281
2282    malloc_string(command);
2283
2284    // tar -zxvf-
2285    sprintf(command,
2286            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2287            dev,
2288            tape_block_size,
2289            1024L * 1024 * 32 / tape_block_size,
2290            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2291            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "./tmp/i-want-my-lvm");
2292    log_msg(2, "command = '%s'", command);
2293    res = run_program_and_log_output(command, -1);
2294    if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2295        res = 0;
2296    }
2297    paranoid_free(command);
2298    return (res);
2299}
2300
2301
2302
2303/**
2304 * Get the configuration file from the floppy, tape, or CD.
2305 * @param bkpinfo The backup information structure. Fields used:
2306 * - @c bkpinfo->backup_media_type
2307 * - @c bkpinfo->media_device
2308 * - @c bkpinfo->tmpdir
2309 * @return 0 for success, nonzero for failure.
2310 */
2311int get_cfg_file_from_archive()
2312{
2313    int retval = 0;
2314
2315   /** malloc *****/
2316    char *device;
2317    char *command;
2318    char *cfg_file;
2319    char *mounted_cfgf_path;
2320    char *tmp;
2321    char *mountpt;
2322    char *ramdisk_fname;
2323    char *mountlist_file;
2324
2325    bool try_plan_B;
2326
2327    assert(bkpinfo != NULL);
2328    malloc_string(cfg_file);
2329    malloc_string(mounted_cfgf_path);
2330    malloc_string(mountpt);
2331    malloc_string(ramdisk_fname);
2332    malloc_string(mountlist_file);
2333    malloc_string(device);
2334    malloc_string(command);
2335    malloc_string(tmp);
2336    log_msg(2, "gcffa --- starting");
2337    log_to_screen("I'm thinking...");
2338    sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2339    device[0] = '\0';
2340    chdir(bkpinfo->tmpdir);
2341    strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2342    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
2343    unlink(FILELIST_FULL_STUB);
2344    unlink(BIGGIELIST_TXT_STUB);
2345    unlink("tmp/i-want-my-lvm");
2346    sprintf(command, "mkdir -p %s", mountpt);
2347    run_program_and_log_output(command, FALSE);
2348
2349//   unlink( "tmp/mondo-restore.cfg" ); // superfluous, surely?
2350
2351    sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2352    sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir,
2353            MOUNTLIST_FNAME_STUB);
2354    //   make_hole_for_file( cfg_file );
2355    //   make_hole_for_file( mountlist_file);
2356    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2357
2358    if (!does_file_exist(cfg_file)) {
2359        log_msg(2, "gcffa --- we don't have cfg file yet.");
2360        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2361            try_plan_B = TRUE;
2362        } else {
2363            log_msg(2, "gcffa --- calling mount_media now :)");
2364            if (!mount_media()) {
2365                log_msg(2,
2366                        "gcffa --- managed to mount CD; so, no need for Plan B");
2367                try_plan_B = FALSE;
2368            } else {
2369                try_plan_B = TRUE;
2370            }
2371            if (what_number_cd_is_this() > 1) {
2372                insist_on_this_cd_number((g_current_media_number = 1));
2373            }
2374        }
2375        if (try_plan_B) {
2376            log_msg(2, "gcffa --- OK, switching to Plan B");
2377            chdir(bkpinfo->tmpdir);
2378            run_program_and_log_output("mkdir -p tmp", FALSE);
2379
2380            if (strlen(bkpinfo->media_device) == 0) {
2381                strcpy(bkpinfo->media_device, "/dev/st0");
2382                log_msg(2, "media_device is blank; assuming %s");
2383            }
2384            strcpy(tmp, bkpinfo->media_device);
2385            if (extract_cfg_file_and_mountlist_from_tape_dev
2386                (bkpinfo->media_device)) {
2387                strcpy(bkpinfo->media_device, "/dev/st0");
2388                if (extract_cfg_file_and_mountlist_from_tape_dev
2389                    (bkpinfo->media_device)) {
2390                    strcpy(bkpinfo->media_device, "/dev/osst0");
2391                    if (extract_cfg_file_and_mountlist_from_tape_dev
2392                        (bkpinfo->media_device)) {
2393                        strcpy(bkpinfo->media_device, "/dev/ht0");
2394                        if (extract_cfg_file_and_mountlist_from_tape_dev
2395                            (bkpinfo->media_device)) {
2396                            log_msg(3,
2397                                    "I tried lots of devices but none worked.");
2398                            strcpy(bkpinfo->media_device, tmp);
2399                        }
2400                    }
2401                }
2402            }
2403
2404            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2405                log_to_screen("Cannot find config info on media");
2406                return (1);
2407            }
2408        } else {
2409                log_msg(2,
2410                        "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2411                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
2412                run_program_and_log_output(command, TRUE);
2413                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2414                    fatal_error
2415                        ("Please reinsert the disk/CD and try again.");
2416                }
2417        }
2418    }
2419    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2420        log_msg(1, "gcffa --- great! We've got the config file");
2421        sprintf(tmp, "%s/%s",
2422                call_program_and_get_last_line_of_output("pwd"),
2423                MONDO_CFG_FILE_STUB);
2424        sprintf(command, "cp -f %s %s", tmp, cfg_file);
2425        iamhere(command);
2426        if (strcmp(tmp, cfg_file)
2427            && run_program_and_log_output(command, 1)) {
2428            log_msg(1,
2429                    "... but an error occurred when I tried to move it to %s",
2430                    cfg_file);
2431        } else {
2432            log_msg(1, "... and I moved it successfully to %s", cfg_file);
2433        }
2434        sprintf(command, "cp -f %s/%s %s",
2435                call_program_and_get_last_line_of_output("pwd"),
2436                MOUNTLIST_FNAME_STUB, mountlist_file);
2437        iamhere(command);
2438        if (strcmp(tmp, cfg_file)
2439            && run_program_and_log_output(command, 1)) {
2440            log_msg(1, "Failed to get mountlist");
2441        } else {
2442            log_msg(1, "Got mountlist too");
2443            sprintf(command, "cp -f %s %s", mountlist_file,
2444                    g_mountlist_fname);
2445            if (run_program_and_log_output(command, 1)) {
2446                log_msg(1, "Failed to copy mountlist to /tmp");
2447            } else {
2448                log_msg(1, "Copied mountlist to /tmp as well OK");
2449                sprintf(command, "cp -f tmp/i-want-my-lvm /tmp/");
2450                run_program_and_log_output(command, 1);
2451/*        sprintf(command, "grep \" lvm \" %s", g_mountlist_fname);
2452          if (!run_program_and_log_output(command, 5) && !does_file_exist("/tmp/i-want-my-lvm"))
2453            {
2454          log_msg(1, "Warning. You want LVM but I don't have i-want-my-lvm. FIXME.");
2455        }
2456              else if (run_program_and_log_output(command,5) && does_file_exist("/tmp/i-want-my-lvm"))
2457                {
2458          log_msg(1, "Warning. You don't want LVM but i-want-my-lvm exists. I'll delete it. Cool.");
2459              do_my_funky_lvm_stuff(TRUE, FALSE); // ...after I stop any LVMs :)
2460          stop_raid_device("/dev/md0");
2461          stop_raid_device("/dev/md1");
2462          stop_raid_device("/dev/md2");
2463          unlink("/tmp/i-want-my-lvm");
2464        }
2465          else if (!run_program_and_log_output(command,5) && does_file_exist("/tmp/i-want-my-lvm"))
2466            {
2467          log_msg(1, "You had better pray that i-want-my-lvm patches your mountlist. FIXME.");
2468        }
2469*/
2470            }
2471        }
2472    }
2473    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2474    if (!does_file_exist(cfg_file)) {
2475        iamhere(cfg_file);
2476        log_msg(1, "%s not found", cfg_file);
2477        log_to_screen
2478            ("Oh dear. Unable to recover configuration file from boot disk");
2479        return (1);
2480    }
2481
2482    log_to_screen("Recovered mondo-restore.cfg");
2483    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2484        log_to_screen("...but not mountlist.txt - a pity, really...");
2485    }
2486/* start SAH */
2487    else {
2488        sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2489                bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2490        run_program_and_log_output(command, FALSE);
2491    }
2492/*--commented out by SAH
2493  sprintf( command, "cp -f %s %s/%s", cfg_file, bkpinfo->tmpdir, MONDO_CFG_FILE_STUB );
2494  run_program_and_log_output( command, FALSE );
2495  sprintf( command, "cp -f %s %s/%s", mountlist_file, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB );
2496  run_program_and_log_output( command, FALSE );
2497*/
2498/* end SAH */
2499
2500    sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2501    run_program_and_log_output(command, FALSE);
2502    sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2503    run_program_and_log_output(command, FALSE);
2504    sprintf(command, "cp -f etc/raidtab /etc/");
2505    run_program_and_log_output(command, FALSE);
2506    sprintf(command, "cp -f tmp/i-want-my-lvm /tmp/");
2507    run_program_and_log_output(command, FALSE);
2508    g_backup_media_type = bkpinfo->backup_media_type;
2509    paranoid_free(device);
2510    paranoid_free(command);
2511    paranoid_free(tmp);
2512    paranoid_free(cfg_file);
2513    paranoid_free(mounted_cfgf_path);
2514    paranoid_free(mountpt);
2515    paranoid_free(ramdisk_fname);
2516    paranoid_free(mountlist_file);
2517    return (retval);
2518}
2519
2520/**************************************************************************
2521 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2522 **************************************************************************/
2523
2524/* @} - end restoreUtilityGroup */
2525
2526
2527/***************************************************************************
2528 * F@                                                                      *
2529 * () -- Hugo Rabson                                  *
2530 *                                                                         *
2531 * Purpose:                                                                *
2532 *                                                                         *
2533 * Called by:                                                              *
2534 * Params:    -                      -                                     *
2535 * Returns:   0=success; nonzero=failure                                   *
2536 ***************************************************************************/
2537
2538
2539
2540void wait_until_software_raids_are_prepped(char *mdstat_file,
2541                                           int wait_for_percentage)
2542{
2543    struct raidlist_itself *raidlist;
2544    int unfinished_mdstat_devices = 9999, i;
2545    char *screen_message;
2546
2547    malloc_string(screen_message);
2548    raidlist = malloc(sizeof(struct raidlist_itself));
2549
2550    assert(wait_for_percentage <= 100);
2551    iamhere("wait_until_software_raids_are_prepped");
2552    while (unfinished_mdstat_devices > 0) {
2553            // FIXME: Prefix '/dev/' should really be dynamic!
2554        if (parse_mdstat(raidlist, "/dev/")) {
2555            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2556            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2557            return;
2558        }
2559        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2560            if (raidlist->el[i].progress < wait_for_percentage) {
2561                unfinished_mdstat_devices++;
2562                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2563                {
2564                    continue;
2565                }
2566                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2567                sprintf(screen_message, "Sync'ing %s",
2568                        raidlist->el[i].raid_device);
2569                open_evalcall_form(screen_message);
2570                while (raidlist->el[i].progress < wait_for_percentage) {
2571                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2572                    update_evalcall_form(raidlist->el[i].progress);
2573                    sleep(2);
2574                    // FIXME: Prefix '/dev/' should really be dynamic!
2575                    if (parse_mdstat(raidlist, "/dev/")) {
2576                        break;
2577                    }
2578                }
2579                close_evalcall_form();
2580            }
2581        }
2582    }
2583    paranoid_free(screen_message);
2584    paranoid_free(raidlist);
2585}
Note: See TracBrowser for help on using the repository browser.