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

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