source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondo-rstr-tools.c@ 2280

Last change on this file since 2280 was 2280, checked in by Bruno Cornec, 15 years ago

r3275@localhost: bruno | 2009-07-19 23:23:18 +0200

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