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

Last change on this file since 3397 was 3397, checked in by Bruno Cornec, 9 years ago

Adds a boot-type config option

It's filled by mondoarchive, passed to mindi as new 23rd param and
stored in the config file. It's also now read at restore time. No
exploitation of this parameter is done yet.
Remains also to prepare a correct bootable device for restoration
(currently ia64 == EFI we should manage the boot loader separately from
the boot type and from the boot env of the DR media)

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