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

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

r3327@localhost: bruno | 2009-08-04 00:17:46 +0200
popup_and_get_string and build_partition_name now return an allocated string

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