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

Last change on this file since 2623 was 2623, checked in by Bruno Cornec, 14 years ago

r3783@localhost: bruno | 2010-04-11 11:57:27 +0200

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