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

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

Continue to use configuration file data (may not compile)

  • Property svn:keywords set to Id
File size: 70.6 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-tools.c 1638 2007-09-19 07:32: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 = mr_conf->internal_tape_blocksize;
889 mr_msg(1, "Internal tape block size = default (%ld)", mr_conf->internal_tape_blocksize);
890 }
891
892 read_cfg_var(cfg_file, "use-lzo", value);
893 if (strstr(value, "yes")) {
894 bkpinfo->use_lzo = TRUE;
895 bkpinfo->use_gzip = FALSE;
896 strcpy(bkpinfo->zip_exe, "lzop");
897 strcpy(bkpinfo->zip_suffix, "lzo");
898 } else {
899 read_cfg_var(cfg_file, "use-gzip", value);
900 if (strstr(value, "yes")) {
901 bkpinfo->use_lzo = FALSE;
902 bkpinfo->use_gzip = TRUE;
903 strcpy(bkpinfo->zip_exe, "gzip");
904 strcpy(bkpinfo->zip_suffix, "gz");
905 } else {
906 read_cfg_var(cfg_file, "use-comp", value);
907 if (strstr(value, "yes")) {
908 bkpinfo->use_lzo = FALSE;
909 bkpinfo->use_gzip = FALSE;
910 strcpy(bkpinfo->zip_exe, "bzip2");
911 strcpy(bkpinfo->zip_suffix, "bz2");
912 } else {
913 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
914 }
915 }
916 }
917
918 value[0] = '\0';
919 read_cfg_var(cfg_file, "differential", value);
920 if (!strcmp(value, "yes") || !strcmp(value, "1")) {
921 bkpinfo->differential = TRUE;
922 }
923 mr_msg(2, "differential var = '%s'", value);
924 if (bkpinfo->differential) {
925 mr_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
926 } else {
927 mr_msg(2, "This is a regular (full) backup");
928 }
929
930 read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
931 if (tmp[0]
932 ||
933 strstr(call_program_and_get_last_line_of_output
934 ("cat /proc/cmdline"), "donteject")) {
935 bkpinfo->please_dont_eject = TRUE;
936 mr_msg(2, "Ok, I shan't eject when restoring! Groovy.");
937 }
938
939 if (bkpinfo->backup_media_type == nfs) {
940 if (!cfgf) {
941 mr_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount);
942 mr_msg(2, "nfs_remote_dir remains %s",
943 bkpinfo->nfs_remote_dir);
944 mr_msg(2,
945 "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
946 } else {
947 read_cfg_var(g_mondo_cfg_file, "nfs-server-mount",
948 bkpinfo->nfs_mount);
949 read_cfg_var(g_mondo_cfg_file, "nfs-server-path",
950 bkpinfo->nfs_remote_dir);
951 mr_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount);
952 mr_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir);
953 }
954 if (strstr(call_program_and_get_last_line_of_output
955 ("cat /proc/cmdline"), "pxe")) {
956 /* We need to override values in PXE mode as it's
957 * already done in start-nfs */
958 envtmp1 = getenv("nfsmount");
959 if (envtmp1 == NULL) {
960 fatal_error("no nfsmount variable in environment");
961 }
962 envtmp2 = getenv("dirimg");
963 if (envtmp2 == NULL) {
964 fatal_error("no dirimg variable in environment");
965 }
966 strcpy(bkpinfo->nfs_mount,envtmp1);
967 strcpy(bkpinfo->nfs_remote_dir,envtmp2);
968 }
969 } else if (bkpinfo->backup_media_type == iso) {
970 /* Patch by Conor Daly 23-june-2004
971 * to correctly mount iso-dev and set a sensible
972 * isodir in disaster recovery mode
973 */
974 mr_asprintf(&old_isodir, bkpinfo->isodir);
975 read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
976 read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
977 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
978 if (!bkpinfo->isodir[0]) {
979 strcpy(bkpinfo->isodir, old_isodir);
980 }
981 if (!bkpinfo->disaster_recovery) {
982 if (strcmp(old_isodir, bkpinfo->isodir)) {
983 log_it
984 ("user nominated isodir differs from archive, keeping user's choice: %s %s\n",
985 old_isodir, bkpinfo->isodir);
986 strcpy(bkpinfo->isodir, old_isodir);
987 }
988 }
989 mr_free(old_isodir);
990
991 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
992 mr_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
993 if (bkpinfo->disaster_recovery) {
994 if (is_this_device_mounted(g_isodir_device)) {
995 mr_msg(2, "NB: isodir is already mounted");
996 /* Find out where it's mounted */
997 mr_asprintf(&command,
998 "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3",
999 g_isodir_device);
1000 log_it("command = %s", command);
1001 mr_asprintf(&iso_mnt, "%s",
1002 call_program_and_get_last_line_of_output(command));
1003 log_it("res of it = %s", iso_mnt);
1004 } else {
1005 mr_asprintf(&iso_mnt, "/tmp/isodir");
1006 mr_asprintf(&tmp, "mkdir -p %s", iso_mnt);
1007 run_program_and_log_output(tmp, 5);
1008 mr_free(tmp);
1009
1010 mr_asprintf(&tmp, "mount %s %s", g_isodir_device, iso_mnt);
1011 if (run_program_and_log_output(tmp, 3)) {
1012 mr_msg(1,
1013 "Unable to mount isodir. Perhaps this is really a CD backup?");
1014 bkpinfo->backup_media_type = cdr;
1015 mr_allocstr(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
1016 bkpinfo->isodir[0] = '\0';
1017 mr_free(iso_mnt);
1018 mr_free(iso_path);
1019 mr_asprintf(&iso_mnt, "");
1020 mr_asprintf(&iso_path, "");
1021 if (mount_cdrom(bkpinfo)) {
1022 fatal_error
1023 ("Unable to mount isodir. Failed to mount CD-ROM as well.");
1024 } else {
1025 mr_msg(1,
1026 "You backed up to disk, then burned some CDs.");
1027 }
1028 }
1029 mr_free(tmp);
1030 }
1031 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1032 if (bkpinfo->backup_media_type == iso) {
1033 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1034 }
1035 mr_free(iso_mnt);
1036 mr_free(iso_path);
1037 }
1038 }
1039
1040 if (media_specified_by_user != none) {
1041 if (g_restoring_live_from_cd) {
1042 if (bkpinfo->backup_media_type != media_specified_by_user) {
1043 mr_msg(2,
1044 "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1045 interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
1046 media_specified_by_user = bkpinfo->backup_media_type;
1047 get_cfg_file_from_archive(bkpinfo);
1048 }
1049 }
1050 bkpinfo->backup_media_type = media_specified_by_user;
1051 }
1052 g_backup_media_type = bkpinfo->backup_media_type;
1053 strcpy(bkpinfo->backup_media_string, bkptype_to_string(bkpinfo->backup_media_type));
1054 strcpy(g_backup_media_string, bkpinfo->backup_media_string);
1055 mr_free(value);
1056 return (0);
1057}
1058/**************************************************************************
1059 *END_READ_CFG_FILE_INTO_BKPINFO *
1060 **************************************************************************/
1061
1062
1063/**
1064 * Allow the user to edit the filelist and biggielist.
1065 * The filelist is unlinked after it is read.
1066 * @param bkpinfo The backup information structure. Fields used:
1067 * - @c bkpinfo->backup_media_type
1068 * - @c bkpinfo->isodir
1069 * - @c bkpinfo->media_device
1070 * - @c bkpinfo->tmpdir
1071 * @return The filelist structure containing the information read from disk.
1072 */
1073struct
1074s_node *process_filelist_and_biggielist(struct s_bkpinfo *bkpinfo)
1075{
1076 struct s_node *filelist = NULL;
1077
1078 char *command = NULL;
1079 char *tmp = NULL;
1080 int res = 0;
1081 size_t n = 0;
1082 pid_t pid;
1083
1084 assert(bkpinfo != NULL);
1085 malloc_string(tmp);
1086
1087 if (does_file_exist(g_filelist_full)
1088 && does_file_exist(g_biggielist_txt)) {
1089 mr_msg(1, "%s exists", g_filelist_full);
1090 mr_msg(1, "%s exists", g_biggielist_txt);
1091 mr_msg(2,
1092 "Filelist and biggielist already recovered from media. Yay!");
1093 } else {
1094 getcwd(tmp, MAX_STR_LEN);
1095 chdir(bkpinfo->tmpdir);
1096 mr_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1097 log_to_screen("Extracting filelist and biggielist from media...");
1098 unlink("/tmp/filelist.full");
1099 unlink("/" FILELIST_FULL_STUB);
1100 unlink("/tmp/i-want-my-lvm");
1101 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1102 mr_asprintf(&command,
1103 "tar -b %ld -zxf %s %s %s %s %s %s",
1104 bkpinfo->internal_tape_block_size,
1105 bkpinfo->media_device,
1106 MOUNTLIST_FNAME_STUB,
1107 BIGGIELIST_TXT_STUB,
1108 FILELIST_FULL_STUB,
1109 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1110 mr_msg(1, "tarcommand = %s", command);
1111 run_program_and_log_output(command, 1);
1112 mr_free(command);
1113 } else {
1114 mr_msg(2,
1115 "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1116 bkpinfo->isodir);
1117 insist_on_this_cd_number(bkpinfo, 1);
1118 mr_msg(2, "Back from iotcn");
1119 run_program_and_log_output("mount", 1);
1120 mr_asprintf(&command,
1121 "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1122 MNT_CDROM,
1123 MOUNTLIST_FNAME_STUB,
1124 BIGGIELIST_TXT_STUB,
1125 FILELIST_FULL_STUB,
1126 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1127
1128 mr_msg(1, "tarcommand = %s", command);
1129 run_program_and_log_output(command, 1);
1130 mr_free(command);
1131
1132 if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1133 fatal_error
1134 ("all.tar.gz did not include tmp/biggielist.txt");
1135 }
1136 if (!does_file_exist(FILELIST_FULL_STUB)) {
1137 fatal_error
1138 ("all.tar.gz did not include tmp/filelist.full.gz");
1139 }
1140 }
1141 mr_asprintf(&command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1142 g_mondo_cfg_file);
1143 run_program_and_log_output(command, FALSE);
1144 mr_free(command);
1145
1146 mr_asprintf(&command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1147 BIGGIELIST_TXT_STUB, g_biggielist_txt);
1148 mr_msg(1, "command = %s", command);
1149 paranoid_system(command);
1150 mr_free(command);
1151
1152 mr_asprintf(&command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1153 FILELIST_FULL_STUB, g_filelist_full);
1154 mr_msg(1, "command = %s", command);
1155 paranoid_system(command);
1156 mr_free(command);
1157 }
1158
1159 if (am_I_in_disaster_recovery_mode()
1160 &&
1161 ask_me_yes_or_no(_
1162 ("Do you want to retrieve the mountlist as well?")))
1163 {
1164 mr_asprintf(&command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1165 bkpinfo->tmpdir);
1166 paranoid_system(command);
1167 mr_free(command);
1168 }
1169
1170 chdir(tmp);
1171 mr_free(tmp);
1172
1173 if (!does_file_exist(g_biggielist_txt)) {
1174 mr_msg(1, "Warning - %s not found", g_biggielist_txt);
1175 }
1176 if (!does_file_exist(g_filelist_full)) {
1177 mr_msg(1, "Warning - %s does not exist", g_filelist_full);
1178 }
1179
1180 mr_msg(2, "Forking");
1181 pid = fork();
1182 switch (pid) {
1183 case -1:
1184 fatal_error("Forking error");
1185 break;
1186
1187 case 0:
1188 log_to_screen(_("Pre-processing filelist"));
1189 if (!does_file_exist(g_biggielist_txt)) {
1190 mr_asprintf(&command, "echo -n > %s", g_biggielist_txt);
1191 paranoid_system(command);
1192 mr_free(command);
1193 }
1194 mr_asprintf(&command, "grep -E '^/dev/.*' %s > %s",
1195 g_biggielist_txt, g_filelist_imagedevs);
1196 paranoid_system(command);
1197 mr_free(command);
1198 exit(0);
1199 break;
1200
1201 default:
1202 open_evalcall_form(_("Pre-processing filelist"));
1203 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1204 usleep(100000);
1205 update_evalcall_form(0);
1206 }
1207 }
1208 close_evalcall_form();
1209
1210 mr_msg(3, "loading filelist");
1211 filelist = load_filelist(g_filelist_full);
1212 mr_msg(3, "deleting original filelist");
1213 unlink(g_filelist_full);
1214 if (g_text_mode) {
1215 printf(_("Restore which directory? --> "));
1216 mr_getline(&tmp, &n, stdin);
1217 toggle_path_selection(filelist, tmp, TRUE);
1218 if (strlen(tmp) == 0) {
1219 res = 1;
1220 } else {
1221 res = 0;
1222 }
1223 mr_free(tmp);
1224 } else {
1225 res = edit_filelist(filelist);
1226 }
1227 if (res) {
1228 mr_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1229 free_filelist(filelist);
1230 return (NULL);
1231 }
1232 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1233 close_evalcall_form();
1234
1235 // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1236 // file. The filelist.full file already contains the filename of EVERY
1237 // file backed up - regular and biggie files.
1238
1239 // However, we do want to make sure the imagedevs selected by the user
1240 // are flagged for restoring.
1241 if (length_of_file(g_imagedevs_restthese) > 2) {
1242 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1243 TRUE);
1244 }
1245 return (filelist);
1246}
1247/**************************************************************************
1248 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1249 **************************************************************************/
1250
1251
1252/**
1253 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1254 * The backup filename is the filename of the original with ".pristine" added.
1255 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1256 * @param filename The filename (absolute path) within @p path_root.
1257 * @return 0 for success, nonzero for failure.
1258 */
1259int backup_crucial_file(char *path_root, char *filename)
1260{
1261 char *command = NULL;
1262 int res = 0;
1263
1264 assert(path_root != NULL);
1265 assert_string_is_neither_NULL_nor_zerolength(filename);
1266
1267 mr_asprintf(&command, "cp -f %s/%s %s/%s.pristine", path_root, filename,path_root, filename);
1268 res = run_program_and_log_output(command, 5);
1269 mr_free(command);
1270 return (res);
1271}
1272
1273
1274/**
1275 * Install the user's boot loader in the MBR.
1276 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1277 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1278 * @return 0 for success, nonzero for failure.
1279 */
1280int run_boot_loader(bool offer_to_hack_scripts)
1281{
1282 int res = 0;
1283 int retval = 0;
1284
1285 char *device = NULL;
1286#ifdef __FreeBSD__
1287 char *tmp = NULL;
1288#endif
1289 char *name = NULL;
1290
1291 malloc_string(device);
1292 malloc_string(name);
1293 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1294 backup_crucial_file(MNT_RESTORING, "/etc/grub.conf");
1295 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1296 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1297 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1298 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1299 mr_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1300 sync();
1301 if (!strcmp(name, "LILO")) {
1302 res = run_lilo(offer_to_hack_scripts);
1303 } else if (!strcmp(name, "ELILO")) {
1304 res = run_elilo(offer_to_hack_scripts);
1305 } else if (!strcmp(name, "GRUB")) {
1306 res = run_grub(offer_to_hack_scripts, device);
1307 } else if (!strcmp(name, "RAW")) {
1308 res = run_raw_mbr(offer_to_hack_scripts, device);
1309 }
1310#ifdef __FreeBSD__
1311 else if (!strcmp(name, "BOOT0")) {
1312 mr_asprintf(&tmp, "boot0cfg -B %s", device);
1313 res = run_program_and_log_output(tmp, FALSE);
1314 mr_free(tmp);
1315 } else {
1316 mr_asprintf(&tmp, "ls /dev | grep -Eq '^%ss[1-4].*$'", device);
1317 if (!system(tmp)) {
1318 mr_free(tmp);
1319 mr_asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1320 res = run_program_and_log_output(tmp, 3);
1321 } else {
1322 mr_msg(1,
1323 "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1324 }
1325 mr_free(tmp);
1326 }
1327#else
1328 else {
1329 log_to_screen
1330 (_
1331 ("Unable to determine type of boot loader. Defaulting to LILO."));
1332 res = run_lilo(offer_to_hack_scripts);
1333 }
1334#endif
1335 mr_free(device);
1336 mr_free(name);
1337
1338 retval += res;
1339 if (res) {
1340 log_to_screen(_("Your boot loader returned an error"));
1341 } else {
1342 log_to_screen(_("Your boot loader ran OK"));
1343 }
1344 return (retval);
1345}
1346/**************************************************************************
1347 *END_ RUN_BOOT_LOADER *
1348 **************************************************************************/
1349
1350
1351/**
1352 * Attempt to find the user's editor.
1353 * @return The editor found ("vi" if none could be found).
1354 * @note The returned string points to static storage that will be overwritten with each call.
1355 */
1356char *find_my_editor(void)
1357{
1358 static char output[MAX_STR_LEN];
1359 char *p;
1360
1361 if ((p = getenv("EDITOR")) != NULL) {
1362 strcpy(output, p);
1363 }
1364 if (find_home_of_exe("pico")) {
1365 strcpy(output, "pico");
1366 } else if (find_home_of_exe("nano")) {
1367 strcpy(output, "nano");
1368 } else if (find_home_of_exe("vim")) {
1369 strcpy(output, "vim");
1370 } else {
1371 strcpy(output, "vi");
1372 }
1373 if (!find_home_of_exe(output)) {
1374 mr_msg(2, " (find_my_editor) --- warning - %s not found", output);
1375 }
1376 return (output);
1377}
1378
1379
1380/**
1381 * Install GRUB on @p bd.
1382 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1383 * @param bd The boot device where GRUB is installed.
1384 * @return 0 for success, nonzero for failure.
1385 */
1386int run_grub(bool offer_to_run_stabgrub, char *bd)
1387{
1388 char *command = NULL;
1389 char *boot_device = NULL;
1390 char *tmp = NULL;
1391 char *editor = NULL;
1392
1393 int res = 0;
1394 int done = 0;
1395
1396 malloc_string(boot_device);
1397 strcpy(boot_device, bd);
1398 assert_string_is_neither_NULL_nor_zerolength(bd);
1399 mr_asprintf(&editor, find_my_editor());
1400
1401 if (offer_to_run_stabgrub
1402 && ask_me_yes_or_no(_("Did you change the mountlist?")))
1403 /* interactive mode */
1404 {
1405 mvaddstr_and_log_it(g_currentY,
1406 0,
1407 ("Modifying fstab, mtab, device.map and grub.conf, and running GRUB... "));
1408 for (done = FALSE; !done;) {
1409 popup_and_get_string(_("Boot device"),
1410 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), boot_device, MAX_STR_LEN / 4);
1411 mr_asprintf(&command, "stabgrub-me %s", boot_device);
1412 res = run_program_and_log_output(command, 1);
1413 mr_free(command);
1414
1415 if (res) {
1416 popup_and_OK
1417 (_
1418 ("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."));
1419 newtSuspend();
1420 system("chroot " MNT_RESTORING);
1421 newtResume();
1422 popup_and_OK(_("Thank you."));
1423 } else {
1424 done = TRUE;
1425 }
1426 popup_and_OK(_("You will now edit fstab, mtab, device.map and grub.conf"));
1427 if (!g_text_mode) {
1428 newtSuspend();
1429 }
1430 mr_asprintf(&tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1431 paranoid_system(tmp);
1432 mr_free(tmp);
1433
1434 mr_asprintf(&tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1435 paranoid_system(tmp);
1436 mr_free(tmp);
1437
1438 mr_asprintf(&tmp, "chroot %s %s /etc/grub.conf", MNT_RESTORING, editor);
1439 paranoid_system(tmp);
1440 mr_free(tmp);
1441
1442 mr_asprintf(&tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1443 paranoid_system(tmp);
1444 mr_free(tmp);
1445
1446 if (!g_text_mode) {
1447 newtResume();
1448 }
1449 }
1450 } else {
1451 /* nuke mode */
1452 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1453 mr_msg(1, "Yay! grub-MR found...");
1454 mr_asprintf(&command, "grub-MR %s /tmp/mountlist.txt", bd);
1455 mr_msg(1, "command = %s", command);
1456 } else {
1457 mr_asprintf(&command, "chroot " MNT_RESTORING " grub-install %s", bd);
1458 mr_msg(1, "WARNING - grub-MR not found; using grub-install");
1459 }
1460 mvaddstr_and_log_it(g_currentY,
1461 0,
1462 _
1463 ("Running GRUB... "));
1464 iamhere(command);
1465 res = run_program_and_log_output(command, 1);
1466 mr_free(command);
1467
1468 if (res) {
1469 popup_and_OK
1470 (_
1471 ("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."));
1472 newtSuspend();
1473 system("chroot " MNT_RESTORING);
1474 newtResume();
1475 popup_and_OK(_("Thank you."));
1476 }
1477 }
1478 if (res) {
1479 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1480 log_to_screen(_("GRUB ran w/error(s). See %s for more info."), MONDO_LOGFILE);
1481 mr_msg(1, "Type:-");
1482 mr_msg(1, " mount-me");
1483 mr_msg(1, " chroot " MNT_RESTORING);
1484 mr_msg(1, " mount /boot");
1485 mr_msg(1, " grub-install '(hd0)'");
1486 mr_msg(1, " exit");
1487 mr_msg(1, " unmount-me");
1488 mr_msg(1,
1489 "If you're really stuck, please e-mail the mailing list.");
1490 } else {
1491 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1492 }
1493 mr_free(boot_device);
1494 mr_free(editor);
1495 return (res);
1496}
1497/**************************************************************************
1498 *END_RUN_GRUB *
1499 **************************************************************************/
1500
1501
1502/**
1503 * Install ELILO on the user's boot drive (determined by elilo.conf).
1504 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1505 * @return 0 for success, nonzero for failure.
1506 */
1507int run_elilo(bool offer_to_run_stabelilo)
1508{
1509 char *command = NULL;
1510 char *tmp = NULL;
1511 char *editor = NULL;
1512
1513 int res = 0;
1514 int done = 0;
1515
1516 mr_asprintf(&editor, find_my_editor());
1517 if (offer_to_run_stabelilo
1518 && ask_me_yes_or_no(_("Did you change the mountlist?")))
1519
1520 /* interactive mode */
1521 {
1522 mvaddstr_and_log_it(g_currentY,
1523 0,
1524 _
1525 ("Modifying fstab and elilo.conf... "));
1526 mr_asprintf(&command, "stabelilo-me");
1527 res = run_program_and_log_output(command, 3);
1528 mr_free(command);
1529
1530 if (res) {
1531 popup_and_OK
1532 (_
1533 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist."));
1534 for (done = FALSE; !done;) {
1535 if (!g_text_mode) {
1536 newtSuspend();
1537 }
1538 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1539 paranoid_system(tmp);
1540 mr_free(tmp);
1541
1542 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/elilo.conf", editor);
1543 paranoid_system(tmp);
1544 mr_free(tmp);
1545
1546 if (!g_text_mode) {
1547 newtResume();
1548 }
1549// newtCls();
1550 if (ask_me_yes_or_no(_("Edit them again?"))) {
1551 continue;
1552 }
1553 done = TRUE;
1554 }
1555 } else {
1556 log_to_screen(_("elilo.conf and fstab were modified OK"));
1557 }
1558 } else
1559 /* nuke mode */
1560 {
1561 res = TRUE;
1562 }
1563 mr_free(editor);
1564 return (res);
1565}
1566/**************************************************************************
1567 *END_RUN_ELILO *
1568 **************************************************************************/
1569
1570
1571/**
1572 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1573 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1574 * @return 0 for success, nonzero for failure.
1575 */
1576int run_lilo(bool offer_to_run_stablilo)
1577{
1578 /** malloc **/
1579 char *command = NULL;
1580 char *tmp = NULL;
1581 char *editor = NULL;
1582
1583 int res = 0;
1584 int done = 0;
1585 bool run_lilo_M = FALSE;
1586
1587 if (!run_program_and_log_output
1588 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1589 run_lilo_M = TRUE;
1590 }
1591
1592 mr_asprintf(&editor, find_my_editor());
1593 if (offer_to_run_stablilo
1594 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1595 /* interactive mode */
1596 mvaddstr_and_log_it(g_currentY,
1597 0,
1598 _
1599 ("Modifying fstab and lilo.conf, and running LILO... "));
1600 mr_asprintf(&command, "stablilo-me");
1601 res = run_program_and_log_output(command, 3);
1602 mr_free(command);
1603
1604 if (res) {
1605 popup_and_OK
1606 (_
1607 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."));
1608 for (done = FALSE; !done;) {
1609 if (!g_text_mode) {
1610 newtSuspend();
1611 }
1612 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1613 paranoid_system(tmp);
1614 mr_free(tmp);
1615
1616 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1617 paranoid_system(tmp);
1618 mr_free(tmp);
1619
1620 if (!g_text_mode) {
1621 newtResume();
1622 }
1623 if (ask_me_yes_or_no(_("Edit them again?"))) {
1624 continue;
1625 }
1626 res =
1627 run_program_and_log_output("chroot " MNT_RESTORING
1628 " lilo -L", 3);
1629 if (res) {
1630 res =
1631 run_program_and_log_output("chroot " MNT_RESTORING
1632 " lilo", 3);
1633 }
1634 if (res) {
1635 done =
1636 ask_me_yes_or_no
1637 (_("LILO failed. Re-edit system files?"));
1638 } else {
1639 done = TRUE;
1640 }
1641 }
1642 } else {
1643 log_to_screen(_("lilo.conf and fstab were modified OK"));
1644 }
1645 } else {
1646 /* nuke mode */
1647 mvaddstr_and_log_it(g_currentY,
1648 0,
1649 _
1650 ("Running LILO... "));
1651 res =
1652 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1653 3);
1654 if (res) {
1655 res =
1656 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1657 3);
1658 }
1659 if (res) {
1660 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1661 log_to_screen
1662 (_
1663 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."));
1664 } else {
1665 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1666 }
1667 }
1668 if (run_lilo_M) {
1669 run_program_and_log_output("chroot " MNT_RESTORING
1670 " lilo -M /dev/hda", 3);
1671 run_program_and_log_output("chroot " MNT_RESTORING
1672 " lilo -M /dev/sda", 3);
1673 }
1674 mr_free(editor);
1675 return (res);
1676}
1677
1678/**************************************************************************
1679 *END_RUN_LILO *
1680 **************************************************************************/
1681
1682
1683/**
1684 * Install a raw MBR onto @p bd.
1685 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1686 * @param bd The device to copy the stored MBR to.
1687 * @return 0 for success, nonzero for failure.
1688 */
1689int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1690{
1691 char *command = NULL;
1692 char *boot_device = NULL;
1693 char *tmp = NULL;
1694 char *editor = NULL;
1695 int res = 0;
1696 int done = 0;
1697
1698 assert_string_is_neither_NULL_nor_zerolength(bd);
1699
1700 malloc_string(boot_device);
1701 mr_asprintf(&editor, find_my_editor());
1702 strcpy(boot_device, bd);
1703 if (offer_to_hack_scripts
1704 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1705 /* interactive mode */
1706 mvaddstr_and_log_it(g_currentY, 0,
1707 _
1708 ("Modifying fstab and restoring MBR... "));
1709 for (done = FALSE; !done;) {
1710 if (!run_program_and_log_output("which vi", FALSE)) {
1711 popup_and_OK(_("You will now edit fstab"));
1712 if (!g_text_mode) {
1713 newtSuspend();
1714 }
1715 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1716 paranoid_system(tmp);
1717 mr_free(tmp);
1718
1719 if (!g_text_mode) {
1720 newtResume();
1721 }
1722 }
1723 popup_and_get_string(_("Boot device"),
1724 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), boot_device, MAX_STR_LEN / 4);
1725 mr_asprintf(&command, "stabraw-me %s", boot_device);
1726 res = run_program_and_log_output(command, 3);
1727 mr_free(command);
1728
1729 if (res) {
1730 done =
1731 ask_me_yes_or_no(_("Modifications failed. Re-try?"));
1732 } else {
1733 done = TRUE;
1734 }
1735 }
1736 } else {
1737 /* nuke mode */
1738 mvaddstr_and_log_it(g_currentY, 0,
1739 _("Restoring MBR... "));
1740 mr_asprintf(&command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1741 mr_msg(2, "run_raw_mbr() --- command='%s'", command);
1742 res = run_program_and_log_output(command, 3);
1743 mr_free(command);
1744 }
1745 if (res) {
1746 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1747 log_to_screen(_("MBR+fstab processed w/error(s). See %s for more info."), MONDO_LOGFILE);
1748 } else {
1749 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1750 }
1751 mr_free(boot_device);
1752 mr_free(editor);
1753 return (res);
1754}
1755/**************************************************************************
1756 *END_RUN_RAW_MBR *
1757 **************************************************************************/
1758
1759
1760/**
1761 * Turn signal trapping on or off.
1762 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1763 * print a message and exit immediately.
1764 */
1765void set_signals(int on)
1766{
1767 int signals[] =
1768 { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1769 SIGSTOP, 0
1770 };
1771 int i;
1772 for (i = 0; signals[i]; i++) {
1773 if (on) {
1774 signal(signals[i], terminate_daemon);
1775 } else {
1776 signal(signals[i], termination_in_progress);
1777 }
1778 }
1779}
1780
1781/**************************************************************************
1782 *END_SET_SIGNALS *
1783 **************************************************************************/
1784
1785
1786/**
1787 * malloc() and set sensible defaults for the mondorestore filename variables.
1788 * @param bkpinfo The backup information structure. Fields used:
1789 * - @c bkpinfo->tmpdir
1790 * - @c bkpinfo->disaster_recovery
1791 */
1792void setup_MR_global_filenames(struct s_bkpinfo *bkpinfo)
1793{
1794 char *temppath;
1795
1796 assert(bkpinfo != NULL);
1797
1798 malloc_string(g_biggielist_txt);
1799 malloc_string(g_filelist_full);
1800 malloc_string(g_filelist_imagedevs);
1801 malloc_string(g_imagedevs_restthese);
1802 malloc_string(g_mondo_cfg_file);
1803 malloc_string(g_mountlist_fname);
1804 malloc_string(g_tmpfs_mountpt);
1805 malloc_string(g_isodir_device);
1806 malloc_string(g_isodir_format);
1807
1808 temppath = bkpinfo->tmpdir;
1809
1810 sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1811 sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1812 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1813 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1814 temppath);
1815 if (bkpinfo->disaster_recovery) {
1816 sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1817 sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1818 } else {
1819 sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1820 sprintf(g_mountlist_fname, "%s/%s", temppath,
1821 MOUNTLIST_FNAME_STUB);
1822 }
1823}
1824
1825/**************************************************************************
1826 *END_SET_GLOBAL_FILENAME *
1827 **************************************************************************/
1828
1829
1830/**
1831 * Copy @p input_file (containing the result of a compare) to @p output_file,
1832 * deleting spurious "changes" along the way.
1833 * @param output_file The output file to write with spurious changes removed.
1834 * @param input_file The input file, a list of changed files created by a compare.
1835 */
1836void streamline_changes_file(char *output_file, char *input_file)
1837{
1838 FILE *fin;
1839 FILE *fout;
1840 char *incoming = NULL;
1841 size_t n = 0;
1842
1843 assert_string_is_neither_NULL_nor_zerolength(output_file);
1844 assert_string_is_neither_NULL_nor_zerolength(input_file);
1845
1846 if (!(fin = fopen(input_file, "r"))) {
1847 log_OS_error(input_file);
1848 return;
1849 }
1850 if (!(fout = fopen(output_file, "w"))) {
1851 fatal_error("cannot open output_file");
1852 }
1853 for (mr_getline(&incoming, &n, fin); !feof(fin);
1854 mr_getline(&incoming, &n, fin)) {
1855 if (strncmp(incoming, "etc/adjtime", 11)
1856 && strncmp(incoming, "etc/mtab", 8)
1857 && strncmp(incoming, "tmp/", 4)
1858 && strncmp(incoming, "boot/map", 8)
1859 && !strstr(incoming, "incheckentry")
1860 && strncmp(incoming, "etc/mail/statistics", 19)
1861 && strncmp(incoming, "var/", 4))
1862 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1863 }
1864 mr_free(incoming);
1865 paranoid_fclose(fout);
1866 paranoid_fclose(fin);
1867}
1868/**************************************************************************
1869 *END_STREAMLINE_CHANGES_FILE *
1870 **************************************************************************/
1871
1872
1873/**
1874 * Exit due to a signal (normal cleanup).
1875 * @param sig The signal we're exiting due to.
1876 */
1877void terminate_daemon(int sig)
1878{
1879 log_to_screen
1880 (_("Mondorestore is terminating in response to a signal from the OS"));
1881 free_MR_global_filenames();
1882 finish(254);
1883}
1884/**************************************************************************
1885 *END_TERMINATE_DAEMON *
1886 **************************************************************************/
1887
1888
1889/**
1890 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1891 */
1892void twenty_seconds_til_yikes()
1893{
1894 int i;
1895 char *tmp = NULL;
1896
1897 if (does_file_exist("/tmp/NOPAUSE")) {
1898 return;
1899 }
1900 open_progress_form(_("CAUTION"),
1901 _
1902 ("Be advised: I am about to ERASE your hard disk(s)!"),
1903 _("You may press Ctrl+Alt+Del to abort safely."),
1904 "", 20);
1905 for (i = 0; i < 20; i++) {
1906 g_current_progress = i;
1907 mr_asprintf(&tmp, _("You have %d seconds left to abort."), 20 - i);
1908 update_progress_form(tmp);
1909 mr_free(tmp);
1910 sleep(1);
1911 }
1912 close_progress_form();
1913}
1914/**************************************************************************
1915 *END_TWENTY_SECONDS_TIL_YIKES *
1916 **************************************************************************/
1917
1918
1919/**
1920 * Exit due to a signal (no cleanup).
1921 * @param sig The signal we're exiting due to.
1922 */
1923void termination_in_progress(int sig)
1924{
1925 mr_msg(1, "Termination in progress");
1926 usleep(1000);
1927 pthread_exit(0);
1928}
1929/**************************************************************************
1930 *END_TERMINATION_IN_PROGRESS *
1931 **************************************************************************/
1932
1933
1934/**
1935 * Unmount all devices in @p p_external_copy_of_mountlist.
1936 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1937 * @return 0 for success, nonzero for failure.
1938 */
1939int unmount_all_devices(struct mountlist_itself
1940 *p_external_copy_of_mountlist)
1941{
1942 struct mountlist_itself *mountlist;
1943 int retval = 0;
1944 int lino = 0;
1945 int res = 0;
1946 int i = 0;
1947 char *command = NULL;
1948 char *tmp = NULL;
1949
1950 assert(p_external_copy_of_mountlist != NULL);
1951
1952 mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
1953 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1954 sizeof(struct mountlist_itself));
1955 sort_mountlist_by_mountpoint(mountlist, 0);
1956
1957 run_program_and_log_output("df -m", 3);
1958 mvaddstr_and_log_it(g_currentY, 0, _("Unmounting devices "));
1959 open_progress_form(_("Unmounting devices"),
1960 _("Unmounting all devices that were mounted,"),
1961 _
1962 ("in preparation for the post-restoration reboot."),
1963 "", mountlist->entries);
1964 chdir("/");
1965 for (i = 0;
1966 i < 10
1967 &&
1968 run_program_and_log_output
1969 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1970 i++) {
1971 sleep(1);
1972 mr_msg(2, "Waiting for buffer() to finish");
1973 }
1974
1975 sync();
1976
1977 sprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1978 if (run_program_and_log_output(tmp, FALSE)) {
1979 mr_msg(1,
1980 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1981 }
1982 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1983 run_program_and_log_output("mkdir -p " MNT_RESTORING
1984 "/mnt/.boot.d", 5);
1985 }
1986 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1987 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1988 continue;
1989 }
1990 mr_asprintf(&tmp, _("Unmounting device %s "),
1991 mountlist->el[lino].device);
1992
1993 update_progress_form(tmp);
1994
1995 if (is_this_device_mounted(mountlist->el[lino].device)) {
1996 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1997 mr_asprintf(&command, "swapoff %s", mountlist->el[lino].device);
1998 } else {
1999 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2000 mr_asprintf(&command, "umount %s/", MNT_RESTORING);
2001 mr_msg(3,
2002 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2003 } else {
2004 mr_asprintf(&command, "umount " MNT_RESTORING "%s",
2005 mountlist->el[lino].mountpoint);
2006 }
2007 }
2008 mr_msg(10, "The 'umount' command is '%s'", command);
2009 res = run_program_and_log_output(command, 3);
2010 mr_free(command);
2011 } else {
2012 mr_strcat(tmp, _("...not mounted anyway :-) OK"));
2013 res = 0;
2014 }
2015 g_current_progress++;
2016 if (res) {
2017 mr_strcat(tmp, _("...Failed"));
2018 retval++;
2019 log_to_screen(tmp);
2020 } else {
2021 mr_msg(2, tmp);
2022 }
2023 mr_free(tmp);
2024 }
2025 close_progress_form();
2026 if (retval) {
2027 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
2028 } else {
2029 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2030 }
2031 if (retval) {
2032 log_to_screen(_("Unable to unmount some of your partitions."));
2033 } else {
2034 log_to_screen(_("All partitions were unmounted OK."));
2035 }
2036 mr_free(mountlist);
2037 return (retval);
2038}
2039/**************************************************************************
2040 *END_UNMOUNT_ALL_DEVICES *
2041 **************************************************************************/
2042
2043
2044/**
2045 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2046 * to the ./tmp/ directory.
2047 * @param dev The tape device to read from.
2048 * @return 0 for success, nonzero for failure.
2049 */
2050int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2051{
2052 char *command = NULL;
2053 int res = 0;
2054 // BERLIOS: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2055 long tape_block_size = 32768;
2056
2057 // tar -zxvf-
2058 mr_asprintf(&command,
2059 "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2060 dev,
2061 tape_block_size,
2062 1024L * 1024 * 32 / tape_block_size,
2063 MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2064 BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2065 mr_msg(2, "command = '%s'", command);
2066 res = run_program_and_log_output(command, -1);
2067 mr_free(command);
2068
2069 if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2070 res = 0;
2071 }
2072 return (res);
2073}
2074
2075
2076/**
2077 * Get the configuration file from the tape, or CD.
2078 * @param bkpinfo The backup information structure. Fields used:
2079 * - @c bkpinfo->backup_media_type
2080 * - @c bkpinfo->media_device
2081 * - @c bkpinfo->tmpdir
2082 * @return 0 for success, nonzero for failure.
2083 */
2084int get_cfg_file_from_archive(struct s_bkpinfo *bkpinfo)
2085{
2086 int retval = 0;
2087 char *command = NULL;
2088 char *cfg_file = NULL;
2089 char *mounted_cfgf_path = NULL;
2090 char *tmp = NULL;
2091 char *mountpt = NULL;
2092 char *ramdisk_fname = NULL;
2093 char *mountlist_file = NULL;
2094 int res = 0;
2095
2096 bool try_plan_B = FALSE;
2097
2098 assert(bkpinfo != NULL);
2099 mr_msg(2, "gcffa --- starting");
2100 log_to_screen(_("I'm thinking..."));
2101 mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2102 chdir(bkpinfo->tmpdir);
2103 // MONDO_CFG_FILE_STUB is missing the '/' at the start, FYI, by intent
2104 unlink(MONDO_CFG_FILE_STUB);
2105
2106 unlink(FILELIST_FULL_STUB);
2107 unlink(BIGGIELIST_TXT_STUB);
2108 unlink("tmp/i-want-my-lvm");
2109 mr_asprintf(&command, "mkdir -p %s", mountpt);
2110 run_program_and_log_output(command, FALSE);
2111 mr_free(command);
2112
2113 mr_asprintf(&cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2114 mr_asprintf(&mountlist_file, "%s/%s", bkpinfo->tmpdir,
2115 MOUNTLIST_FNAME_STUB);
2116 mr_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2117
2118 mr_asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2119 run_program_and_log_output(tmp, FALSE);
2120 mr_free(tmp);
2121
2122 if (!does_file_exist(cfg_file)) {
2123 mr_msg(2, "gcffa --- we don't have cfg file yet.");
2124 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2125 try_plan_B = TRUE;
2126 } else {
2127 mr_msg(2, "gcffa --- calling mount_cdrom now :)");
2128 if (!mount_cdrom(bkpinfo)) {
2129 mr_msg(2,
2130 "gcffa --- managed to mount CD; so, no need for Plan B");
2131 try_plan_B = FALSE;
2132 } else {
2133 try_plan_B = TRUE;
2134 }
2135 if (what_number_cd_is_this(bkpinfo) > 1) {
2136 insist_on_this_cd_number(bkpinfo,
2137 (g_current_media_number = 1));
2138 }
2139 }
2140 if (try_plan_B) {
2141 mr_msg(2, "gcffa --- OK, switching to Plan B");
2142 chdir(bkpinfo->tmpdir);
2143 run_program_and_log_output("mkdir -p tmp", FALSE);
2144
2145 if (strlen(bkpinfo->media_device) == 0) {
2146 mr_allocstr(bkpinfo->media_device, "/dev/st0");
2147 mr_msg(2, "media_device is blank; assuming %s",
2148 bkpinfo->media_device);
2149 }
2150 mr_asprintf(&tmp, bkpinfo->media_device);
2151 if (extract_cfg_file_and_mountlist_from_tape_dev
2152 (bkpinfo->media_device)) {
2153 mr_allocstr(bkpinfo->media_device, "/dev/st0");
2154 if (extract_cfg_file_and_mountlist_from_tape_dev
2155 (bkpinfo->media_device)) {
2156 mr_allocstr(bkpinfo->media_device, "/dev/osst0");
2157 if (extract_cfg_file_and_mountlist_from_tape_dev
2158 (bkpinfo->media_device)) {
2159 mr_allocstr(bkpinfo->media_device, "/dev/ht0");
2160 if (extract_cfg_file_and_mountlist_from_tape_dev
2161 (bkpinfo->media_device)) {
2162 mr_msg(3,
2163 "I tried lots of devices but none worked.");
2164 mr_allocstr(bkpinfo->media_device, tmp);
2165 }
2166 }
2167 }
2168 }
2169 mr_free(tmp);
2170
2171 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2172 log_to_screen(_
2173 ("Cannot find config info on tape/CD"));
2174 return (1);
2175 }
2176 } else {
2177 mr_asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2178 if (!does_file_exist(mounted_cfgf_path)) {
2179 mr_msg(2,
2180 "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2181 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
2182 run_program_and_log_output(command, TRUE);
2183 mr_free(command);
2184
2185 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2186 fatal_error
2187 ("Please reinsert the disk/CD and try again.");
2188 }
2189 }
2190 mr_free(mounted_cfgf_path);
2191 }
2192 }
2193 mr_free(mountpt);
2194
2195 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2196 mr_msg(1, "gcffa --- great! We've got the config file");
2197 mr_asprintf(&tmp, "%s/%s",
2198 call_program_and_get_last_line_of_output("pwd"),
2199 MONDO_CFG_FILE_STUB);
2200 mr_asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2201 iamhere(command);
2202
2203 if (strcmp(tmp, cfg_file)
2204 && run_program_and_log_output(command, 1)) {
2205 mr_msg(1,
2206 "... but an error occurred when I tried to move it to %s",
2207 cfg_file);
2208 } else {
2209 mr_msg(1, "... and I moved it successfully to %s", cfg_file);
2210 }
2211 mr_free(command);
2212
2213 mr_asprintf(&command, "cp -f %s/%s %s",
2214 call_program_and_get_last_line_of_output("pwd"),
2215 MOUNTLIST_FNAME_STUB, mountlist_file);
2216 iamhere(command);
2217 if (strcmp(tmp, cfg_file)
2218 && run_program_and_log_output(command, 1)) {
2219 mr_msg(1, "Failed to get mountlist");
2220 } else {
2221 mr_msg(1, "Got mountlist too");
2222 mr_free(command);
2223 mr_asprintf(&command, "cp -f %s %s", mountlist_file,
2224 g_mountlist_fname);
2225 if (run_program_and_log_output(command, 1)) {
2226 mr_msg(1, "Failed to copy mountlist to /tmp");
2227 } else {
2228 mr_msg(1, "Copied mountlist to /tmp as well OK");
2229 mr_free(command);
2230 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2231 run_program_and_log_output(command, 1);
2232 }
2233 }
2234 mr_free(command);
2235 mr_free(tmp);
2236 }
2237 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2238 if (!does_file_exist(cfg_file)) {
2239 iamhere(cfg_file);
2240 mr_msg(1, "%s not found", cfg_file);
2241 log_to_screen
2242 (_
2243 ("Oh dear. Unable to recover configuration file from boot disk"));
2244 return (1);
2245 }
2246
2247 log_to_screen(_("Recovered mondo-restore.cfg"));
2248 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2249 log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2250 }
2251/* start SAH */
2252 else {
2253 mr_asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2254 bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2255 run_program_and_log_output(command, FALSE);
2256 mr_free(command);
2257 }
2258/* end SAH */
2259
2260 mr_asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2261 mr_free(cfg_file);
2262 run_program_and_log_output(command, FALSE);
2263 mr_free(command);
2264
2265 mr_asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2266 mr_free(mountlist_file);
2267 run_program_and_log_output(command, FALSE);
2268 mr_free(command);
2269
2270 mr_asprintf(&command, "cp -f etc/raidtab /etc/");
2271 run_program_and_log_output(command, FALSE);
2272 mr_free(command);
2273
2274 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2275 run_program_and_log_output(command, FALSE);
2276 mr_free(command);
2277
2278 g_backup_media_type = bkpinfo->backup_media_type;
2279 strncpy(bkpinfo->backup_media_string,bkptype_to_string(bkpinfo->backup_media_type), (size_t)63);
2280 g_backup_media_string = bkpinfo->backup_media_string;
2281 return (retval);
2282}
2283/**************************************************************************
2284 *END_GET_CFG_FILE_FROM_ARCHIVE *
2285 **************************************************************************/
2286/* @} - end restoreUtilityGroup */
2287
2288
2289void wait_until_software_raids_are_prepped(int wait_for_percentage)
2290{
2291 struct raidlist_itself *raidlist = NULL;
2292 int unfinished_mdstat_devices = 9999, i = 0;
2293 char *screen_message = NULL;
2294
2295 raidlist = (struct raidlist_itself *)mr_malloc(sizeof(struct raidlist_itself));
2296
2297 assert(wait_for_percentage <= 100);
2298 iamhere("wait_until_software_raids_are_prepped");
2299 while (unfinished_mdstat_devices > 0) {
2300 // FIXME: Prefix '/dev/' should really be dynamic!
2301 if (parse_mdstat(raidlist, "/dev/")) {
2302 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2303 mr_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2304 return;
2305 }
2306 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2307 if (raidlist->el[i].progress < wait_for_percentage) {
2308 unfinished_mdstat_devices++;
2309 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2310 {
2311 continue;
2312 }
2313 mr_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2314 mr_asprintf(&screen_message, "Sync'ing %s",
2315 raidlist->el[i].raid_device);
2316 open_evalcall_form(screen_message);
2317 mr_free(screen_message);
2318
2319 while (raidlist->el[i].progress < wait_for_percentage) {
2320 mr_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2321 update_evalcall_form(raidlist->el[i].progress);
2322 sleep(2);
2323 // FIXME: Prefix '/dev/' should really be dynamic!
2324 if (parse_mdstat(raidlist, "/dev/")) {
2325 break;
2326 }
2327 }
2328 close_evalcall_form();
2329 }
2330 }
2331 }
2332 mr_free(raidlist);
2333}
Note: See TracBrowser for help on using the repository browser.