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

Last change on this file since 3205 was 3205, checked in by Bruno Cornec, 10 years ago
  • Fix mondoarchive which now works in text mode. GUI mode still not working and crashing on first update for backup. Needs more

investigation in newt-specific.c

  • Property svn:keywords set to Id
File size: 73.8 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 3205 2013-12-06 14:40:47Z 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 *tmp1 = NULL;
642char *envtmp1 = NULL;
643char *envtmp2 = NULL;
644char *command = NULL;
645char iso_mnt[MAX_STR_LEN];
646char iso_path[MAX_STR_LEN];
647char *old_isodir = NULL;
648char *cfg_file = NULL;
649t_bkptype media_specified_by_user;
650
651// assert_string_is_neither_NULL_nor_zerolength(cfg_file);
652assert(bkpinfo != NULL);
653assert(cfgf != NULL);
654log_it("Entering read_cfg_file_into_bkpinfo");
655
656if (!cfgf) {
657 strcpy(cfg_file, g_mondo_cfg_file);
658} else {
659 strcpy(cfg_file, cfgf);
660}
661
662media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
663
664if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
665 if (!strcmp(value, "cdstream")) {
666 bkpinfo->backup_media_type = cdstream;
667 } else if (!strcmp(value, "cdr")) {
668 bkpinfo->backup_media_type = cdr;
669 } else if (!strcmp(value, "cdrw")) {
670 bkpinfo->backup_media_type = cdrw;
671 } else if (!strcmp(value, "dvd")) {
672 bkpinfo->backup_media_type = dvd;
673 } else if (!strcmp(value, "usb")) {
674 bkpinfo->backup_media_type = usb;
675 bkpinfo->please_dont_eject = TRUE;
676 } else if (!strcmp(value, "iso")) {
677 bkpinfo->backup_media_type = iso;
678 if (am_I_in_disaster_recovery_mode()) {
679 /* Check to see if CD is already mounted before mounting it... */
680 if (!is_this_device_mounted("/dev/cdrom")) {
681 log_msg(2, "NB: CDROM device not mounted, mounting...");
682 run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
683 }
684 if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
685 bkpinfo->backup_media_type = cdr;
686 run_program_and_log_output("umount -d "MNT_CDROM, 1);
687 log_it("Re-jigging configuration AGAIN. CD-R, not ISO.");
688 }
689 }
690 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
691 strcpy(bkpinfo->prefix,value);
692 } else {
693 strcpy(bkpinfo->prefix,STD_PREFIX);
694 }
695 log_it("Setting Prefix to %s", bkpinfo->prefix);
696 } else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
697 /* Stay compatible with previous versions by allowing nfs as an entry here */
698 bkpinfo->backup_media_type = netfs;
699 bkpinfo->please_dont_eject = TRUE;
700 if (read_cfg_var(cfg_file, "netfs-proto", value) == 0) {
701 mr_asprintf(bkpinfo->netfs_proto,"%s", value);
702 } else {
703 /* For compatibility, force protocol in old nfs case to be transparent */
704 mr_asprintf(bkpinfo->netfs_proto, "nfs");
705 }
706 if (read_cfg_var(cfg_file, "netfs-server-user", value) == 0) {
707 mr_asprintf(bkpinfo->netfs_user,"%s", value);
708 }
709 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
710 strcpy(bkpinfo->prefix,value);
711 } else {
712 strcpy(bkpinfo->prefix,STD_PREFIX);
713 }
714 if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "pxe")) {
715 /* We need to override prefix value in PXE mode as it's
716 * already done in start-netfs */
717 envtmp1 = getenv("imgname");
718 if (envtmp1 == NULL) {
719 fatal_error("no imgname variable in environment");
720 }
721 strcpy(bkpinfo->prefix,envtmp1);
722 }
723 } else if (!strcmp(value, "tape")) {
724 bkpinfo->backup_media_type = tape;
725 } else if (!strcmp(value, "udev")) {
726 bkpinfo->backup_media_type = udev;
727 } else {
728 fatal_error("UNKNOWN bkp-media-type");
729 }
730} else {
731 fatal_error("backup-media-type not specified!");
732}
733
734if (bkpinfo->disaster_recovery) {
735 if (bkpinfo->backup_media_type == cdstream) {
736 sprintf(bkpinfo->media_device, "/dev/cdrom");
737 bkpinfo->media_size = 650; /* good guess */
738 } else if (bkpinfo->backup_media_type == usb) {
739 envtmp1 = getenv("MRUSBDEV");
740 if (envtmp1 == NULL) {
741 if (read_cfg_var(cfg_file, "usb-dev", value)) {
742 fatal_error("Cannot get USB device name from cfg file");
743 }
744 } else {
745 strcpy(value,envtmp1);
746 }
747 sprintf(bkpinfo->media_device, "%s1", value);
748 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
749 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
750 if (read_cfg_var(cfg_file, "media-dev", value)) {
751 fatal_error("Cannot get tape device name from cfg file");
752 }
753 strcpy(bkpinfo->media_device, value);
754 read_cfg_var(cfg_file, "media-size", value);
755 bkpinfo->media_size = atol(value);
756 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
757 } else {
758 strcpy(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
759 bkpinfo->media_size = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
760 log_msg(2, "Backup medium is similar to CD-R[W]");
761 }
762} else {
763 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
764}
765
766read_cfg_var(cfg_file, "use-star", value);
767if (strstr(value, "yes")) {
768 bkpinfo->use_star = TRUE;
769 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
770}
771
772read_cfg_var(cfg_file, "obdr", value);
773if (strstr(value, "TRUE")) {
774 bkpinfo->use_obdr = TRUE;
775 log_msg(1, "OBDR mode activated");
776}
777
778read_cfg_var(cfg_file, "acl", value);
779if (strstr(value, "TRUE")) {
780 mr_asprintf(g_getfacl,"setfacl");
781 log_msg(1, "We will restore ACLs");
782 if (! find_home_of_exe("setfacl")) {
783 log_msg(1, "Unable to restore ACLs as no setfacl found");
784 }
785}
786read_cfg_var(cfg_file, "xattr", value);
787if (strstr(value, "TRUE")) {
788 mr_asprintf(g_getfattr,"setfattr");
789 log_msg(1, "We will restore XATTRs");
790 if (! find_home_of_exe("setfattr")) {
791 log_msg(1, "Unable to restore XATTRs as no setfattr found");
792 }
793}
794
795if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
796 bkpinfo->internal_tape_block_size = atol(value);
797} else {
798 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
799}
800log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
801
802read_cfg_var(cfg_file, "use-lzma", value);
803if (strstr(value, "yes")) {
804 bkpinfo->use_lzma = TRUE;
805 bkpinfo->use_lzo = FALSE;
806 bkpinfo->use_gzip = FALSE;
807 strcpy(bkpinfo->zip_exe, "lzma");
808 strcpy(bkpinfo->zip_suffix, "lzma");
809}
810
811read_cfg_var(cfg_file, "use-lzo", value);
812if (strstr(value, "yes")) {
813 bkpinfo->use_lzma = FALSE;
814 bkpinfo->use_lzo = TRUE;
815 bkpinfo->use_gzip = FALSE;
816 strcpy(bkpinfo->zip_exe, "lzop");
817 strcpy(bkpinfo->zip_suffix, "lzo");
818}
819
820read_cfg_var(cfg_file, "use-gzip", value);
821if (strstr(value, "yes")) {
822 bkpinfo->use_lzma = FALSE;
823 bkpinfo->use_lzo = FALSE;
824 bkpinfo->use_gzip = TRUE;
825 strcpy(bkpinfo->zip_exe, "gzip");
826 strcpy(bkpinfo->zip_suffix, "gz");
827}
828
829read_cfg_var(cfg_file, "use-comp", value);
830if (strstr(value, "yes")) {
831 bkpinfo->use_lzma = FALSE;
832 bkpinfo->use_lzo = FALSE;
833 bkpinfo->use_gzip = FALSE;
834 strcpy(bkpinfo->zip_exe, "bzip2");
835 strcpy(bkpinfo->zip_suffix, "bz2");
836}
837
838value[0] = '\0';
839read_cfg_var(cfg_file, "differential", value);
840if (!strcmp(value, "yes") || !strcmp(value, "1")) {
841 bkpinfo->differential = TRUE;
842}
843log_msg(2, "differential var = '%s'", value);
844if (bkpinfo->differential) {
845 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
846} else {
847 log_msg(2, "This is a regular (full) backup");
848}
849
850read_cfg_var(g_mondo_cfg_file, "please-dont-eject", value);
851if (value[0] || strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "donteject")) {
852 bkpinfo->please_dont_eject = TRUE;
853 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
854}
855
856if (bkpinfo->backup_media_type == netfs) {
857 if (!cfgf) {
858 if (bkpinfo->netfs_mount) {
859 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
860 }
861 if (bkpinfo->netfs_remote_dir) {
862 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
863 }
864 log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
865 } else {
866 read_cfg_var(g_mondo_cfg_file, "netfs-server-mount", value);
867 mr_free(bkpinfo->netfs_mount);
868 mr_asprintf(bkpinfo->netfs_mount, "%s", value);
869
870 read_cfg_var(g_mondo_cfg_file, "netfs-server-path", value);
871 mr_free(bkpinfo->netfs_remote_dir);
872 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", value);
873
874 if (bkpinfo->netfs_mount != NULL) {
875 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
876 }
877 if (bkpinfo->netfs_remote_dir != NULL) {
878 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
879 }
880 if (bkpinfo->netfs_proto != NULL) {
881 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
882 }
883 if (bkpinfo->netfs_user != NULL) {
884 log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
885 }
886 }
887 if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "pxe")) {
888 /* We need to override values in PXE mode as it's
889 * already done in start-netfs */
890 envtmp1 = getenv("netfsmount");
891 if (envtmp1 == NULL) {
892 fatal_error("no netfsmount variable in environment");
893 }
894 envtmp2 = getenv("dirimg");
895 if (envtmp2 == NULL) {
896 fatal_error("no dirimg variable in environment");
897 }
898 mr_free(bkpinfo->netfs_mount);
899 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
900
901 mr_free(bkpinfo->netfs_remote_dir);
902 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
903 }
904} else if (bkpinfo->backup_media_type == iso) {
905 /* Patch by Conor Daly 23-june-2004
906 * to correctly mount iso-dev and set a sensible
907 * isodir in disaster recovery mode
908 */
909 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
910 read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
911 read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
912 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
913 if (!bkpinfo->isodir[0]) {
914 strcpy(bkpinfo->isodir, old_isodir);
915 }
916 if ((!bkpinfo->disaster_recovery) || (g_isodir_device[0] != '\0')) {
917 if (strcmp(old_isodir, bkpinfo->isodir)) {
918 log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
919 strcpy(bkpinfo->isodir, old_isodir);
920 }
921 }
922 if (g_isodir_device[0] == '\0') {
923 /* We don't want to loose our conf made earlier in iso_fiddly_bits
924 * so go here only if job not done already */
925 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
926 }
927
928 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
929
930 if (bkpinfo->disaster_recovery) {
931 if (is_this_device_mounted(g_isodir_device)) {
932 log_msg(2, "NB: isodir is already mounted");
933 /* Find out where it's mounted */
934 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
935 log_it("command = %s", command);
936 log_it("res of it = %s", call_program_and_get_last_line_of_output(command));
937 sprintf(iso_mnt, "%s", call_program_and_get_last_line_of_output(command));
938 mr_free(command);
939 } else {
940 sprintf(iso_mnt, "/tmp/isodir");
941 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
942 run_program_and_log_output(tmp1, 5);
943 mr_free(tmp1);
944
945 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
946 if (run_program_and_log_output(tmp1, 3)) {
947 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
948 bkpinfo->backup_media_type = cdr;
949 strcpy(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
950 bkpinfo->isodir[0] = iso_mnt[0] = iso_path[0] = '\0';
951 if (mount_media()) {
952 mr_free(tmp1);
953 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
954 } else {
955 log_msg(1, "You backed up to disk, then burned some CDs.");
956 }
957 }
958 mr_free(tmp1);
959 }
960 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
961 /* except when already done in iso_fiddly_bits */
962 if ((bkpinfo->backup_media_type == iso) && (g_isodir_device[0] == '\0')) {
963 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
964 }
965 }
966}
967
968if (media_specified_by_user != none) {
969 if (g_restoring_live_from_cd) {
970 if (bkpinfo->backup_media_type != media_specified_by_user) {
971 log_msg(2, "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
972 interactively_obtain_media_parameters_from_user(FALSE);
973 media_specified_by_user = bkpinfo->backup_media_type;
974 get_cfg_file_from_archive();
975 }
976 }
977 bkpinfo->backup_media_type = media_specified_by_user;
978}
979g_backup_media_type = bkpinfo->backup_media_type;
980return (0);
981
982}
983
984/**************************************************************************
985*END_READ_CFG_FILE_INTO_BKPINFO *
986**************************************************************************/
987
988
989
990
991/**
992 * Allow the user to edit the filelist and biggielist.
993 * The filelist is unlinked after it is read.
994 * @param bkpinfo The backup information structure. Fields used:
995 * - @c bkpinfo->backup_media_type
996 * - @c bkpinfo->isodir
997 * - @c bkpinfo->media_device
998 * - @c bkpinfo->tmpdir
999 * @return The filelist structure containing the information read from disk.
1000 */
1001struct
1002s_node *process_filelist_and_biggielist()
1003{
1004struct s_node *filelist;
1005
1006char *command = NULL;
1007char *tmp;
1008char *q;
1009int res = 0;
1010pid_t pid;
1011bool extract_mountlist_stub = FALSE;
1012
1013assert(bkpinfo != NULL);
1014malloc_string(tmp);
1015
1016/* If those files already exist, do not overwrite them later on */
1017if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
1018 extract_mountlist_stub = FALSE;
1019} else {
1020 extract_mountlist_stub = TRUE;
1021}
1022
1023if (does_file_exist(g_filelist_full)
1024&& does_file_exist(g_biggielist_txt)) {
1025 log_msg(1, "%s exists", g_filelist_full);
1026 log_msg(1, "%s exists", g_biggielist_txt);
1027 log_msg(2,
1028 "Filelist and biggielist already recovered from media. Yay!");
1029} else {
1030 if (getcwd(tmp, MAX_STR_LEN) == NULL) {
1031 // FIXME
1032 }
1033 if (chdir(bkpinfo->tmpdir)) {
1034 // FIXME
1035 }
1036 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1037 log_to_screen("Extracting filelist and biggielist from media...");
1038 unlink("/tmp/filelist.full");
1039 unlink(FILELIST_FULL_STUB);
1040 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1041 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);
1042 log_msg(1, "tarcommand = %s", command);
1043 run_program_and_log_output(command, 1);
1044 mr_free(command);
1045
1046 if (!does_file_exist(FILELIST_FULL_STUB)) {
1047 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1048 log_msg(2, "pre-2.2.4 compatible mode on");
1049 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);
1050 log_msg(1, "tarcommand = %s", command);
1051 run_program_and_log_output(command, 1);
1052 mr_free(command);
1053 }
1054 } else {
1055 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1056 insist_on_this_cd_number(1);
1057 log_msg(2, "Back from iotcn");
1058 run_program_and_log_output("mount", 1);
1059 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);
1060
1061 log_msg(1, "tarcommand = %s", command);
1062 run_program_and_log_output(command, 1);
1063 mr_free(command);
1064
1065 if (!does_file_exist(FILELIST_FULL_STUB)) {
1066 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
1067 log_msg(2, "pre-2.2.4 compatible mode on");
1068 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);
1069
1070 log_msg(1, "tarcommand = %s", command);
1071 run_program_and_log_output(command, 1);
1072 mr_free(command);
1073 }
1074 if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1075 fatal_error("all.tar.gz did not include " BIGGIELIST_TXT_STUB);
1076 }
1077 if (!does_file_exist(FILELIST_FULL_STUB)) {
1078 fatal_error("all.tar.gz did not include " FILELIST_FULL_STUB);
1079 }
1080 }
1081 mr_asprintf(command, "cp -f %s %s", MONDO_CFG_FILE_STUB, g_mondo_cfg_file);
1082 run_program_and_log_output(command, FALSE);
1083 mr_free(command);
1084
1085 mr_asprintf(command, "cp -f %s/%s %s", bkpinfo->tmpdir, BIGGIELIST_TXT_STUB, g_biggielist_txt);
1086 log_msg(1, "command = %s", command);
1087 paranoid_system(command);
1088 mr_free(command);
1089
1090 mr_asprintf(command, "ln -sf %s/%s %s", bkpinfo->tmpdir, FILELIST_FULL_STUB, g_filelist_full);
1091 log_msg(1, "command = %s", command);
1092 paranoid_system(command);
1093 mr_free(command);
1094 }
1095
1096 if (am_I_in_disaster_recovery_mode()
1097 &&
1098 /* If it was there, do not overwrite it */
1099 (extract_mountlist_stub)
1100 &&
1101 ask_me_yes_or_no("Do you want to retrieve the mountlist as well?"))
1102 {
1103 mr_asprintf(command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir);
1104 paranoid_system(command);
1105 mr_free(command);
1106 }
1107
1108 if (chdir(tmp)) {
1109 // FIXME
1110 }
1111
1112 if (!does_file_exist(g_biggielist_txt)) {
1113 log_msg(1, "Warning - %s not found", g_biggielist_txt);
1114 }
1115 if (!does_file_exist(g_filelist_full)) {
1116 log_msg(1, "Warning - %s does not exist", g_filelist_full);
1117 }
1118
1119 log_msg(2, "Forking");
1120 pid = fork();
1121 switch (pid) {
1122 case -1:
1123 fatal_error("Forking error");
1124 break;
1125
1126 case 0:
1127 log_to_screen("Pre-processing filelist");
1128 if (!does_file_exist(g_biggielist_txt)) {
1129 mr_asprintf(command, "echo -n > %s", g_biggielist_txt);
1130 paranoid_system(command);
1131 mr_free(command);
1132 }
1133 mr_asprintf(command, "grep -E '^/dev/.*' %s > %s", g_biggielist_txt, g_filelist_imagedevs);
1134 paranoid_system(command);
1135 mr_free(command);
1136 exit(0);
1137 break;
1138
1139 default:
1140 open_evalcall_form("Pre-processing filelist");
1141 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1142 usleep(100000);
1143 update_evalcall_form(0);
1144 }
1145 }
1146 close_evalcall_form();
1147
1148 log_msg(3, "loading filelist");
1149 filelist = load_filelist(g_filelist_full);
1150 log_msg(3, "deleting original filelist");
1151 unlink(g_filelist_full);
1152 if (g_text_mode) {
1153 q = NULL;
1154 while (q == NULL) {
1155 printf("Restore which directory? --> ");
1156 mr_getline(q, stdin);
1157 }
1158 toggle_path_selection(filelist, q, TRUE);
1159 if (strlen(q) == 0) {
1160 res = 1;
1161 } else {
1162 res = 0;
1163 }
1164 mr_free(q);
1165 } else {
1166 res = edit_filelist(filelist);
1167 }
1168 if (res) {
1169 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1170 free_filelist(filelist);
1171 return (NULL);
1172 }
1173 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1174 close_evalcall_form();
1175
1176 // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1177 // file. The filelist.full file already contains the filename of EVERY
1178 // file backed up - regular and biggie files.
1179
1180 // However, we do want to make sure the imagedevs selected by the user
1181 // are flagged for restoring.
1182 if (length_of_file(g_imagedevs_restthese) > 2) {
1183 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1184 TRUE);
1185 }
1186
1187 paranoid_free(tmp);
1188 return (filelist);
1189}
1190
1191/**************************************************************************
1192 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1193 **************************************************************************/
1194
1195
1196
1197
1198/**
1199 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1200 * The backup filename is the filename of the original with ".pristine" added.
1201 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1202 * @param filename The filename (absolute path) within @p path_root.
1203 * @return 0 for success, nonzero for failure.
1204 */
1205int backup_crucial_file(char *path_root, char *filename)
1206{
1207 char *tmp = NULL;
1208 char *command = NULL;
1209 int res;
1210
1211 assert(path_root != NULL);
1212 assert_string_is_neither_NULL_nor_zerolength(filename);
1213
1214 mr_asprintf(tmp, "%s/%s", path_root, filename);
1215 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1216 mr_free(tmp);
1217
1218 res = run_program_and_log_output(command, 5);
1219 mr_free(command);
1220 return (res);
1221}
1222
1223void offer_to_make_initrd() {
1224
1225if (bkpinfo->restore_mode != nuke) {
1226 if (ask_me_yes_or_no
1227 ("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 ?")) {
1228 log_msg(1,"Launching shell for manual initrd recreation");
1229 if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1230 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");
1231 } else {
1232 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.");
1233 }
1234 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1235 if (!g_text_mode) {
1236 newtSuspend();
1237 }
1238 paranoid_system("chroot " MNT_RESTORING);
1239 if (!g_text_mode) {
1240 newtResume();
1241 }
1242 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1243 } else {
1244 return;
1245 }
1246} else {
1247 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1248 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1249}
1250}
1251
1252
1253/**
1254 * Install the user's boot loader in the MBR.
1255 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1256 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1257 * @return 0 for success, nonzero for failure.
1258 */
1259int run_boot_loader(bool offer_to_hack_scripts)
1260{
1261 int res;
1262 int retval = 0;
1263
1264 /** malloc *******/
1265 char *device = NULL;
1266 char *name = NULL;
1267 char *cmd = NULL;
1268
1269 malloc_string(device);
1270 malloc_string(name);
1271
1272 /* In order to have a working bootloader, we need to have all devices
1273 * ready in the chroot. If they are not there (udev) then copy them from
1274 * the current /dev location
1275 */
1276 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1277 run_program_and_log_output(cmd, 3);
1278 paranoid_free(cmd);
1279
1280 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1281 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1282 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1283 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
1284 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1285 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1286 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1287 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
1288 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1289 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1290 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1291 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1292 sync();
1293
1294 offer_to_make_initrd();
1295 if (!strcmp(name, "LILO")) {
1296 res = run_lilo(offer_to_hack_scripts);
1297 } else if (!strcmp(name, "ELILO")) {
1298 res = run_elilo(offer_to_hack_scripts);
1299 } else if (!strcmp(name, "GRUB")) {
1300 res = run_grub(offer_to_hack_scripts, device);
1301 } else if (!strcmp(name, "RAW")) {
1302 res = run_raw_mbr(offer_to_hack_scripts, device);
1303 }
1304#ifdef __FreeBSD__
1305 else if (!strcmp(name, "BOOT0")) {
1306 mr_asprintf(tmp, "boot0cfg -B %s", device);
1307 res = run_program_and_log_output(tmp, FALSE);
1308 paranoid_free(tmp);
1309 } else {
1310 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1311 if (!system(tmp)) {
1312 mr_free(tmp);
1313 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1314 res = run_program_and_log_output(tmp, 3);
1315 } else {
1316 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1317 }
1318 mr_free(tmp);
1319 }
1320#else
1321 else {
1322 log_to_screen
1323 ("Unable to determine type of boot loader. Defaulting to LILO.");
1324 res = run_lilo(offer_to_hack_scripts);
1325 }
1326#endif
1327 retval += res;
1328 if (res) {
1329 log_to_screen("Your boot loader returned an error");
1330 } else {
1331 log_to_screen("Your boot loader ran OK");
1332 }
1333 paranoid_free(device);
1334 paranoid_free(name);
1335 return (retval);
1336}
1337
1338/**************************************************************************
1339 *END_ RUN_BOOT_LOADER *
1340 **************************************************************************/
1341
1342
1343
1344/**
1345 * Attempt to find the user's editor.
1346 * @return The editor found ("vi" if none could be found).
1347 * @note The returned string points to static storage that will be overwritten with each call.
1348 */
1349char *find_my_editor(void) {
1350
1351 static char output[MAX_STR_LEN];
1352 if (find_home_of_exe("pico")) {
1353 strcpy(output, "pico");
1354 } else if (find_home_of_exe("nano")) {
1355 strcpy(output, "nano");
1356 } else if (find_home_of_exe("e3em")) {
1357 strcpy(output, "e3em");
1358 } else if (find_home_of_exe("e3vi")) {
1359 strcpy(output, "e3vi");
1360 } else {
1361 strcpy(output, "vi");
1362 }
1363 if (!find_home_of_exe(output)) {
1364 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1365 }
1366 return (output);
1367}
1368
1369
1370/**
1371 * Install GRUB on @p bd.
1372 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1373 * @param bd The boot device where GRUB is installed.
1374 * @return 0 for success, nonzero for failure.
1375 */
1376int run_grub(bool offer_to_run_stabgrub, char *bd)
1377{
1378 /** malloc **/
1379 char *command = NULL;
1380 char *boot_device = NULL;
1381 char *tmp = NULL;
1382 char *editor = NULL;
1383
1384 bool done;
1385 int res = 0; /* FALSE */
1386 bool mntlistchg = FALSE;
1387 FILE *fin = NULL;
1388
1389 malloc_string(boot_device);
1390
1391 assert_string_is_neither_NULL_nor_zerolength(bd);
1392 strcpy(boot_device, bd);
1393
1394 if (offer_to_run_stabgrub
1395 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1396 /* interactive mode */
1397 mvaddstr_and_log_it(g_currentY,
1398 0,
1399 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1400 /* Did we changed the mountlist ? If yes, then force editing conf files */
1401 if ((fin = fopen(MONDO_MNTLISTCHG, "r")) != NULL) {
1402 mntlistchg = TRUE;
1403 }
1404 for (done = FALSE; !done;) {
1405 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
1406 /* Only try to adapt grub here first if the mountlist wasn't changed before */
1407 if (! mntlistchg) {
1408 mr_asprintf(command, "stabgrub-me %s", boot_device);
1409 res = run_program_and_log_output(command, 1);
1410 mr_free(command);
1411 }
1412
1413 if ((res) || (mntlistchg)) {
1414 if (res) {
1415 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");
1416 } else {
1417 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");
1418 }
1419 if (!g_text_mode) {
1420 newtSuspend();
1421 }
1422 mr_asprintf(editor, "%s", find_my_editor());
1423 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1424 paranoid_system(tmp);
1425 mr_free(tmp);
1426
1427 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1428 paranoid_system(tmp);
1429 mr_free(tmp);
1430
1431 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1432 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1433 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1434 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1435 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1436 mr_asprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1437 }
1438 paranoid_system(tmp);
1439 mr_free(tmp);
1440
1441 if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1442 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1443 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1444 mr_asprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1445 }
1446 paranoid_system(tmp);
1447 mr_free(tmp);
1448 mr_free(editor);
1449
1450 if (!g_text_mode) {
1451 newtResume();
1452 }
1453 mr_asprintf(command, "stabgrub-me %s", boot_device);
1454 res = run_program_and_log_output(command, 1);
1455 mr_free(command);
1456
1457 if (res) {
1458 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.");
1459 newtSuspend();
1460 paranoid_system("chroot " MNT_RESTORING);
1461 newtResume();
1462 popup_and_OK("Thank you.");
1463 } else {
1464 popup_and_OK("GRUB is now installed correctly");
1465 done = TRUE;
1466 }
1467 } else {
1468 done = TRUE;
1469 }
1470 }
1471 } else {
1472 /* nuke mode */
1473 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1474 log_msg(1, "Yay! grub-MR found...");
1475 mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1476 log_msg(1, "command = %s", command);
1477 } else {
1478 mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
1479 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1480 }
1481 mvaddstr_and_log_it(g_currentY, 0, "Running GRUB... ");
1482 log_it("%s",command);
1483 res = run_program_and_log_output(command, 1);
1484 mr_free(command);
1485
1486 if (res) {
1487 popup_and_OK
1488 ("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.");
1489 newtSuspend();
1490 paranoid_system("chroot " MNT_RESTORING);
1491 newtResume();
1492 popup_and_OK("Thank you.");
1493 }
1494 }
1495 if (res) {
1496 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1497 log_to_screen
1498 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1499 log_msg(1, "Type:-");
1500 log_msg(1, " mount-me");
1501 log_msg(1, " chroot " MNT_RESTORING);
1502 log_msg(1, " mount /boot");
1503 log_msg(1, " grub-install '(hd0)'");
1504 log_msg(1, " exit");
1505 log_msg(1, " unmount-me");
1506 log_msg(1,
1507 "If you're really stuck, please e-mail the mailing list.");
1508 } else {
1509 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1510 }
1511 paranoid_free(boot_device);
1512
1513 return (res);
1514}
1515
1516/**************************************************************************
1517 *END_RUN_GRUB *
1518 **************************************************************************/
1519
1520
1521/**
1522 * Install ELILO on the user's boot drive (determined by elilo.conf).
1523 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1524 * @return 0 for success, nonzero for failure.
1525 */
1526int run_elilo(bool offer_to_run_stabelilo)
1527{
1528 /** malloc **/
1529 char *command = NULL;
1530 char *tmp = NULL;
1531 char *editor = NULL;
1532
1533 int res;
1534 int done;
1535
1536 if (offer_to_run_stabelilo
1537 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1538
1539 /* interactive mode */
1540 {
1541 mvaddstr_and_log_it(g_currentY,
1542 0,
1543 "Modifying fstab and elilo.conf... ");
1544 mr_asprintf(command, "stabelilo-me");
1545 res = run_program_and_log_output(command, 3);
1546 mr_free(command);
1547
1548 if (res) {
1549 popup_and_OK
1550 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1551 for (done = FALSE; !done;) {
1552 if (!g_text_mode) {
1553 newtSuspend();
1554 }
1555 mr_asprintf(editor, "%s", find_my_editor());
1556
1557 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1558 paranoid_system(tmp);
1559 mr_free(tmp);
1560
1561 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1562 paranoid_system(tmp);
1563 mr_free(tmp);
1564 mr_free(editor);
1565
1566 if (!g_text_mode) {
1567 newtResume();
1568 }
1569// newtCls();
1570 if (ask_me_yes_or_no("Edit them again?")) {
1571 continue;
1572 }
1573 done = TRUE;
1574 }
1575 } else {
1576 log_to_screen("elilo.conf and fstab were modified OK");
1577 }
1578 } else
1579 /* nuke mode */
1580 {
1581 res = TRUE;
1582 }
1583 return (res);
1584}
1585
1586/**************************************************************************
1587 *END_RUN_ELILO *
1588 **************************************************************************/
1589
1590
1591/**
1592 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1593 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1594 * @return 0 for success, nonzero for failure.
1595 */
1596int run_lilo(bool offer_to_run_stablilo)
1597{
1598 /** malloc **/
1599 char *command = NULL;
1600 char *tmp = NULL;
1601 char *editor = NULL;
1602
1603 int res;
1604 int done;
1605 bool run_lilo_M = FALSE;
1606
1607 if (!run_program_and_log_output
1608 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1609 run_lilo_M = TRUE;
1610 }
1611
1612 if (offer_to_run_stablilo
1613 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1614
1615 /* interactive mode */
1616 {
1617 mvaddstr_and_log_it(g_currentY,
1618 0,
1619 "Modifying fstab and lilo.conf, and running LILO... ");
1620 mr_asprintf(command, "stablilo-me");
1621 res = run_program_and_log_output(command, 3);
1622 mr_free(command);
1623
1624 if (res) {
1625 popup_and_OK
1626 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1627 for (done = FALSE; !done;) {
1628 if (!g_text_mode) {
1629 newtSuspend();
1630 }
1631 mr_asprintf(editor, "%s", find_my_editor());
1632
1633 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1634 paranoid_system(tmp);
1635 mr_free(tmp);
1636
1637 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1638 paranoid_system(tmp);
1639 mr_free(tmp);
1640 mr_free(editor);
1641
1642 if (!g_text_mode) {
1643 newtResume();
1644 }
1645// newtCls();
1646 if (ask_me_yes_or_no("Edit them again?")) {
1647 continue;
1648 }
1649 res =
1650 run_program_and_log_output("chroot " MNT_RESTORING
1651 " lilo -L", 3);
1652 if (res) {
1653 res =
1654 run_program_and_log_output("chroot " MNT_RESTORING
1655 " lilo", 3);
1656 }
1657 if (res) {
1658 done =
1659 ask_me_yes_or_no
1660 ("LILO failed. Re-edit system files?");
1661 } else {
1662 done = TRUE;
1663 }
1664 }
1665 } else {
1666 log_to_screen("lilo.conf and fstab were modified OK");
1667 }
1668 } else
1669 /* nuke mode */
1670 {
1671 mvaddstr_and_log_it(g_currentY,
1672 0,
1673 "Running LILO... ");
1674 res =
1675 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1676 3);
1677 if (res) {
1678 res =
1679 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1680 3);
1681 }
1682 if (res) {
1683 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1684 log_to_screen
1685 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1686 } else {
1687 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1688 }
1689 }
1690 if (run_lilo_M) {
1691 run_program_and_log_output("chroot " MNT_RESTORING
1692 " lilo -M /dev/hda", 3);
1693 run_program_and_log_output("chroot " MNT_RESTORING
1694 " lilo -M /dev/sda", 3);
1695 }
1696 return (res);
1697}
1698
1699/**************************************************************************
1700 *END_RUN_LILO *
1701 **************************************************************************/
1702
1703
1704/**
1705 * Install a raw MBR onto @p bd.
1706 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1707 * @param bd The device to copy the stored MBR to.
1708 * @return 0 for success, nonzero for failure.
1709 */
1710int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1711{
1712 /** malloc **/
1713 char *command = NULL;
1714 char *boot_device = NULL;
1715 char *tmp = NULL;
1716 char *editor;
1717 int res;
1718 int done;
1719
1720 malloc_string(boot_device);
1721 assert_string_is_neither_NULL_nor_zerolength(bd);
1722
1723 strcpy(boot_device, bd);
1724
1725 if (offer_to_hack_scripts
1726 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1727 /* interactive mode */
1728 mvaddstr_and_log_it(g_currentY, 0,
1729 "Modifying fstab and restoring MBR... ");
1730 for (done = FALSE; !done;) {
1731 if (!run_program_and_log_output("which vi", FALSE)) {
1732 popup_and_OK("You will now edit fstab");
1733 if (!g_text_mode) {
1734 newtSuspend();
1735 }
1736 mr_asprintf(editor, "%s", find_my_editor());
1737 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1738 mr_free(editor);
1739
1740 paranoid_system(tmp);
1741 mr_free(tmp);
1742 if (!g_text_mode) {
1743 newtResume();
1744 }
1745 }
1746 popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
1747 mr_asprintf(command, "stabraw-me %s", boot_device);
1748 res = run_program_and_log_output(command, 3);
1749 mr_free(command);
1750
1751 if (res) {
1752 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1753 } else {
1754 done = TRUE;
1755 }
1756 }
1757 } else {
1758 /* nuke mode */
1759 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1760 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1761
1762 mvaddstr_and_log_it(g_currentY, 0,
1763 "Restoring MBR... ");
1764 res = run_program_and_log_output(command, 3);
1765 mr_free(command);
1766 }
1767 if (res) {
1768 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1769 log_to_screen
1770 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1771 } else {
1772 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1773 }
1774 paranoid_free(boot_device);
1775 return (res);
1776}
1777
1778/**************************************************************************
1779 *END_RUN_RAW_MBR *
1780 **************************************************************************/
1781
1782
1783
1784/**
1785 * malloc() and set sensible defaults for the mondorestore filename variables.
1786 * @param bkpinfo The backup information structure. Fields used:
1787 * - @c bkpinfo->tmpdir
1788 * - @c bkpinfo->disaster_recovery
1789 */
1790void setup_MR_global_filenames()
1791{
1792 char *temppath;
1793
1794 assert(bkpinfo != NULL);
1795
1796 malloc_string(g_biggielist_txt);
1797 malloc_string(g_filelist_full);
1798 malloc_string(g_filelist_imagedevs);
1799 malloc_string(g_imagedevs_restthese);
1800 malloc_string(g_mondo_cfg_file);
1801 malloc_string(g_mountlist_fname);
1802 malloc_string(g_mondo_home);
1803 malloc_string(g_isodir_device);
1804 malloc_string(g_isodir_format);
1805
1806 temppath = bkpinfo->tmpdir;
1807
1808 sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1809 sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1810 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1811// sprintf(g_imagedevs_pot, "%s/tmp/imagedevs.pot", temppath);
1812 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1813 temppath);
1814 if (bkpinfo->disaster_recovery) {
1815 sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1816 sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1817 } else {
1818 sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1819 sprintf(g_mountlist_fname, "%s/%s", temppath,
1820 MOUNTLIST_FNAME_STUB);
1821 }
1822}
1823
1824/**************************************************************************
1825 *END_SET_GLOBAL_FILENAME *
1826 **************************************************************************/
1827
1828
1829/**
1830 * Copy @p input_file (containing the result of a compare) to @p output_file,
1831 * deleting spurious "changes" along the way.
1832 * @param output_file The output file to write with spurious changes removed.
1833 * @param input_file The input file, a list of changed files created by a compare.
1834 */
1835void streamline_changes_file(char *output_file, char *input_file)
1836{
1837 FILE *fin;
1838 FILE *fout;
1839 char *incoming = NULL;
1840
1841 assert_string_is_neither_NULL_nor_zerolength(output_file);
1842 assert_string_is_neither_NULL_nor_zerolength(input_file);
1843
1844 if (!(fin = fopen(input_file, "r"))) {
1845 log_OS_error(input_file);
1846 return;
1847 }
1848 if (!(fout = fopen(output_file, "w"))) {
1849 fatal_error("cannot open output_file");
1850 }
1851 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1852 if (strncmp(incoming, "etc/adjtime", 11)
1853 && strncmp(incoming, "etc/mtab", 8)
1854 && strncmp(incoming, "tmp/", 4)
1855 && strncmp(incoming, "boot/map", 8)
1856 && !strstr(incoming, "incheckentry")
1857 && strncmp(incoming, "etc/mail/statistics", 19)
1858 && strncmp(incoming, "var/", 4))
1859 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1860 mr_free(incoming);
1861 }
1862 mr_free(incoming);
1863 paranoid_fclose(fout);
1864 paranoid_fclose(fin);
1865}
1866
1867/**************************************************************************
1868 *END_STREAMLINE_CHANGES_FILE *
1869 **************************************************************************/
1870
1871
1872/**
1873 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1874 */
1875void twenty_seconds_til_yikes()
1876{
1877 int i;
1878 /* MALLOC * */
1879 char *tmp = NULL;
1880
1881 if (does_file_exist("/tmp/NOPAUSE")) {
1882 return;
1883 }
1884 open_progress_form("CAUTION",
1885 "Be advised: I am about to ERASE your hard disk(s)!",
1886 "You may press Ctrl+Alt+Del to abort safely.",
1887 "", 20);
1888 for (i = 0; i < 20; i++) {
1889 g_current_progress = i;
1890 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1891 update_progress_form(tmp);
1892 mr_free(tmp);
1893 sleep(1);
1894 }
1895 close_progress_form();
1896}
1897
1898/**************************************************************************
1899 *END_TWENTY_SECONDS_TIL_YIKES *
1900 **************************************************************************/
1901
1902
1903/**
1904 * Unmount all devices in @p p_external_copy_of_mountlist.
1905 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1906 * @return 0 for success, nonzero for failure.
1907 */
1908int unmount_all_devices(struct mountlist_itself
1909 *p_external_copy_of_mountlist)
1910{
1911 struct mountlist_itself *mountlist;
1912 int retval = 0, lino, res = 0, i;
1913 char *command = NULL;
1914 char *tmp = NULL;
1915
1916 assert(p_external_copy_of_mountlist != NULL);
1917
1918 mountlist = malloc(sizeof(struct mountlist_itself));
1919 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1920 sizeof(struct mountlist_itself));
1921 sort_mountlist_by_mountpoint(mountlist, 0);
1922
1923 run_program_and_log_output("df -m -P", 3);
1924 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1925 open_progress_form("Unmounting devices",
1926 "Unmounting all devices that were mounted,",
1927 "in preparation for the post-restoration reboot.",
1928 "", mountlist->entries);
1929 if (chdir("/")) {
1930 // FIXME
1931 }
1932 for (i = 0;
1933 i < 10
1934 &&
1935 run_program_and_log_output
1936 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1937 i++) {
1938 sleep(1);
1939 log_msg(2, "Waiting for buffer() to finish");
1940 }
1941
1942 sync();
1943
1944 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1945 if (run_program_and_log_output(tmp, FALSE)) {
1946 log_msg(1,
1947 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1948 }
1949 paranoid_free(tmp);
1950 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1951 run_program_and_log_output("mkdir -p " MNT_RESTORING
1952 "/mnt/.boot.d", 5);
1953 }
1954
1955 /* Unmounting the local /proc and /sys first */
1956 run_program_and_log_output("umount -d " MNT_RESTORING "/proc",3);
1957 run_program_and_log_output("umount -d " MNT_RESTORING "/sys",3);
1958
1959 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1960 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1961 continue;
1962 }
1963 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
1964 update_progress_form(tmp);
1965
1966 if (is_this_device_mounted(mountlist->el[lino].device)) {
1967 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1968 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
1969 } else {
1970 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1971 mr_asprintf(command, "umount -d %s/", MNT_RESTORING);
1972 log_msg(3,
1973 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1974 } else {
1975 mr_asprintf(command, "umount -d " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
1976
1977 /* To support latest Ubuntu where /var is a separate FS
1978 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1979 * we need to create some dirs under the real / before unmounting it */
1980 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1981 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1982 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1983 }
1984 }
1985 }
1986 log_msg(10, "The 'umount' command is '%s'", command);
1987 res = run_program_and_log_output(command, 3);
1988 mr_free(command);
1989 } else {
1990 mr_strcat(tmp, "...not mounted anyway :-) OK");
1991 res = 0;
1992 }
1993 g_current_progress++;
1994 if (res) {
1995 mr_strcat(tmp, "...Failed");
1996 retval++;
1997 log_to_screen(tmp);
1998 } else {
1999 log_msg(2, tmp);
2000 }
2001 paranoid_free(tmp);
2002 }
2003 close_progress_form();
2004 if (retval) {
2005 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2006 } else {
2007 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2008 }
2009 if (retval) {
2010 log_to_screen("Unable to unmount some of your partitions.");
2011 } else {
2012 log_to_screen("All partitions were unmounted OK.");
2013 }
2014 free(mountlist);
2015 return (retval);
2016}
2017
2018/**************************************************************************
2019 *END_UNMOUNT_ALL_DEVICES *
2020 **************************************************************************/
2021
2022/**
2023 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2024 * to the ./tmp/ directory.
2025 * @param dev The tape device to read from.
2026 * @return 0 for success, nonzero for failure.
2027 */
2028int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2029{
2030 char *command = NULL;
2031 int res = 0;
2032
2033 if (bkpinfo->use_obdr) {
2034 skip_obdr();
2035 } else {
2036 // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2037 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
2038 }
2039
2040 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);
2041 log_msg(2, "command = '%s'", command);
2042 res = run_program_and_log_output(command, -1);
2043 mr_free(command);
2044
2045 if (res != 0) {
2046 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2047 res = 0;
2048 } else {
2049 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2050 log_msg(2, "pre-2.2.4 compatible mode on");
2051 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);
2052 log_msg(2, "command = '%s'", command);
2053 res = run_program_and_log_output(command, -1);
2054 mr_free(command);
2055 if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
2056 res = 0;
2057 }
2058 }
2059 }
2060 paranoid_free(command);
2061 return (res);
2062}
2063
2064
2065/**
2066 * Get the configuration file from the floppy, tape, or CD.
2067 * @param bkpinfo The backup information structure. Fields used:
2068 * - @c bkpinfo->backup_media_type
2069 * - @c bkpinfo->media_device
2070 * - @c bkpinfo->tmpdir
2071 * @return 0 for success, nonzero for failure.
2072 */
2073int get_cfg_file_from_archive()
2074{
2075 int retval = 0;
2076
2077 /** malloc *****/
2078 char *command = NULL;
2079 char *cfg_file = NULL;
2080 char *tmp = NULL;
2081 char *mountpt = NULL;
2082 char *mountlist_file = NULL;
2083 bool extract_mountlist_stub = FALSE;
2084 bool extract_i_want_my_lvm = FALSE;
2085
2086 bool try_plan_B;
2087
2088 assert(bkpinfo != NULL);
2089 log_msg(2, "gcffa --- starting");
2090 log_to_screen("I'm thinking...");
2091 mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2092 if (chdir(bkpinfo->tmpdir)) {
2093 // FIXME
2094 }
2095 mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB);
2096 unlink(cfg_file); // cfg_file[] is missing the '/' at the start, FYI, by intent
2097 mr_free(cfg_file);
2098
2099 unlink(FILELIST_FULL_STUB);
2100 unlink(BIGGIELIST_TXT_STUB);
2101 mr_asprintf(command, "mkdir -p %s", mountpt);
2102 run_program_and_log_output(command, FALSE);
2103 mr_free(command);
2104
2105 mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2106 mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2107 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2108 mr_free(mountpt);
2109
2110 if (!does_file_exist(cfg_file)) {
2111 log_msg(2, "gcffa --- we don't have cfg file yet.");
2112 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2113 try_plan_B = TRUE;
2114 } else {
2115 log_msg(2, "gcffa --- calling mount_media now :)");
2116 if (!mount_media()) {
2117 log_msg(2,
2118 "gcffa --- managed to mount CD; so, no need for Plan B");
2119 try_plan_B = FALSE;
2120 } else {
2121 try_plan_B = TRUE;
2122 }
2123 if (what_number_cd_is_this() > 1) {
2124 insist_on_this_cd_number((g_current_media_number = 1));
2125 }
2126 }
2127 if (try_plan_B) {
2128 log_msg(2, "gcffa --- OK, switching to Plan B");
2129 if (chdir(bkpinfo->tmpdir)) {
2130 // FIXME
2131 }
2132 run_program_and_log_output("mkdir -p tmp", FALSE);
2133
2134 if (strlen(bkpinfo->media_device) == 0) {
2135 strcpy(bkpinfo->media_device, "/dev/st0");
2136 log_msg(2, "media_device is blank; assuming %s");
2137 }
2138 mr_asprintf(tmp, "%s", bkpinfo->media_device);
2139 if (extract_cfg_file_and_mountlist_from_tape_dev
2140 (bkpinfo->media_device)) {
2141 strcpy(bkpinfo->media_device, "/dev/st0");
2142 if (extract_cfg_file_and_mountlist_from_tape_dev
2143 (bkpinfo->media_device)) {
2144 strcpy(bkpinfo->media_device, "/dev/osst0");
2145 if (extract_cfg_file_and_mountlist_from_tape_dev
2146 (bkpinfo->media_device)) {
2147 strcpy(bkpinfo->media_device, "/dev/ht0");
2148 if (extract_cfg_file_and_mountlist_from_tape_dev
2149 (bkpinfo->media_device)) {
2150 log_msg(3,
2151 "I tried lots of devices but none worked.");
2152 strcpy(bkpinfo->media_device, tmp);
2153 }
2154 }
2155 }
2156 }
2157 mr_free(tmp);
2158
2159 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2160 log_to_screen("Cannot find config info on media");
2161 return (1);
2162 }
2163 } else {
2164 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
2165 extract_mountlist_stub = FALSE;
2166 } else {
2167 extract_mountlist_stub = TRUE;
2168 }
2169 if (does_file_exist("/"IWANTMYLVM_STUB)) {
2170 extract_i_want_my_lvm = FALSE;
2171 } else {
2172 extract_i_want_my_lvm = TRUE;
2173 }
2174
2175 log_msg(2,
2176 "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2177 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
2178 run_program_and_log_output(command, TRUE);
2179 mr_free(command);
2180
2181 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2182 /* Doing that allow us to remain compatible with pre-2.2.5 versions */
2183 log_msg(2, "pre-2.2.4 compatible mode on");
2184 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
2185 run_program_and_log_output(command, TRUE);
2186 mr_free(command);
2187 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2188 fatal_error
2189 ("Please reinsert the disk/CD and try again.");
2190 }
2191 }
2192 }
2193 }
2194 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2195 log_msg(1, "gcffa --- great! We've got the config file");
2196 mr_asprintf(tmp, "%s/%s", call_program_and_get_last_line_of_output("pwd"), MONDO_CFG_FILE_STUB);
2197 mr_asprintf(command, "cp -f %s %s", tmp, cfg_file);
2198 log_it("%s",command);
2199 if (strcmp(tmp, cfg_file)
2200 && run_program_and_log_output(command, 1)) {
2201 log_msg(1,
2202 "... but an error occurred when I tried to move it to %s",
2203 cfg_file);
2204 } else {
2205 log_msg(1, "... and I moved it successfully to %s", cfg_file);
2206 }
2207 mr_free(command);
2208
2209 mr_asprintf(command, "cp -f %s/%s %s", call_program_and_get_last_line_of_output("pwd"), MOUNTLIST_FNAME_STUB, mountlist_file);
2210 log_it("%s",command);
2211 if (extract_mountlist_stub) {
2212 if (strcmp(tmp, cfg_file)
2213 && run_program_and_log_output(command, 1)) {
2214 log_msg(1, "Failed to get mountlist");
2215 } else {
2216 log_msg(1, "Got mountlist too");
2217 mr_free(command);
2218 mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname);
2219 if (run_program_and_log_output(command, 1)) {
2220 log_msg(1, "Failed to copy mountlist to /tmp");
2221 } else {
2222 log_msg(1, "Copied mountlist to /tmp as well OK");
2223 mr_free(command);
2224 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2225 run_program_and_log_output(command, 1);
2226 }
2227 }
2228 }
2229 mr_free(command);
2230 mr_free(tmp);
2231 }
2232
2233 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
2234 if (!does_file_exist(cfg_file)) {
2235 log_it("%s",cfg_file);
2236 log_msg(1, "%s not found", cfg_file);
2237 log_to_screen
2238 ("Oh dear. Unable to recover configuration file from boot disk");
2239 return (1);
2240 }
2241
2242 log_to_screen("Recovered mondo-restore.cfg");
2243 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2244 log_to_screen("...but not mountlist.txt - a pity, really...");
2245 }
2246 else {
2247 /* Is this code really useful ??? */
2248 if (extract_mountlist_stub) {
2249 mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2250 run_program_and_log_output(command, FALSE);
2251 mr_free(command);
2252 }
2253 }
2254
2255 mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2256 mr_free(cfg_file);
2257
2258 run_program_and_log_output(command, FALSE);
2259 mr_free(command);
2260
2261 if (extract_mountlist_stub) {
2262 mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2263 run_program_and_log_output(command, FALSE);
2264 mr_free(command);
2265 }
2266 mr_free(mountlist_file);
2267
2268 mr_asprintf(command, "cp -f etc/raidtab /etc/");
2269 run_program_and_log_output(command, FALSE);
2270 mr_free(command);
2271
2272 if (extract_i_want_my_lvm) {
2273 mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
2274 run_program_and_log_output(command, FALSE);
2275 mr_free(command);
2276 }
2277 g_backup_media_type = bkpinfo->backup_media_type;
2278 return (retval);
2279}
2280
2281/**************************************************************************
2282 *END_GET_CFG_FILE_FROM_ARCHIVE *
2283 **************************************************************************/
2284
2285/* @} - end restoreUtilityGroup */
2286
2287void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage)
2288{
2289 struct raidlist_itself *raidlist;
2290 int unfinished_mdstat_devices = 9999;
2291 int i = 0;
2292 char *screen_message = NULL;
2293
2294 raidlist = malloc(sizeof(struct raidlist_itself));
2295
2296 assert(wait_for_percentage <= 100);
2297 log_it("wait_until_software_raids_are_prepped");
2298 while (unfinished_mdstat_devices > 0) {
2299 // FIXME: Prefix '/dev/' should really be dynamic!
2300 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2301 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2302 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2303 return;
2304 }
2305 for (unfinished_mdstat_devices = 0; i <= raidlist->entries; i++) {
2306 if (raidlist->el[i].progress < wait_for_percentage) {
2307 unfinished_mdstat_devices++;
2308 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2309 {
2310 continue;
2311 }
2312 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2313 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2314 open_evalcall_form(screen_message);
2315 mr_free(screen_message);
2316
2317 while (raidlist->el[i].progress < wait_for_percentage) {
2318 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2319 update_evalcall_form(raidlist->el[i].progress);
2320 sleep(2);
2321 // FIXME: Prefix '/dev/' should really be dynamic!
2322 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2323 break;
2324 }
2325 }
2326 close_evalcall_form();
2327 }
2328 }
2329 }
2330 paranoid_free(raidlist);
2331}
Note: See TracBrowser for help on using the repository browser.