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

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

r3333@localhost: bruno | 2009-08-08 01:58:31 +0200

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