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

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