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

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

r3334@localhost: bruno | 2009-08-08 12:17:37 +0200

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