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

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