source: MondoRescue/branches/3.3/mondo/src/mondorestore/mondo-rstr-tools.c@ 3790

Last change on this file since 3790 was 3790, checked in by Bruno Cornec, 21 months ago

Backport link fixes made for 3.2.2 to allow build on recent gcc versions

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