source: MondoRescue/trunk/mondo/src/mondorestore/mondo-rstr-tools.c@ 1086

Last change on this file since 1086 was 1086, checked in by Bruno Cornec, 17 years ago

log_msg => mr_msg in trunk

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