source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondo-rstr-tools.c@ 3193

Last change on this file since 3193 was 3193, checked in by Bruno Cornec, 11 years ago
  • Finish with backports from 3.1 for now. Still some work to do, but we will now make that version compile and work again and serve as a base

so the gettext patch can be added

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