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

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