source: MondoRescue/branches/2.2.7/mondo/src/mondorestore/mondo-rstr-tools.c@ 2029

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