source: MondoRescue/branches/stable/mondo/src/mondorestore/mondo-rstr-tools.c@ 1275

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

find_my_editor now uses first the value of the env var EDITOR

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