source: MondoRescue/branches/2.2.8/mondo/src/mondorestore/mondo-rstr-tools.c@ 2049

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