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

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