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

Last change on this file since 2324 was 2324, checked in by Bruno Cornec, 15 years ago

r3335@localhost: bruno | 2009-08-08 23:04:12 +0200

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