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

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