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

Last change on this file since 2758 was 2758, checked in by Bruno Cornec, 13 years ago
  • Improved message for Arch Linux for rebuilding the initrd (mc_at_carreira.com.pt)
  • Property svn:keywords set to Id
File size: 71.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2758 2011-04-07 09:31:12Z 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 if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1243 popup_and_OK("You'll now be chrooted under your future / partition.\nEdit /etc/mkinitcpio.conf if needed and rebuild your initrd with the kernel preset name e.g.\nmkinitcpio -p kernel26\nThen type exit to finish.\n");
1244 } else {
1245 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.");
1246 }
1247 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1248 if (!g_text_mode) {
1249 newtSuspend();
1250 }
1251 (void)system("chroot " MNT_RESTORING);
1252 if (!g_text_mode) {
1253 newtResume();
1254 }
1255 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1256 } else {
1257 return;
1258 }
1259} else {
1260 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1261 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1262}
1263}
1264
1265
1266/**
1267 * Install the user's boot loader in the MBR.
1268 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1269 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1270 * @return 0 for success, nonzero for failure.
1271 */
1272int run_boot_loader(bool offer_to_hack_scripts)
1273{
1274 int res;
1275 int retval = 0;
1276
1277 /** malloc *******/
1278 char *device;
1279 char *tmp = NULL;
1280 char *name;
1281 char *cmd = NULL;
1282
1283 malloc_string(device);
1284 malloc_string(name);
1285
1286 /* In order to have a working bootloader, we need to have all devices
1287 * ready in the chroot. If they are not there (udev) then copy them from
1288 * the current /dev location
1289 */
1290 mr_asprintf(&cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1291 run_program_and_log_output(cmd, 3);
1292 paranoid_free(cmd);
1293
1294 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1295 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1296 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1297 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1298 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1299 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1300 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1301 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1302 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1303 mr_asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1304 log_msg(2, tmp);
1305 paranoid_free(tmp);
1306 system("sync");
1307
1308 offer_to_make_initrd();
1309 if (!strcmp(name, "LILO")) {
1310 res = run_lilo(offer_to_hack_scripts);
1311 } else if (!strcmp(name, "ELILO")) {
1312 res = run_elilo(offer_to_hack_scripts);
1313 } else if (!strcmp(name, "GRUB")) {
1314 res = run_grub(offer_to_hack_scripts, device);
1315 } else if (!strcmp(name, "RAW")) {
1316 res = run_raw_mbr(offer_to_hack_scripts, device);
1317 }
1318#ifdef __FreeBSD__
1319 else if (!strcmp(name, "BOOT0")) {
1320 mr_asprintf(&tmp, "boot0cfg -B %s", device);
1321 res = run_program_and_log_output(tmp, FALSE);
1322 paranoid_free(tmp);
1323 } else {
1324 mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1325 if (!system(tmp)) {
1326 paranoid_free(tmp);
1327 mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1328 res = run_program_and_log_output(tmp, 3);
1329 } else {
1330 log_msg(1,
1331 "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1332 }
1333 paranoid_free(tmp);
1334 }
1335#else
1336 else {
1337 log_to_screen
1338 ("Unable to determine type of boot loader. Defaulting to LILO.");
1339 res = run_lilo(offer_to_hack_scripts);
1340 }
1341#endif
1342 retval += res;
1343 if (res) {
1344 log_to_screen("Your boot loader returned an error");
1345 } else {
1346 log_to_screen("Your boot loader ran OK");
1347 }
1348 paranoid_free(device);
1349 paranoid_free(name);
1350 return (retval);
1351}
1352
1353/**************************************************************************
1354 *END_ RUN_BOOT_LOADER *
1355 **************************************************************************/
1356
1357
1358
1359/**
1360 * Attempt to find the user's editor.
1361 * @return The editor found ("vi" if none could be found).
1362 * @note The returned string points to static storage that will be overwritten with each call.
1363 */
1364char *find_my_editor(void)
1365{
1366 static char output[MAX_STR_LEN];
1367 if (find_home_of_exe("pico")) {
1368 strcpy(output, "pico");
1369 } else if (find_home_of_exe("nano")) {
1370 strcpy(output, "nano");
1371 } else if (find_home_of_exe("e3em")) {
1372 strcpy(output, "e3em");
1373 } else if (find_home_of_exe("e3vi")) {
1374 strcpy(output, "e3vi");
1375 } else {
1376 strcpy(output, "vi");
1377 }
1378 if (!find_home_of_exe(output)) {
1379 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1380 }
1381 return (output);
1382}
1383
1384
1385/**
1386 * Install GRUB on @p bd.
1387 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1388 * @param bd The boot device where GRUB is installed.
1389 * @return 0 for success, nonzero for failure.
1390 */
1391int run_grub(bool offer_to_run_stabgrub, char *bd)
1392{
1393 /** malloc **/
1394 char *command;
1395 char *boot_device;
1396 char *rootdev;
1397 char *rootdrive;
1398 char *conffile;
1399 char *tmp;
1400 char *editor;
1401
1402 int res;
1403 int done;
1404
1405 malloc_string(command);
1406 malloc_string(boot_device);
1407 malloc_string(tmp);
1408 malloc_string(editor);
1409 malloc_string(rootdev);
1410 malloc_string(rootdrive);
1411 malloc_string(conffile);
1412 assert_string_is_neither_NULL_nor_zerolength(bd);
1413 strcpy(editor, find_my_editor());
1414 strcpy(boot_device, bd);
1415
1416 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1417 log_msg(1, "Yay! grub-MR found...");
1418 sprintf(command, "grub-MR %s /tmp/mountlist.txt", boot_device);
1419 log_msg(1, "command = %s", command);
1420 } else {
1421 sprintf(command, "chroot " MNT_RESTORING " grub-install %s",
1422 boot_device);
1423 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1424 }
1425 if (offer_to_run_stabgrub
1426 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1427 /* interactive mode */
1428 {
1429 mvaddstr_and_log_it(g_currentY,
1430 0,
1431 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1432 for (done = FALSE; !done;) {
1433 popup_and_get_string("Boot device",
1434 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1435 boot_device, MAX_STR_LEN / 4);
1436 sprintf(command, "stabgrub-me %s", boot_device);
1437 res = run_program_and_log_output(command, 1);
1438 if (res) {
1439 popup_and_OK
1440 ("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.");
1441 newtSuspend();
1442 system("chroot " MNT_RESTORING);
1443 newtResume();
1444 popup_and_OK("Thank you.");
1445 } else {
1446 done = TRUE;
1447 }
1448 popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
1449 if (!g_text_mode) {
1450 newtSuspend();
1451 }
1452 sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1453 paranoid_system(tmp);
1454 sprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1455 paranoid_system(tmp);
1456 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1457 sprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1458 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1459 sprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1460 }
1461 paranoid_system(tmp);
1462 sprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1463 paranoid_system(tmp);
1464 if (!g_text_mode) {
1465 newtResume();
1466 }
1467 }
1468 } else
1469 /* nuke mode */
1470 {
1471 mvaddstr_and_log_it(g_currentY,
1472 0,
1473 "Running GRUB... ");
1474 log_it("%s",command);
1475 res = run_program_and_log_output(command, 1);
1476 if (res) {
1477 popup_and_OK
1478 ("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.");
1479 newtSuspend();
1480 system("chroot " MNT_RESTORING);
1481 newtResume();
1482 popup_and_OK("Thank you.");
1483 }
1484 }
1485 if (res) {
1486 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1487 log_to_screen
1488 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1489 log_msg(1, "Type:-");
1490 log_msg(1, " mount-me");
1491 log_msg(1, " chroot " MNT_RESTORING);
1492 log_msg(1, " mount /boot");
1493 log_msg(1, " grub-install '(hd0)'");
1494 log_msg(1, " exit");
1495 log_msg(1, " unmount-me");
1496 log_msg(1,
1497 "If you're really stuck, please e-mail the mailing list.");
1498 } else {
1499 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1500 }
1501 paranoid_free(rootdev);
1502 paranoid_free(rootdrive);
1503 paranoid_free(conffile);
1504 paranoid_free(command);
1505 paranoid_free(boot_device);
1506 paranoid_free(tmp);
1507 paranoid_free(editor);
1508
1509 return (res);
1510}
1511
1512/**************************************************************************
1513 *END_RUN_GRUB *
1514 **************************************************************************/
1515
1516
1517/**
1518 * Install ELILO on the user's boot drive (determined by elilo.conf).
1519 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1520 * @return 0 for success, nonzero for failure.
1521 */
1522int run_elilo(bool offer_to_run_stabelilo)
1523{
1524 /** malloc **/
1525 char *command;
1526 char *tmp;
1527 char *editor;
1528
1529 int res;
1530 int done;
1531
1532 malloc_string(command);
1533 malloc_string(tmp);
1534 malloc_string(editor);
1535 strcpy(editor, find_my_editor());
1536 if (offer_to_run_stabelilo
1537 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1538
1539 /* interactive mode */
1540 {
1541 mvaddstr_and_log_it(g_currentY,
1542 0,
1543 "Modifying fstab and elilo.conf... ");
1544 sprintf(command, "stabelilo-me");
1545 res = run_program_and_log_output(command, 3);
1546 if (res) {
1547 popup_and_OK
1548 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1549 for (done = FALSE; !done;) {
1550 if (!g_text_mode) {
1551 newtSuspend();
1552 }
1553 sprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1554 paranoid_system(tmp);
1555 sprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1556 paranoid_system(tmp);
1557 if (!g_text_mode) {
1558 newtResume();
1559 }
1560// newtCls();
1561 if (ask_me_yes_or_no("Edit them again?")) {
1562 continue;
1563 }
1564 done = TRUE;
1565 }
1566 } else {
1567 log_to_screen("elilo.conf and fstab were modified OK");
1568 }
1569 } else
1570 /* nuke mode */
1571 {
1572 res = TRUE;
1573 }
1574 paranoid_free(command);
1575 paranoid_free(tmp);
1576 paranoid_free(editor);
1577 return (res);
1578}
1579
1580/**************************************************************************
1581 *END_RUN_ELILO *
1582 **************************************************************************/
1583
1584
1585/**
1586 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1587 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1588 * @return 0 for success, nonzero for failure.
1589 */
1590int run_lilo(bool offer_to_run_stablilo)
1591{
1592 /** malloc **/
1593 char *command;
1594 char *tmp;
1595 char *editor;
1596
1597 int res;
1598 int done;
1599 bool run_lilo_M = FALSE;
1600 malloc_string(command);
1601 malloc_string(tmp);
1602 malloc_string(editor);
1603
1604 if (!run_program_and_log_output
1605 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1606 run_lilo_M = TRUE;
1607 }
1608
1609 strcpy(editor, find_my_editor());
1610 if (offer_to_run_stablilo
1611 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1612
1613 /* interactive mode */
1614 {
1615 mvaddstr_and_log_it(g_currentY,
1616 0,
1617 "Modifying fstab and lilo.conf, and running LILO... ");
1618 sprintf(command, "stablilo-me");
1619 res = run_program_and_log_output(command, 3);
1620 if (res) {
1621 popup_and_OK
1622 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1623 for (done = FALSE; !done;) {
1624 if (!g_text_mode) {
1625 newtSuspend();
1626 }
1627 sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1628 paranoid_system(tmp);
1629 sprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1630 paranoid_system(tmp);
1631 if (!g_text_mode) {
1632 newtResume();
1633 }
1634// newtCls();
1635 if (ask_me_yes_or_no("Edit them again?")) {
1636 continue;
1637 }
1638 res =
1639 run_program_and_log_output("chroot " MNT_RESTORING
1640 " lilo -L", 3);
1641 if (res) {
1642 res =
1643 run_program_and_log_output("chroot " MNT_RESTORING
1644 " lilo", 3);
1645 }
1646 if (res) {
1647 done =
1648 ask_me_yes_or_no
1649 ("LILO failed. Re-edit system files?");
1650 } else {
1651 done = TRUE;
1652 }
1653 }
1654 } else {
1655 log_to_screen("lilo.conf and fstab were modified OK");
1656 }
1657 } else
1658 /* nuke mode */
1659 {
1660 mvaddstr_and_log_it(g_currentY,
1661 0,
1662 "Running LILO... ");
1663 res =
1664 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1665 3);
1666 if (res) {
1667 res =
1668 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1669 3);
1670 }
1671 if (res) {
1672 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1673 log_to_screen
1674 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1675 } else {
1676 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1677 }
1678 }
1679 if (run_lilo_M) {
1680 run_program_and_log_output("chroot " MNT_RESTORING
1681 " lilo -M /dev/hda", 3);
1682 run_program_and_log_output("chroot " MNT_RESTORING
1683 " lilo -M /dev/sda", 3);
1684 }
1685 paranoid_free(command);
1686 paranoid_free(tmp);
1687 paranoid_free(editor);
1688 return (res);
1689}
1690
1691/**************************************************************************
1692 *END_RUN_LILO *
1693 **************************************************************************/
1694
1695
1696/**
1697 * Install a raw MBR onto @p bd.
1698 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1699 * @param bd The device to copy the stored MBR to.
1700 * @return 0 for success, nonzero for failure.
1701 */
1702int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1703{
1704 /** malloc **/
1705 char *command;
1706 char *boot_device;
1707 char *tmp;
1708 char *editor;
1709 int res;
1710 int done;
1711
1712 malloc_string(command);
1713 malloc_string(boot_device);
1714 malloc_string(tmp);
1715 malloc_string(editor);
1716 assert_string_is_neither_NULL_nor_zerolength(bd);
1717
1718 strcpy(editor, find_my_editor());
1719 strcpy(boot_device, bd);
1720 sprintf(command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1721 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1722
1723 if (offer_to_hack_scripts
1724 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1725 /* interactive mode */
1726 {
1727 mvaddstr_and_log_it(g_currentY, 0,
1728 "Modifying fstab and restoring MBR... ");
1729 for (done = FALSE; !done;) {
1730 if (!run_program_and_log_output("which vi", FALSE)) {
1731 popup_and_OK("You will now edit fstab");
1732 if (!g_text_mode) {
1733 newtSuspend();
1734 }
1735 sprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1736 paranoid_system(tmp);
1737 if (!g_text_mode) {
1738 newtResume();
1739 }
1740// newtCls();
1741 }
1742 popup_and_get_string("Boot device",
1743 "Please confirm/enter the boot device. If in doubt, try /dev/hda",
1744 boot_device, MAX_STR_LEN / 4);
1745 sprintf(command, "stabraw-me %s", boot_device);
1746 res = run_program_and_log_output(command, 3);
1747 if (res) {
1748 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1749 } else {
1750 done = TRUE;
1751 }
1752 }
1753 } else
1754 /* nuke mode */
1755 {
1756 mvaddstr_and_log_it(g_currentY, 0,
1757 "Restoring MBR... ");
1758 res = run_program_and_log_output(command, 3);
1759 }
1760 if (res) {
1761 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1762 log_to_screen
1763 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1764 } else {
1765 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1766 }
1767 paranoid_free(command);
1768 paranoid_free(boot_device);
1769 paranoid_free(tmp);
1770 paranoid_free(editor);
1771 return (res);
1772}
1773
1774/**************************************************************************
1775 *END_RUN_RAW_MBR *
1776 **************************************************************************/
1777
1778
1779
1780/**
1781 * malloc() and set sensible defaults for the mondorestore filename variables.
1782 * @param bkpinfo The backup information structure. Fields used:
1783 * - @c bkpinfo->tmpdir
1784 * - @c bkpinfo->disaster_recovery
1785 */
1786void setup_MR_global_filenames()
1787{
1788 char *temppath;
1789
1790 assert(bkpinfo != NULL);
1791
1792 malloc_string(g_biggielist_txt);
1793 malloc_string(g_filelist_full);
1794 malloc_string(g_filelist_imagedevs);
1795 malloc_string(g_imagedevs_restthese);
1796 malloc_string(g_mondo_cfg_file);
1797 malloc_string(g_mountlist_fname);
1798 malloc_string(g_mondo_home);
1799 /*
1800 malloc_string(g_tmpfs_mountpt);
1801 */
1802 malloc_string(g_isodir_device);
1803 malloc_string(g_isodir_format);
1804
1805 temppath = bkpinfo->tmpdir;
1806
1807 sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1808 sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1809 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1810// sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1811 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1812 temppath);
1813 if (bkpinfo->disaster_recovery) {
1814 sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1815 sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1816 } else {
1817 sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1818 sprintf(g_mountlist_fname, "%s/%s", temppath,
1819 MOUNTLIST_FNAME_STUB);
1820 }
1821}
1822
1823/**************************************************************************
1824 *END_SET_GLOBAL_FILENAME *
1825 **************************************************************************/
1826
1827
1828/**
1829 * Copy @p input_file (containing the result of a compare) to @p output_file,
1830 * deleting spurious "changes" along the way.
1831 * @param output_file The output file to write with spurious changes removed.
1832 * @param input_file The input file, a list of changed files created by a compare.
1833 */
1834void streamline_changes_file(char *output_file, char *input_file)
1835{
1836 FILE *fin;
1837 FILE *fout;
1838 /** malloc **/
1839 char *incoming;
1840
1841 assert_string_is_neither_NULL_nor_zerolength(output_file);
1842 assert_string_is_neither_NULL_nor_zerolength(input_file);
1843 malloc_string(incoming);
1844
1845 if (!(fin = fopen(input_file, "r"))) {
1846 log_OS_error(input_file);
1847 return;
1848 }
1849 if (!(fout = fopen(output_file, "w"))) {
1850 fatal_error("cannot open output_file");
1851 }
1852 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1853 fgets(incoming, MAX_STR_LEN - 1, fin)) {
1854 if (strncmp(incoming, "etc/adjtime", 11)
1855 && strncmp(incoming, "etc/mtab", 8)
1856 && strncmp(incoming, "tmp/", 4)
1857 && strncmp(incoming, "boot/map", 8)
1858 && !strstr(incoming, "incheckentry")
1859 && strncmp(incoming, "etc/mail/statistics", 19)
1860 && strncmp(incoming, "var/", 4))
1861 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1862 }
1863 paranoid_fclose(fout);
1864 paranoid_fclose(fin);
1865 paranoid_free(incoming);
1866}
1867
1868/**************************************************************************
1869 *END_STREAMLINE_CHANGES_FILE *
1870 **************************************************************************/
1871
1872
1873/**
1874 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1875 */
1876void twenty_seconds_til_yikes()
1877{
1878 int i;
1879 /* MALLOC * */
1880 char *tmp;
1881
1882 malloc_string(tmp);
1883 if (does_file_exist("/tmp/NOPAUSE")) {
1884 return;
1885 }
1886 open_progress_form("CAUTION",
1887 "Be advised: I am about to ERASE your hard disk(s)!",
1888 "You may press Ctrl+Alt+Del to abort safely.",
1889 "", 20);
1890 for (i = 0; i < 20; i++) {
1891 g_current_progress = i;
1892 sprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1893 update_progress_form(tmp);
1894 sleep(1);
1895 }
1896 close_progress_form();
1897 paranoid_free(tmp);
1898}
1899
1900/**************************************************************************
1901 *END_TWENTY_SECONDS_TIL_YIKES *
1902 **************************************************************************/
1903
1904
1905/**
1906 * Unmount all devices in @p p_external_copy_of_mountlist.
1907 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1908 * @return 0 for success, nonzero for failure.
1909 */
1910int unmount_all_devices(struct mountlist_itself
1911 *p_external_copy_of_mountlist)
1912{
1913 struct mountlist_itself *mountlist;
1914 int retval = 0, lino, res = 0, i;
1915 char *command;
1916 char *tmp = NULL;
1917
1918 malloc_string(command);
1919 assert(p_external_copy_of_mountlist != NULL);
1920
1921 mountlist = malloc(sizeof(struct mountlist_itself));
1922 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1923 sizeof(struct mountlist_itself));
1924 sort_mountlist_by_mountpoint(mountlist, 0);
1925
1926 run_program_and_log_output("df -m", 3);
1927 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1928 open_progress_form("Unmounting devices",
1929 "Unmounting all devices that were mounted,",
1930 "in preparation for the post-restoration reboot.",
1931 "", mountlist->entries);
1932 chdir("/");
1933 for (i = 0;
1934 i < 10
1935 &&
1936 run_program_and_log_output
1937 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1938 i++) {
1939 sleep(1);
1940 log_msg(2, "Waiting for buffer() to finish");
1941 }
1942
1943 paranoid_system("sync");
1944
1945 mr_asprintf(&tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1946 if (run_program_and_log_output(tmp, FALSE)) {
1947 log_msg(1,
1948 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1949 }
1950 paranoid_free(tmp);
1951 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1952 run_program_and_log_output("mkdir -p " MNT_RESTORING
1953 "/mnt/.boot.d", 5);
1954 }
1955
1956 /* Unmounting the local /proc and /sys first */
1957 run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1958 run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1959
1960 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1961 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1962 continue;
1963 }
1964 mr_asprintf(&tmp, "Unmounting device %s ", mountlist->el[lino].device);
1965
1966 update_progress_form(tmp);
1967
1968 if (is_this_device_mounted(mountlist->el[lino].device)) {
1969 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1970 sprintf(command, "swapoff %s", mountlist->el[lino].device);
1971 } else {
1972 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1973 sprintf(command, "umount %s/", MNT_RESTORING);
1974 log_msg(3,
1975 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1976 } else {
1977 sprintf(command, "umount " MNT_RESTORING "%s",
1978 mountlist->el[lino].mountpoint);
1979
1980 /* To support latest Ubuntu where /var is a separate FS
1981 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1982 * we need to create some dirs under the real / before unmounting it */
1983 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1984 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1985 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1986 }
1987 }
1988 }
1989 log_msg(10, "The 'umount' command is '%s'", command);
1990 res = run_program_and_log_output(command, 3);
1991 } else {
1992 mr_strcat(tmp, "...not mounted anyway :-) OK");
1993 res = 0;
1994 }
1995 g_current_progress++;
1996 if (res) {
1997 mr_strcat(tmp, "...Failed");
1998 retval++;
1999 log_to_screen(tmp);
2000 } else {
2001 log_msg(2, tmp);
2002 }
2003 paranoid_free(tmp);
2004 }
2005 close_progress_form();
2006 if (retval) {
2007 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2008 } else {
2009 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2010 }
2011 if (retval) {
2012 log_to_screen("Unable to unmount some of your partitions.");
2013 } else {
2014 log_to_screen("All partitions were unmounted OK.");
2015 }
2016 free(mountlist);
2017 paranoid_free(command);
2018 return (retval);
2019}
2020
2021/**************************************************************************
2022 *END_UNMOUNT_ALL_DEVICES *
2023 **************************************************************************/
2024
2025
2026
2027/**
2028 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2029 * to the ./tmp/ directory.
2030 * @param dev The tape device to read from.
2031 * @return 0 for success, nonzero for failure.
2032 */
2033int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2034{
2035 char *command;
2036 int res = 0;
2037
2038 malloc_string(command);
2039
2040 if (bkpinfo->use_obdr) {
2041 skip_obdr();
2042 } else {
2043 // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2044 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2045 }
2046
2047 sprintf(command,
2048 "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s",
2049 dev,
2050 bkpinfo->internal_tape_block_size,
2051 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2052 MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2053 BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2054 log_msg(2, "command = '%s'", command);
2055 res = run_program_and_log_output(command, -1);
2056 if (res != 0) {
2057 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2058 res = 0;
2059 } else {
2060 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2061 log_msg(2, "pre-2.2.4 compatible mode on");
2062 sprintf(command,
2063 "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2064 dev,
2065 bkpinfo->internal_tape_block_size,
2066 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2067 MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2068 BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
2069 log_msg(2, "command = '%s'", command);
2070 res = run_program_and_log_output(command, -1);
2071 if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2072 res = 0;
2073 }
2074 }
2075 }
2076 paranoid_free(command);
2077 return (res);
2078}
2079
2080
2081
2082/**
2083 * Get the configuration file from the floppy, tape, or CD.
2084 * @param bkpinfo The backup information structure. Fields used:
2085 * - @c bkpinfo->backup_media_type
2086 * - @c bkpinfo->media_device
2087 * - @c bkpinfo->tmpdir
2088 * @return 0 for success, nonzero for failure.
2089 */
2090int get_cfg_file_from_archive()
2091{
2092 int retval = 0;
2093
2094 /** malloc *****/
2095 char *device;
2096 char *command;
2097 char *cfg_file;
2098 char *mounted_cfgf_path;
2099 char *tmp;
2100 char *mountpt;
2101 char *ramdisk_fname;
2102 char *mountlist_file;
2103 bool extract_mountlist_stub = FALSE;
2104 bool extract_i_want_my_lvm = FALSE;
2105
2106 bool try_plan_B;
2107
2108 assert(bkpinfo != NULL);
2109 malloc_string(cfg_file);
2110 malloc_string(mounted_cfgf_path);
2111 malloc_string(mountpt);
2112 malloc_string(ramdisk_fname);
2113 malloc_string(mountlist_file);
2114 malloc_string(device);
2115 malloc_string(command);
2116 malloc_string(tmp);
2117 log_msg(2, "gcffa --- starting");
2118 log_to_screen("I'm thinking...");
2119 sprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2120 device[0] = '\0';
2121 chdir(bkpinfo->tmpdir);
2122 strcpy(cfg_file, MONDO_CFG_FILE_STUB);
2123 unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent
2124 unlink(FILELIST_FULL_STUB);
2125 unlink(BIGGIELIST_TXT_STUB);
2126 sprintf(command, "mkdir -p %s", mountpt);
2127 run_program_and_log_output(command, FALSE);
2128
2129 sprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2130 sprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2131 // make_hole_for_file( cfg_file );
2132 // make_hole_for_file( mountlist_file);
2133 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2134
2135 if (!does_file_exist(cfg_file)) {
2136 log_msg(2, "gcffa --- we don't have cfg file yet.");
2137 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2138 try_plan_B = TRUE;
2139 } else {
2140 log_msg(2, "gcffa --- calling mount_media now :)");
2141 if (!mount_media()) {
2142 log_msg(2,
2143 "gcffa --- managed to mount CD; so, no need for Plan B");
2144 try_plan_B = FALSE;
2145 } else {
2146 try_plan_B = TRUE;
2147 }
2148 if (what_number_cd_is_this() > 1) {
2149 insist_on_this_cd_number((g_current_media_number = 1));
2150 }
2151 }
2152 if (try_plan_B) {
2153 log_msg(2, "gcffa --- OK, switching to Plan B");
2154 chdir(bkpinfo->tmpdir);
2155 run_program_and_log_output("mkdir -p tmp", FALSE);
2156
2157 if (strlen(bkpinfo->media_device) == 0) {
2158 strcpy(bkpinfo->media_device, "/dev/st0");
2159 log_msg(2, "media_device is blank; assuming %s");
2160 }
2161 strcpy(tmp, bkpinfo->media_device);
2162 if (extract_cfg_file_and_mountlist_from_tape_dev
2163 (bkpinfo->media_device)) {
2164 strcpy(bkpinfo->media_device, "/dev/st0");
2165 if (extract_cfg_file_and_mountlist_from_tape_dev
2166 (bkpinfo->media_device)) {
2167 strcpy(bkpinfo->media_device, "/dev/osst0");
2168 if (extract_cfg_file_and_mountlist_from_tape_dev
2169 (bkpinfo->media_device)) {
2170 strcpy(bkpinfo->media_device, "/dev/ht0");
2171 if (extract_cfg_file_and_mountlist_from_tape_dev
2172 (bkpinfo->media_device)) {
2173 log_msg(3,
2174 "I tried lots of devices but none worked.");
2175 strcpy(bkpinfo->media_device, tmp);
2176 }
2177 }
2178 }
2179 }
2180
2181 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2182 log_to_screen("Cannot find config info on media");
2183 return (1);
2184 }
2185 } else {
2186 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2187 extract_mountlist_stub = FALSE;
2188 } else {
2189 extract_mountlist_stub = TRUE;
2190 }
2191 if (does_file_exist("/"IWANTMYLVM_STUB)) {
2192 extract_i_want_my_lvm = FALSE;
2193 } else {
2194 extract_i_want_my_lvm = TRUE;
2195 }
2196
2197 log_msg(2,
2198 "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2199 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
2200 run_program_and_log_output(command, TRUE);
2201 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2202 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2203 log_msg(2, "pre-2.2.4 compatible mode on");
2204 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
2205 run_program_and_log_output(command, TRUE);
2206 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2207 fatal_error
2208 ("Please reinsert the disk/CD and try again.");
2209 }
2210 }
2211 }
2212 }
2213 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2214 log_msg(1, "gcffa --- great! We've got the config file");
2215 sprintf(tmp, "%s/%s",
2216 call_program_and_get_last_line_of_output("pwd"),
2217 MONDO_CFG_FILE_STUB);
2218 sprintf(command, "cp -f %s %s", tmp, cfg_file);
2219 log_it("%s",command);
2220 if (strcmp(tmp, cfg_file)
2221 && run_program_and_log_output(command, 1)) {
2222 log_msg(1,
2223 "... but an error occurred when I tried to move it to %s",
2224 cfg_file);
2225 } else {
2226 log_msg(1, "... and I moved it successfully to %s", cfg_file);
2227 }
2228 sprintf(command, "cp -f %s/%s %s",
2229 call_program_and_get_last_line_of_output("pwd"),
2230 MOUNTLIST_FNAME_STUB, mountlist_file);
2231 log_it("%s",command);
2232 if (extract_mountlist_stub) {
2233 if (strcmp(tmp, cfg_file)
2234 && run_program_and_log_output(command, 1)) {
2235 log_msg(1, "Failed to get mountlist");
2236 } else {
2237 log_msg(1, "Got mountlist too");
2238 sprintf(command, "cp -f %s %s", mountlist_file,
2239 g_mountlist_fname);
2240 if (run_program_and_log_output(command, 1)) {
2241 log_msg(1, "Failed to copy mountlist to /tmp");
2242 } else {
2243 log_msg(1, "Copied mountlist to /tmp as well OK");
2244 sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2245 run_program_and_log_output(command, 1);
2246 }
2247 }
2248 }
2249 }
2250 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2251 if (!does_file_exist(cfg_file)) {
2252 log_it("%s",cfg_file);
2253 log_msg(1, "%s not found", cfg_file);
2254 log_to_screen
2255 ("Oh dear. Unable to recover configuration file from boot disk");
2256 return (1);
2257 }
2258
2259 log_to_screen("Recovered mondo-restore.cfg");
2260 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2261 log_to_screen("...but not mountlist.txt - a pity, really...");
2262 }
2263 else {
2264 /* Is this code really useful ??? */
2265 if (extract_mountlist_stub) {
2266 sprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2267 bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2268 run_program_and_log_output(command, FALSE);
2269 }
2270 }
2271
2272 sprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2273 run_program_and_log_output(command, FALSE);
2274 if (extract_mountlist_stub) {
2275 sprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2276 run_program_and_log_output(command, FALSE);
2277 }
2278 sprintf(command, "cp -f etc/raidtab /etc/");
2279 run_program_and_log_output(command, FALSE);
2280 if (extract_i_want_my_lvm) {
2281 sprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2282 run_program_and_log_output(command, FALSE);
2283 }
2284 g_backup_media_type = bkpinfo->backup_media_type;
2285 paranoid_free(device);
2286 paranoid_free(command);
2287 paranoid_free(tmp);
2288 paranoid_free(cfg_file);
2289 paranoid_free(mounted_cfgf_path);
2290 paranoid_free(mountpt);
2291 paranoid_free(ramdisk_fname);
2292 paranoid_free(mountlist_file);
2293 return (retval);
2294}
2295
2296/**************************************************************************
2297 *END_GET_CFG_FILE_FROM_ARCHIVE *
2298 **************************************************************************/
2299
2300/* @} - end restoreUtilityGroup */
2301
2302
2303/***************************************************************************
2304 * F@ *
2305 * () -- Hugo Rabson *
2306 * *
2307 * Purpose: *
2308 * *
2309 * Called by: *
2310 * Params: - - *
2311 * Returns: 0=success; nonzero=failure *
2312 ***************************************************************************/
2313
2314
2315
2316void wait_until_software_raids_are_prepped(char *mdstat_file,
2317 int wait_for_percentage)
2318{
2319 struct raidlist_itself *raidlist;
2320 int unfinished_mdstat_devices = 9999, i;
2321 char *screen_message;
2322
2323 malloc_string(screen_message);
2324 raidlist = malloc(sizeof(struct raidlist_itself));
2325
2326 assert(wait_for_percentage <= 100);
2327 log_it("wait_until_software_raids_are_prepped");
2328 while (unfinished_mdstat_devices > 0) {
2329 // FIXME: Prefix '/dev/' should really be dynamic!
2330 if (parse_mdstat(raidlist, "/dev/")) {
2331 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2332 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2333 return;
2334 }
2335 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2336 if (raidlist->el[i].progress < wait_for_percentage) {
2337 unfinished_mdstat_devices++;
2338 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2339 {
2340 continue;
2341 }
2342 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2343 sprintf(screen_message, "Sync'ing %s",
2344 raidlist->el[i].raid_device);
2345 open_evalcall_form(screen_message);
2346 while (raidlist->el[i].progress < wait_for_percentage) {
2347 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2348 update_evalcall_form(raidlist->el[i].progress);
2349 sleep(2);
2350 // FIXME: Prefix '/dev/' should really be dynamic!
2351 if (parse_mdstat(raidlist, "/dev/")) {
2352 break;
2353 }
2354 }
2355 close_evalcall_form();
2356 }
2357 }
2358 }
2359 paranoid_free(screen_message);
2360 paranoid_free(raidlist);
2361}
2362
2363
Note: See TracBrowser for help on using the repository browser.