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

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