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

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