source: MondoRescue/tags/3.2.2/mondo/src/mondorestore/mondo-rstr-tools.c@ 3866

Last change on this file since 3866 was 3789, checked in by Bruno Cornec, 23 months ago

More fixes for global vars which should not be initialized when declared with extern

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