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

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

STD_PREFIX only for restore now, waiting for removal also.

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