source: MondoRescue/branches/stable/mondo/src/mondorestore/mondo-rstr-tools.c

Last change on this file was 1977, checked in by Bruno Cornec, 16 years ago

svn merge -r 1938:1976 $SVN_M/branches/2.2.6

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