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

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

typo

  • Property svn:keywords set to Id
File size: 72.4 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-tools.c 1267 2007-03-24 10:31:19Z bruno $
3*/
4
5
6#include <pthread.h>
7#include <unistd.h>
8#include "my-stuff.h"
9#include "mr_mem.h"
10#include "mr_msg.h"
11#include "mr_str.h"
12
13#include "mondostructures.h"
14#include "libmondo.h"
15#include "mr-externs.h"
16#include "mondo-rstr-tools.h"
17
18extern bool g_sigpipe_caught;
19extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
20extern bool g_I_have_just_nuked;
21extern char *g_tmpfs_mountpt;
22extern char *g_isodir_device;
23extern char *g_isodir_format;
24extern long g_current_progress, g_maximum_progress;
25extern char *g_biggielist_txt; // where 'biggielist.txt' is stored, on ramdisk / tempdir;
26 // biggielist.txt is the list of big files stored on the
27 // backup media set in question
28extern char *g_filelist_full; // filelist.full.gz is the list of all regular files
29 // (excluding big files) stored on the backup media set
30extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the
31 // user chooses them
32extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which
33 // were archived as images, not just /dev entries
34 // ... e.g. NTFS, BeOS partitions
35extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
36 // restore only these
37extern char *g_mondo_cfg_file; // where m*ndo-restore.cfg (the config file) is stored
38extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
39
40extern t_bkptype g_backup_media_type;
41extern char *g_backup_media_string;
42
43extern int g_partition_table_locked_up;
44
45/* Should we use or not extended attributes and acl when restoring */
46char *g_getfattr = NULL;
47char *g_getfacl = NULL;
48
49/**
50 * @addtogroup restoreUtilityGroup
51 * @{
52 */
53/**
54 * Free the malloc()s for the filename variables.
55 */
56void free_MR_global_filenames(void)
57{
58 mr_free(g_biggielist_txt);
59 mr_free(g_filelist_full);
60 mr_free(g_filelist_imagedevs);
61 mr_free(g_imagedevs_restthese);
62 mr_free(g_mondo_cfg_file);
63 mr_free(g_mountlist_fname);
64 mr_free(g_tmpfs_mountpt);
65 mr_free(g_isodir_device);
66 mr_free(g_isodir_format);
67}
68
69
70/**
71 * Ask the user which imagedevs from the list contained in @p infname should
72 * actually be restored.
73 * @param infname The file containing a list of all imagedevs.
74 * @param outfname The location of the output file containing the imagedevs the user wanted to restore.
75 * @ingroup restoreUtilityGroup
76 */
77void ask_about_these_imagedevs(char *infname, char *outfname)
78{
79 FILE *fin = NULL;
80 FILE *fout = NULL;
81 /************************************************************************
82 * allocate memory regions. test and set -sab 16 feb 2003 *
83 ************************************************************************/
84 char *incoming = NULL;
85 char *question = NULL;
86
87 size_t n = 0;
88
89 assert_string_is_neither_NULL_nor_zerolength(infname);
90 assert_string_is_neither_NULL_nor_zerolength(outfname);
91
92 if (!(fin = fopen(infname, "r"))) {
93 fatal_error("Cannot openin infname");
94 }
95 if (!(fout = fopen(outfname, "w"))) {
96 fatal_error("Cannot openin outfname");
97 }
98 for (mr_getline(&incoming, &n, fin);
99 !feof(fin); mr_getline(&incoming, &n, fin)) {
100 mr_strip_spaces(incoming);
101
102 if (incoming[0] == '\0') {
103 continue;
104 }
105
106 mr_asprintf(&question,
107 _("Should I restore the image of %s ?"), incoming);
108
109 if (ask_me_yes_or_no(question)) {
110 fprintf(fout, "%s\n", incoming);
111 }
112 mr_free(question);
113 }
114
115 /*** free memory ***********/
116 mr_free(incoming);
117
118 paranoid_fclose(fout);
119 paranoid_fclose(fin);
120}
121
122/**************************************************************************
123 *ASK_ABOUT_THESE_IMAGEDEVS *
124 **************************************************************************/
125
126
127/**
128 * Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname.
129 * @param bkpinfo The backup information structure. @c tmpdir is the only field used.
130 * @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
131 * @param output_cfg_file Where to put the configuration file extracted.
132 * @param output_mountlist_file Where to put the mountlist file extracted.
133 * @return 0 for success, nonzero for failure.
134 * @ingroup restoreUtilityGroup
135 */
136int
137extract_config_file_from_ramdisk(struct s_bkpinfo *bkpinfo,
138 char *ramdisk_fname,
139 char *output_cfg_file,
140 char *output_mountlist_file)
141{
142 char *mountpt = NULL;
143 char *command = NULL;
144 char *orig_fname = NULL;
145 int retval = 0;
146
147 assert(bkpinfo != NULL);
148 assert_string_is_neither_NULL_nor_zerolength(ramdisk_fname);
149 assert_string_is_neither_NULL_nor_zerolength(output_cfg_file);
150 assert_string_is_neither_NULL_nor_zerolength(output_mountlist_file);
151 mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
152 mr_asprintf(&command, "mkdir -p %s", mountpt);
153 run_program_and_log_output(command, FALSE);
154 mr_free(command);
155
156 mr_asprintf(&command, "gzip -dc %s > %s/mindi.rd 2> /dev/null",
157 ramdisk_fname, bkpinfo->tmpdir);
158 run_program_and_log_output(command, FALSE);
159 mr_free(command);
160
161 mr_asprintf(&command, "umount %s", mountpt);
162 run_program_and_log_output(command, FALSE);
163 mr_free(command);
164
165 mr_asprintf(&command, "mount -o loop %s/mindi.rd -t ext2 %s",
166 bkpinfo->tmpdir, mountpt);
167 run_program_and_log_output(command, FALSE);
168 mr_free(command);
169
170 mr_asprintf(&command, "mkdir -p %s/tmp", bkpinfo->tmpdir);
171 run_program_and_log_output(command, FALSE);
172 mr_free(command);
173
174 mr_asprintf(&command, "cp -f %s/%s %s", // %s/%s becomes {mountpt}/tmp/m*ndo-restore.cfg
175 mountpt, g_mondo_cfg_file, output_cfg_file);
176 run_program_and_log_output(command, FALSE);
177 mr_free(command);
178
179 mr_asprintf(&orig_fname, "%s/%s", mountpt, g_mountlist_fname);
180 if (does_file_exist(orig_fname)) {
181 mr_asprintf(&command, "cp -f %s %s", orig_fname, output_mountlist_file);
182 run_program_and_log_output(command, FALSE);
183 mr_free(command);
184 }
185 mr_asprintf(&command, "umount %s", mountpt);
186 mr_free(mountpt);
187
188 run_program_and_log_output(command, FALSE);
189 mr_free(command);
190
191 if (!does_file_exist(output_cfg_file)
192 || (!does_file_exist(output_mountlist_file)
193 && does_file_exist(orig_fname))) {
194 mr_msg(2, "Failed to extract %s and/or %s from ramdisk",
195 output_cfg_file, output_mountlist_file);
196 retval = 1;
197 } else {
198 retval = 0;
199 }
200 mr_free(orig_fname);
201 return (retval);
202}
203
204
205/**
206 * Keep trying to get mondo-restore.cfg from the archive, until the user gives up.
207 * @param bkpinfo The backup information structure.
208 */
209void get_cfg_file_from_archive_or_bust(struct s_bkpinfo *bkpinfo)
210{
211 while (get_cfg_file_from_archive(bkpinfo)) {
212 if (!ask_me_yes_or_no
213 (_
214 ("Failed to find config file/archives. Choose another source?")))
215 {
216 fatal_error("Could not find config file/archives. Aborting.");
217 }
218 interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
219 }
220}
221
222
223/**
224 * Determine whether @p list_fname contains a line containing @p f.
225 * @param f The line to search for.
226 * @param list_fname The file to search in.
227 * @param preamble Ignore this beginning part of @p f ("" to disable).
228 * @return TRUE if it's in the list, FALSE if it's not.
229 */
230bool is_file_in_list(char *f, char *list_fname, char *preamble)
231{
232
233 /** needs malloc **/
234 char *command = NULL;
235 char *file = NULL;
236 char *tmp = NULL;
237 int res = 0;
238
239 assert_string_is_neither_NULL_nor_zerolength(f);
240 assert_string_is_neither_NULL_nor_zerolength(list_fname);
241 assert(preamble != NULL);
242
243 if (strncmp(preamble, f, strlen(preamble)) == 0) {
244 mr_asprintf(&file, f + strlen(preamble));
245 } else {
246 mr_asprintf(&file, f);
247 }
248 if (file[0] == '/' && file[1] == '/') {
249 mr_asprintf(&tmp, file);
250 mr_free(file);
251 mr_asprintf(&file, tmp + 1);
252 mr_free(tmp);
253 }
254 mr_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles",
255 f, file);
256 mr_asprintf(&command, "grep -E '^%s$' %s", file, list_fname);
257 mr_free(file);
258
259 res = run_program_and_log_output(command, FALSE);
260 mr_free(command);
261 if (res) {
262 return (FALSE);
263 } else {
264 return (TRUE);
265 }
266}
267/**************************************************************************
268 *END_IS_FILE_IN_LIST *
269 **************************************************************************/
270
271
272/**
273 * Set up an ISO backup.
274 * @param bkpinfo The backup information structure. Fields used:
275 * - @c bkpinfo->backup_media_type
276 * - @c bkpinfo->disaster_recovery
277 * - @c bkpinfo->isodir
278 * @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
279 * @return 0 for success, nonzero for failure.
280 */
281int iso_fiddly_bits(struct s_bkpinfo *bkpinfo, bool nuke_me_please)
282{
283 char *mount_isodir_command = NULL;
284 char *command = NULL;
285 int retval = 0, i = 0;
286 bool already_mounted = FALSE;
287
288 assert(bkpinfo != NULL);
289
290 g_ISO_restore_mode = TRUE;
291 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
292 if (bkpinfo->disaster_recovery) {
293 /* Patch Conor Daly 26-june-2004
294 * Don't let this clobber an existing bkpinfo->isodir */
295 if (!bkpinfo->isodir) {
296 mr_allocstr(bkpinfo->isodir, "/tmp/isodir");
297 }
298/* End patch */
299 mr_asprintf(&command, "mkdir -p %s", bkpinfo->isodir);
300 run_program_and_log_output(command, 5);
301 mr_free(command);
302 mr_msg(2, "Setting isodir to %s", bkpinfo->isodir);
303 }
304
305 if (!get_isodir_info
306 (g_isodir_device, g_isodir_format, bkpinfo->isodir,
307 nuke_me_please)) {
308 return (1);
309 }
310 paranoid_system("umount " MNT_CDROM " 2> /dev/null"); /* just in case */
311
312 if (is_this_device_mounted(g_isodir_device)) {
313 log_to_screen(_("WARNING - isodir is already mounted"));
314 already_mounted = TRUE;
315 } else {
316 if (strlen(g_isodir_format) > 1) {
317 mr_asprintf(&mount_isodir_command, "mount %s -t %s -o ro %s", g_isodir_device, g_isodir_format, bkpinfo->isodir);
318 } else {
319 mr_asprintf(&mount_isodir_command, "mount %s -o ro %s", g_isodir_device, bkpinfo->isodir);
320 }
321 run_program_and_log_output("df -m", FALSE);
322 mr_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?",
323 mount_isodir_command);
324 if (run_program_and_log_output(mount_isodir_command, FALSE)) {
325 popup_and_OK
326 (_
327 ("Cannot mount the device where the ISO files are stored."));
328 mr_free(mount_isodir_command);
329 return (1);
330 }
331 mr_free(mount_isodir_command);
332 log_to_screen
333 (_
334 ("I have mounted the device where the ISO files are stored."));
335 }
336 if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
337 mount_cdrom(bkpinfo);
338 }
339 i = what_number_cd_is_this(bkpinfo); /* has the side-effect of calling mount_cdrom() */
340 mr_msg(1, "%s #%d has been mounted via loopback mount",
341 bkpinfo->backup_media_string, i);
342 if (i < 0) {
343 popup_and_OK
344 (_("Cannot find ISO images in the directory you specified."));
345 retval = 1;
346 }
347 mr_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__,
348 bkpinfo->isodir);
349 return (retval);
350}
351
352
353/**
354 * Kill all Petris processes.
355 */
356void kill_petris(void)
357{
358 char *command = NULL;
359 mr_asprintf(&command,
360 "kill `ps 2> /dev/null | grep petris 2> /dev/null | grep -v grep | cut -d' ' -f2` 2> /dev/null");
361 paranoid_system(command);
362 mr_free(command);
363}
364
365/**************************************************************************
366 *END_KILL_PETRIS *
367 **************************************************************************/
368
369/**
370 * Mount @p device at @p mpt as @p format.
371 * @param device The device (/dev entry) to mount.
372 * @param mpt The directory to mount it on.
373 * @param format The filesystem type of @p device.
374 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
375 * @return 0 for success, nonzero for failure.
376 */
377int mount_device(char *device, char *mpt, char *format, bool writeable)
378{
379 int res = 0;
380
381 char *command = NULL;
382 char *mountdir = NULL;
383 char *mountpoint = NULL;
384 char *additional_parameters = NULL;
385
386 assert_string_is_neither_NULL_nor_zerolength(device);
387 assert_string_is_neither_NULL_nor_zerolength(mpt);
388 assert(format != NULL);
389
390 if (!strcmp(mpt, "/1")) {
391 mr_asprintf(&mountpoint, "/");
392 mr_msg(3, "Mommm! SME is being a dildo!");
393 } else {
394 mr_asprintf(&mountpoint, mpt);
395 }
396
397 if (!strcmp(mountpoint, "lvm")) {
398 mr_free(mountpoint);
399 return (0);
400 }
401 if (!strcmp(mountpoint, "image")) {
402 mr_free(mountpoint);
403 return (0);
404 }
405 mr_msg(1, "Mounting device %s ", device);
406 if (writeable) {
407 mr_asprintf(&additional_parameters, "-o rw");
408 } else {
409 mr_asprintf(&additional_parameters, "-o ro");
410 }
411 if (find_home_of_exe("setfattr")) {
412 mr_strcat(additional_parameters, ",user_xattr");
413 }
414 if (find_home_of_exe("setfacl")) {
415 mr_strcat(additional_parameters, ",acl");
416 }
417
418 if (!strcmp(mountpoint, "swap")) {
419 mr_asprintf(&command, "swapon %s", device);
420 } else {
421 if (!strcmp(mountpoint, "/")) {
422 mr_asprintf(&mountdir, MNT_RESTORING);
423 } else {
424 mr_asprintf(&mountdir, "%s%s", MNT_RESTORING, mountpoint);
425 }
426 mr_asprintf(&command, "mkdir -p %s", mountdir);
427 run_program_and_log_output(command, FALSE);
428 mr_free(command);
429
430 mr_asprintf(&command, "mount -t %s %s %s %s 2>> %s", format, device,
431 additional_parameters, mountdir, MONDO_LOGFILE);
432 mr_msg(2, "command='%s'", command);
433 }
434 mr_free(additional_parameters);
435
436 res = run_program_and_log_output(command, TRUE);
437 if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
438 mr_msg(1, "Re-trying without the fancy extra parameters");
439 mr_free(command);
440
441 mr_asprintf(&command, "mount -t %s %s %s 2>> %s", format, device,
442 mountdir, MONDO_LOGFILE);
443 res = run_program_and_log_output(command, TRUE);
444 }
445 if (res) {
446 mr_msg(1, "Unable to mount device %s (type %s) at %s", device,
447 format, mountdir);
448 mr_msg(1, "command was '%s'", command);
449 if (!strcmp(mountpoint, "swap")) {
450 log_to_screen("Unable to mount device %s (type %s) at %s", device,
451 format, mountdir);
452 } else {
453 mr_msg(2, "Retrying w/o the '-t' switch");
454 mr_free(command);
455
456 mr_asprintf(&command, "mount %s %s 2>> %s", device, mountdir,
457 MONDO_LOGFILE);
458 mr_msg(2, "2nd command = '%s'", command);
459 res = run_program_and_log_output(command, TRUE);
460 if (res == 0) {
461 mr_msg(1,
462 "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
463 }
464 }
465 }
466 mr_free(command);
467 mr_free(mountdir);
468
469 if (res && !strcmp(mountpoint, "swap")) {
470 mr_msg(2, "That's ok. It's just a swap partition.");
471 mr_msg(2, "Non-fatal error. Returning 0.");
472 res = 0;
473 }
474 mr_free(mountpoint);
475
476 return (res);
477}
478/**************************************************************************
479 *END_MOUNT_DEVICE *
480 **************************************************************************/
481
482
483/**
484 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
485 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
486 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
487 * @return The number of errors encountered (0 for success).
488 */
489int mount_all_devices(struct mountlist_itself
490 *p_external_copy_of_mountlist, bool writeable)
491{
492 int retval = 0;
493 int lino = 0;
494 int res = 0;
495 char *tmp = NULL;
496 char *these_failed = NULL;
497 char *format = NULL;
498 struct mountlist_itself *mountlist = NULL;
499
500 assert(p_external_copy_of_mountlist != NULL);
501 mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
502 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
503 sizeof(struct mountlist_itself));
504 sort_mountlist_by_mountpoint(mountlist, 0);
505
506 mvaddstr_and_log_it(g_currentY, 0, _("Mounting devices "));
507 open_progress_form(_("Mounting devices"),
508 _("I am now mounting all the drives."),
509 _("This should not take long."),
510 "", mountlist->entries);
511
512 for (lino = 0; lino < mountlist->entries; lino++) {
513 if (!strcmp(mountlist->el[lino].device, "/proc")) {
514 mr_msg(1,
515 "Again with the /proc - why is this in your mountlist?");
516 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
517 log_to_screen(_("%s is already mounted"),
518 mountlist->el[lino].device);
519 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
520 && strcmp(mountlist->el[lino].mountpoint, "lvm")
521 && strcmp(mountlist->el[lino].mountpoint, "raid")
522 && strcmp(mountlist->el[lino].mountpoint, "image")) {
523 mr_asprintf(&tmp, "Mounting %s", mountlist->el[lino].device);
524 update_progress_form(tmp);
525 mr_free(tmp);
526
527 mr_asprintf(&format, mountlist->el[lino].format);
528 if (!strcmp(format, "ext3")) {
529 mr_free(format);
530 mr_asprintf(&format, "ext2");
531 }
532 res = mount_device(mountlist->el[lino].device,
533 mountlist->el[lino].mountpoint,
534 format, writeable);
535 retval += res;
536 if (res) {
537 if (these_failed != NULL) { /* not the first time */
538 mr_strcat(these_failed, " %s", mountlist->el[lino].device);
539 } else { /* The first time */
540 mr_asprintf(&these_failed, "%s", mountlist->el[lino].device);
541 }
542 }
543 mr_free(format);
544 }
545 g_current_progress++;
546 }
547 close_progress_form();
548 run_program_and_log_output("df -m", TRUE);
549 if (retval) {
550 if (g_partition_table_locked_up > 0) {
551 log_to_screen
552 (_
553 ("fdisk's ioctl() call to refresh its copy of the partition table causes the kernel to"));
554 log_to_screen(_
555 ("lock up the partition table. You might have to reboot and use Interactive Mode to"));
556 log_to_screen(_
557 ("format and restore *without* partitioning first. Sorry for the inconvenience."));
558 }
559 mr_asprintf(&tmp, _("Could not mount devices %s- shall I abort?"),
560 these_failed);
561 mr_free(these_failed);
562
563 if (!ask_me_yes_or_no(tmp)) {
564 retval = 0;
565 log_to_screen
566 (_
567 ("Continuing, although some devices failed to be mounted"));
568 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
569 } else {
570 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
571 log_to_screen
572 (_("Unable to mount some or all of your partitions."));
573 }
574 mr_free(tmp);
575 } else {
576 log_to_screen(_("All partitions were mounted OK."));
577 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
578 }
579 run_program_and_log_output("df -m", 3);
580 mr_free(mountlist);
581 return (retval);
582}
583 /**************************************************************************
584 *END_MOUNT_ALL_DEVICES *
585 **************************************************************************/
586
587
588/**
589 * Mount the CD-ROM device at /mnt/cdrom.
590 * @param bkpinfo The backup information structure. Fields used:
591 * - @c bkpinfo->backup_media_type
592 * - @c bkpinfo->disaster_recovery
593 * - @c bkpinfo->isodir
594 * - @c bkpinfo->media_device
595 * @return 0 for success, nonzero for failure.
596 */
597int mount_cdrom(struct s_bkpinfo *bkpinfo)
598{
599 char *mount_cmd = NULL;
600 int i = 0, res = 0;
601#ifdef __FreeBSD__
602 char *mddev = NULL;
603#endif
604
605 assert(bkpinfo != NULL);
606
607 if (bkpinfo->backup_media_type == tape
608 || bkpinfo->backup_media_type == udev) {
609 mr_msg(8, "Tape/udev. Therefore, no need to mount CDROM.");
610 return 0;
611 }
612
613 if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
614 mr_msg(2, "mount_cdrom() - CD already mounted. Fair enough.");
615 return (0);
616 }
617
618 if (bkpinfo->backup_media_type == nfs) {
619 mr_msg(2, "Mounting for NFS thingy");
620 mr_msg(2, "isodir = %s", bkpinfo->isodir);
621 if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
622 && am_I_in_disaster_recovery_mode()) {
623 strcpy(bkpinfo->isodir, "/tmp/isodir");
624 mr_msg(1, "isodir is being set to %s", bkpinfo->isodir);
625 }
626#ifdef __FreeBSD__
627 mr_asprintf(&mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
628 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
629 g_current_media_number);
630 mddev = make_vn(mount_cmd);
631 mr_free(mount_cmd);
632
633 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
634 mr_free(mddev);
635#else
636 mr_asprintf(&mount_cmd,
637 "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
638 bkpinfo->isodir, bkpinfo->nfs_remote_dir, bkpinfo->prefix,
639 g_current_media_number, MNT_CDROM);
640#endif
641
642 } else if (bkpinfo->backup_media_type == iso) {
643#ifdef __FreeBSD__
644 mr_asprintf(&mount_cmd, "%s/%s-%d.iso", bkpinfo->isodir,
645 bkpinfo->prefix, g_current_media_number);
646 mddev = make_vn(mount_cmd);
647 mr_free(mount_cmd);
648
649 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
650 mr_free(mddev);
651#else
652 mr_asprintf(&mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
653 bkpinfo->isodir, bkpinfo->prefix, g_current_media_number,
654 MNT_CDROM);
655#endif
656 } else if (strstr(bkpinfo->media_device, "/dev/"))
657#ifdef __FreeBSD__
658 {
659 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
660 MNT_CDROM);
661 }
662#else
663 {
664 mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
665 bkpinfo->media_device, MNT_CDROM);
666 }
667#endif
668
669 else {
670 if (bkpinfo->disaster_recovery
671 && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
672 strcpy(bkpinfo->media_device,
673 last_line_of_file("/tmp/CDROM-LIVES-HERE"));
674 } else {
675 find_cdrom_device(bkpinfo->media_device, TRUE);
676 }
677
678#ifdef __FreeBSD__
679 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
680 MNT_CDROM);
681#else
682 mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
683 bkpinfo->media_device, MNT_CDROM);
684#endif
685
686 }
687 mr_msg(2, "(mount_cdrom) --- command = %s", mount_cmd);
688 for (i = 0; i < 2; i++) {
689 res = run_program_and_log_output(mount_cmd, FALSE);
690 if (!res) {
691 break;
692 } else {
693 mr_msg(2, "Failed to mount CD-ROM drive.");
694 sleep(5);
695 run_program_and_log_output("sync", FALSE);
696 }
697 }
698 mr_free(mount_cmd);
699
700 if (res) {
701 mr_msg(2, "Failed, despite %d attempts", i);
702 } else {
703 mr_msg(2, "Mounted CD-ROM drive OK");
704 }
705 return (res);
706}
707/**************************************************************************
708 *END_MOUNT_CDROM *
709 **************************************************************************/
710
711
712/**
713 * Fix some miscellaneous things in the filesystem so the system will come
714 * up correctly on the first boot.
715 */
716void protect_against_braindead_sysadmins()
717{
718 run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
719 FALSE);
720 run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
721 FALSE);
722 if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
723 run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
724 FALSE);
725 }
726 run_program_and_log_output("mkdir -p " MNT_RESTORING
727 "/var/run/console", FALSE);
728 run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
729 FALSE);
730 run_program_and_log_output("cd " MNT_RESTORING
731 "; 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",
732 TRUE);
733 run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
734 TRUE);
735 run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
736 TRUE);
737}
738/**************************************************************************
739 *END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS *
740 **************************************************************************/
741
742
743/**
744 * Fill out @p bkpinfo based on @p cfg_file.
745 * @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo.
746 * @param bkpinfo The backup information structure to fill out with information
747 * from @p cfg_file.
748 * @return 0 for success, nonzero for failure.
749 */
750int read_cfg_file_into_bkpinfo(char *cfgf, struct s_bkpinfo *bkpinfo)
751{
752 char *value = NULL;
753 char *tmp = NULL;
754 char *envtmp1 = NULL;
755 char *envtmp2 = NULL;
756 char *command = NULL;
757 char *iso_mnt = NULL;
758 char *iso_path = NULL;
759 char *old_isodir = NULL;
760 char *cfg_file = NULL;
761 t_bkptype media_specified_by_user;
762
763 malloc_string(value);
764 assert(bkpinfo != NULL);
765
766 if (!cfgf) {
767 cfg_file = g_mondo_cfg_file;
768 } else {
769 cfg_file = cfgf;
770 }
771
772 media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
773
774 if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
775 if (!strcmp(value, "cdstream")) {
776 bkpinfo->backup_media_type = cdstream;
777 } else if (!strcmp(value, "cdr")) {
778 bkpinfo->backup_media_type = cdr;
779 } else if (!strcmp(value, "cdrw")) {
780 bkpinfo->backup_media_type = cdrw;
781 } else if (!strcmp(value, "dvd")) {
782 bkpinfo->backup_media_type = dvd;
783 } else if (!strcmp(value, "iso")) {
784 // Patch by Conor Daly - 2004/07/12
785 bkpinfo->backup_media_type = iso;
786 if (am_I_in_disaster_recovery_mode()) {
787 /* Check to see if CD is already mounted before mounting it... */
788 if (!is_this_device_mounted("/dev/cdrom")) {
789 mr_msg(2,
790 "NB: CDROM device not mounted, mounting...");
791 run_program_and_log_output("mount /dev/cdrom "
792 MNT_CDROM, 1);
793 }
794 if (does_file_exist(MNT_CDROM "/archives/filelist.0")) {
795 bkpinfo->backup_media_type = cdr;
796 run_program_and_log_output("umount " MNT_CDROM, 1);
797 log_it
798 ("Re-jigging configuration AGAIN. CD-R, not ISO.");
799 }
800 }
801 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
802 strcpy(bkpinfo->prefix,value);
803 } else {
804 strcpy(bkpinfo->prefix,STD_PREFIX);
805 }
806 } else if (!strcmp(value, "nfs")) {
807 bkpinfo->backup_media_type = nfs;
808 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
809 strcpy(bkpinfo->prefix,value);
810 } else {
811 strcpy(bkpinfo->prefix,STD_PREFIX);
812 }
813 if (strstr(call_program_and_get_last_line_of_output
814 ("cat /proc/cmdline"), "pxe")) {
815 /* We need to override prefix value in PXE mode as it's
816 * already done in start-nfs */
817 envtmp1 = getenv("imgname");
818 if (envtmp1 == NULL) {
819 fatal_error("no imgname variable in environment");
820 }
821 strcpy(bkpinfo->prefix,envtmp1);
822 }
823
824 } else if (!strcmp(value, "tape")) {
825 bkpinfo->backup_media_type = tape;
826 } else if (!strcmp(value, "udev")) {
827 bkpinfo->backup_media_type = udev;
828 } else {
829 fatal_error("UNKNOWN bkp-media-type");
830 }
831 } else {
832 fatal_error("backup-media-type not specified!");
833 }
834 if (bkpinfo->disaster_recovery) {
835 if (bkpinfo->backup_media_type == cdstream) {
836 strcpy(bkpinfo->media_device, "/dev/cdrom");
837 bkpinfo->media_size[0] = 1999 * 1024;
838 bkpinfo->media_size[1] = 650; /* good guess */
839 } else if (bkpinfo->backup_media_type == tape
840 || bkpinfo->backup_media_type == udev) {
841 if (read_cfg_var(cfg_file, "media-dev", value)) {
842 fatal_error("Cannot get tape device name from cfg file");
843 }
844 strcpy(bkpinfo->media_device, value);
845 read_cfg_var(cfg_file, "media-size", value);
846 bkpinfo->media_size[1] = atol(value);
847 mr_msg(2, "Backup medium is TAPE --- dev=%s",
848 bkpinfo->media_device);
849 } else {
850 strcpy(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
851 bkpinfo->media_size[0] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
852 bkpinfo->media_size[1] = 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 strcpy(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
1362 if (find_home_of_exe("pico")) {
1363 strcpy(output, "pico");
1364 } else if (find_home_of_exe("nano")) {
1365 strcpy(output, "nano");
1366 } else if (find_home_of_exe("e3em")) {
1367 strcpy(output, "e3em");
1368 } else if (find_home_of_exe("e3vi")) {
1369 strcpy(output, "e3vi");
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 _
1408 ("Modifying fstab and grub.conf, and running GRUB... "));
1409 for (done = FALSE; !done;) {
1410 popup_and_get_string(_("Boot device"),
1411 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), boot_device, MAX_STR_LEN / 4);
1412 mr_asprintf(&command, "stabgrub-me %s", boot_device);
1413 res = run_program_and_log_output(command, 1);
1414 mr_free(command);
1415
1416 if (res) {
1417 popup_and_OK
1418 (_
1419 ("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."));
1420 newtSuspend();
1421 system("chroot " MNT_RESTORING);
1422 newtResume();
1423 popup_and_OK(_("Thank you."));
1424 } else {
1425 done = TRUE;
1426 }
1427 popup_and_OK(_("You will now edit fstab and grub.conf"));
1428 if (!g_text_mode) {
1429 newtSuspend();
1430 }
1431 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1432 paranoid_system(tmp);
1433 mr_free(tmp);
1434
1435 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/grub.conf", editor);
1436 paranoid_system(tmp);
1437 mr_free(tmp);
1438
1439 if (!g_text_mode) {
1440 newtResume();
1441 }
1442 }
1443 } else {
1444 /* nuke mode */
1445 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1446 mr_msg(1, "Yay! grub-MR found...");
1447 mr_asprintf(&command, "grub-MR %s /tmp/mountlist.txt", bd);
1448 mr_msg(1, "command = %s", command);
1449 } else {
1450 mr_asprintf(&command, "chroot " MNT_RESTORING " grub-install %s", bd);
1451 mr_msg(1, "WARNING - grub-MR not found; using grub-install");
1452 }
1453 mvaddstr_and_log_it(g_currentY,
1454 0,
1455 _
1456 ("Running GRUB... "));
1457 iamhere(command);
1458 res = run_program_and_log_output(command, 1);
1459 mr_free(command);
1460
1461 if (res) {
1462 popup_and_OK
1463 (_
1464 ("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."));
1465 newtSuspend();
1466 system("chroot " MNT_RESTORING);
1467 newtResume();
1468 popup_and_OK(_("Thank you."));
1469 }
1470 }
1471 if (res) {
1472 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1473 log_to_screen
1474 (_
1475 ("GRUB ran w/error(s). See /tmp/mondo-restore.log for more info."));
1476 mr_msg(1, "Type:-");
1477 mr_msg(1, " mount-me");
1478 mr_msg(1, " chroot " MNT_RESTORING);
1479 mr_msg(1, " mount /boot");
1480 mr_msg(1, " grub-install '(hd0)'");
1481 mr_msg(1, " exit");
1482 mr_msg(1, " unmount-me");
1483 mr_msg(1,
1484 "If you're really stuck, please e-mail the mailing list.");
1485 } else {
1486 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1487 }
1488 mr_free(boot_device);
1489 mr_free(editor);
1490 return (res);
1491}
1492/**************************************************************************
1493 *END_RUN_GRUB *
1494 **************************************************************************/
1495
1496
1497/**
1498 * Install ELILO on the user's boot drive (determined by elilo.conf).
1499 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1500 * @return 0 for success, nonzero for failure.
1501 */
1502int run_elilo(bool offer_to_run_stabelilo)
1503{
1504 char *command = NULL;
1505 char *tmp = NULL;
1506 char *editor = NULL;
1507
1508 int res = 0;
1509 int done = 0;
1510
1511 mr_asprintf(&editor, find_my_editor());
1512 if (offer_to_run_stabelilo
1513 && ask_me_yes_or_no(_("Did you change the mountlist?")))
1514
1515 /* interactive mode */
1516 {
1517 mvaddstr_and_log_it(g_currentY,
1518 0,
1519 _
1520 ("Modifying fstab and elilo.conf... "));
1521 mr_asprintf(&command, "stabelilo-me");
1522 res = run_program_and_log_output(command, 3);
1523 mr_free(command);
1524
1525 if (res) {
1526 popup_and_OK
1527 (_
1528 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist."));
1529 for (done = FALSE; !done;) {
1530 if (!g_text_mode) {
1531 newtSuspend();
1532 }
1533 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1534 paranoid_system(tmp);
1535 mr_free(tmp);
1536
1537 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/elilo.conf", editor);
1538 paranoid_system(tmp);
1539 mr_free(tmp);
1540
1541 if (!g_text_mode) {
1542 newtResume();
1543 }
1544// newtCls();
1545 if (ask_me_yes_or_no(_("Edit them again?"))) {
1546 continue;
1547 }
1548 done = TRUE;
1549 }
1550 } else {
1551 log_to_screen(_("elilo.conf and fstab were modified OK"));
1552 }
1553 } else
1554 /* nuke mode */
1555 {
1556 res = TRUE;
1557 }
1558 mr_free(editor);
1559 return (res);
1560}
1561/**************************************************************************
1562 *END_RUN_ELILO *
1563 **************************************************************************/
1564
1565
1566/**
1567 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1568 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1569 * @return 0 for success, nonzero for failure.
1570 */
1571int run_lilo(bool offer_to_run_stablilo)
1572{
1573 /** malloc **/
1574 char *command = NULL;
1575 char *tmp = NULL;
1576 char *editor = NULL;
1577
1578 int res = 0;
1579 int done = 0;
1580 bool run_lilo_M = FALSE;
1581
1582 if (!run_program_and_log_output
1583 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1584 run_lilo_M = TRUE;
1585 }
1586
1587 mr_asprintf(&editor, find_my_editor());
1588 if (offer_to_run_stablilo
1589 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1590 /* interactive mode */
1591 mvaddstr_and_log_it(g_currentY,
1592 0,
1593 _
1594 ("Modifying fstab and lilo.conf, and running LILO... "));
1595 mr_asprintf(&command, "stablilo-me");
1596 res = run_program_and_log_output(command, 3);
1597 mr_free(command);
1598
1599 if (res) {
1600 popup_and_OK
1601 (_
1602 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."));
1603 for (done = FALSE; !done;) {
1604 if (!g_text_mode) {
1605 newtSuspend();
1606 }
1607 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1608 paranoid_system(tmp);
1609 mr_free(tmp);
1610
1611 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1612 paranoid_system(tmp);
1613 mr_free(tmp);
1614
1615 if (!g_text_mode) {
1616 newtResume();
1617 }
1618 if (ask_me_yes_or_no(_("Edit them again?"))) {
1619 continue;
1620 }
1621 res =
1622 run_program_and_log_output("chroot " MNT_RESTORING
1623 " lilo -L", 3);
1624 if (res) {
1625 res =
1626 run_program_and_log_output("chroot " MNT_RESTORING
1627 " lilo", 3);
1628 }
1629 if (res) {
1630 done =
1631 ask_me_yes_or_no
1632 (_("LILO failed. Re-edit system files?"));
1633 } else {
1634 done = TRUE;
1635 }
1636 }
1637 } else {
1638 log_to_screen(_("lilo.conf and fstab were modified OK"));
1639 }
1640 } else {
1641 /* nuke mode */
1642 mvaddstr_and_log_it(g_currentY,
1643 0,
1644 _
1645 ("Running LILO... "));
1646 res =
1647 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1648 3);
1649 if (res) {
1650 res =
1651 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1652 3);
1653 }
1654 if (res) {
1655 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1656 log_to_screen
1657 (_
1658 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."));
1659 } else {
1660 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1661 }
1662 }
1663 if (run_lilo_M) {
1664 run_program_and_log_output("chroot " MNT_RESTORING
1665 " lilo -M /dev/hda", 3);
1666 run_program_and_log_output("chroot " MNT_RESTORING
1667 " lilo -M /dev/sda", 3);
1668 }
1669 mr_free(editor);
1670 return (res);
1671}
1672
1673/**************************************************************************
1674 *END_RUN_LILO *
1675 **************************************************************************/
1676
1677
1678/**
1679 * Install a raw MBR onto @p bd.
1680 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1681 * @param bd The device to copy the stored MBR to.
1682 * @return 0 for success, nonzero for failure.
1683 */
1684int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1685{
1686 char *command = NULL;
1687 char *boot_device = NULL;
1688 char *tmp = NULL;
1689 char *editor = NULL;
1690 int res = 0;
1691 int done = 0;
1692
1693 assert_string_is_neither_NULL_nor_zerolength(bd);
1694
1695 malloc_string(boot_device);
1696 mr_asprintf(&editor, find_my_editor());
1697 strcpy(boot_device, bd);
1698 if (offer_to_hack_scripts
1699 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1700 /* interactive mode */
1701 mvaddstr_and_log_it(g_currentY, 0,
1702 _
1703 ("Modifying fstab and restoring MBR... "));
1704 for (done = FALSE; !done;) {
1705 if (!run_program_and_log_output("which vi", FALSE)) {
1706 popup_and_OK(_("You will now edit fstab"));
1707 if (!g_text_mode) {
1708 newtSuspend();
1709 }
1710 mr_asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1711 paranoid_system(tmp);
1712 mr_free(tmp);
1713
1714 if (!g_text_mode) {
1715 newtResume();
1716 }
1717 }
1718 popup_and_get_string(_("Boot device"),
1719 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), boot_device, MAX_STR_LEN / 4);
1720 mr_asprintf(&command, "stabraw-me %s", boot_device);
1721 res = run_program_and_log_output(command, 3);
1722 mr_free(command);
1723
1724 if (res) {
1725 done =
1726 ask_me_yes_or_no(_("Modifications failed. Re-try?"));
1727 } else {
1728 done = TRUE;
1729 }
1730 }
1731 } else {
1732 /* nuke mode */
1733 mvaddstr_and_log_it(g_currentY, 0,
1734 _("Restoring MBR... "));
1735 mr_asprintf(&command, "raw-MR %s /tmp/mountlist.txt", boot_device);
1736 mr_msg(2, "run_raw_mbr() --- command='%s'", command);
1737 res = run_program_and_log_output(command, 3);
1738 mr_free(command);
1739 }
1740 if (res) {
1741 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1742 log_to_screen
1743 (_
1744 ("MBR+fstab processed w/error(s). See /tmp/mondo-restore.log for more info."));
1745 } else {
1746 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1747 }
1748 mr_free(boot_device);
1749 mr_free(editor);
1750 return (res);
1751}
1752/**************************************************************************
1753 *END_RUN_RAW_MBR *
1754 **************************************************************************/
1755
1756
1757/**
1758 * Turn signal trapping on or off.
1759 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1760 * print a message and exit immediately.
1761 */
1762void set_signals(int on)
1763{
1764 int signals[] =
1765 { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1766 SIGSTOP, 0
1767 };
1768 int i;
1769 for (i = 0; signals[i]; i++) {
1770 if (on) {
1771 signal(signals[i], terminate_daemon);
1772 } else {
1773 signal(signals[i], termination_in_progress);
1774 }
1775 }
1776}
1777
1778/**************************************************************************
1779 *END_SET_SIGNALS *
1780 **************************************************************************/
1781
1782
1783/**
1784 * malloc() and set sensible defaults for the mondorestore filename variables.
1785 * @param bkpinfo The backup information structure. Fields used:
1786 * - @c bkpinfo->tmpdir
1787 * - @c bkpinfo->disaster_recovery
1788 */
1789void setup_MR_global_filenames(struct s_bkpinfo *bkpinfo)
1790{
1791 char *temppath;
1792
1793 assert(bkpinfo != NULL);
1794
1795 malloc_string(g_biggielist_txt);
1796 malloc_string(g_filelist_full);
1797 malloc_string(g_filelist_imagedevs);
1798 malloc_string(g_imagedevs_restthese);
1799 malloc_string(g_mondo_cfg_file);
1800 malloc_string(g_mountlist_fname);
1801 malloc_string(g_tmpfs_mountpt);
1802 malloc_string(g_isodir_device);
1803 malloc_string(g_isodir_format);
1804
1805 temppath = bkpinfo->tmpdir;
1806
1807 sprintf(g_biggielist_txt, "%s/%s", temppath, BIGGIELIST_TXT_STUB);
1808 sprintf(g_filelist_full, "%s/%s", temppath, FILELIST_FULL_STUB);
1809 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", temppath);
1810 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1811 temppath);
1812 if (bkpinfo->disaster_recovery) {
1813 sprintf(g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1814 sprintf(g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1815 } else {
1816 sprintf(g_mondo_cfg_file, "%s/%s", temppath, MONDO_CFG_FILE_STUB);
1817 sprintf(g_mountlist_fname, "%s/%s", temppath,
1818 MOUNTLIST_FNAME_STUB);
1819 }
1820}
1821
1822/**************************************************************************
1823 *END_SET_GLOBAL_FILENAME *
1824 **************************************************************************/
1825
1826
1827/**
1828 * Copy @p input_file (containing the result of a compare) to @p output_file,
1829 * deleting spurious "changes" along the way.
1830 * @param output_file The output file to write with spurious changes removed.
1831 * @param input_file The input file, a list of changed files created by a compare.
1832 */
1833void streamline_changes_file(char *output_file, char *input_file)
1834{
1835 FILE *fin;
1836 FILE *fout;
1837 char *incoming = NULL;
1838 size_t n = 0;
1839
1840 assert_string_is_neither_NULL_nor_zerolength(output_file);
1841 assert_string_is_neither_NULL_nor_zerolength(input_file);
1842
1843 if (!(fin = fopen(input_file, "r"))) {
1844 log_OS_error(input_file);
1845 return;
1846 }
1847 if (!(fout = fopen(output_file, "w"))) {
1848 fatal_error("cannot open output_file");
1849 }
1850 for (mr_getline(&incoming, &n, fin); !feof(fin);
1851 mr_getline(&incoming, &n, fin)) {
1852 if (strncmp(incoming, "etc/adjtime", 11)
1853 && strncmp(incoming, "etc/mtab", 8)
1854 && strncmp(incoming, "tmp/", 4)
1855 && strncmp(incoming, "boot/map", 8)
1856 && !strstr(incoming, "incheckentry")
1857 && strncmp(incoming, "etc/mail/statistics", 19)
1858 && strncmp(incoming, "var/", 4))
1859 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1860 }
1861 mr_free(incoming);
1862 paranoid_fclose(fout);
1863 paranoid_fclose(fin);
1864}
1865/**************************************************************************
1866 *END_STREAMLINE_CHANGES_FILE *
1867 **************************************************************************/
1868
1869
1870/**
1871 * Exit due to a signal (normal cleanup).
1872 * @param sig The signal we're exiting due to.
1873 */
1874void terminate_daemon(int sig)
1875{
1876 log_to_screen
1877 (_("Mondorestore is terminating in response to a signal from the OS"));
1878 free_MR_global_filenames();
1879 finish(254);
1880}
1881/**************************************************************************
1882 *END_TERMINATE_DAEMON *
1883 **************************************************************************/
1884
1885
1886/**
1887 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1888 */
1889void twenty_seconds_til_yikes()
1890{
1891 int i;
1892 char *tmp = NULL;
1893
1894 if (does_file_exist("/tmp/NOPAUSE")) {
1895 return;
1896 }
1897 open_progress_form(_("CAUTION"),
1898 _
1899 ("Be advised: I am about to ERASE your hard disk(s)!"),
1900 _("You may press Ctrl+Alt+Del to abort safely."),
1901 "", 20);
1902 for (i = 0; i < 20; i++) {
1903 g_current_progress = i;
1904 mr_asprintf(&tmp, _("You have %d seconds left to abort."), 20 - i);
1905 update_progress_form(tmp);
1906 mr_free(tmp);
1907 sleep(1);
1908 }
1909 close_progress_form();
1910}
1911/**************************************************************************
1912 *END_TWENTY_SECONDS_TIL_YIKES *
1913 **************************************************************************/
1914
1915
1916/**
1917 * Exit due to a signal (no cleanup).
1918 * @param sig The signal we're exiting due to.
1919 */
1920void termination_in_progress(int sig)
1921{
1922 mr_msg(1, "Termination in progress");
1923 usleep(1000);
1924 pthread_exit(0);
1925}
1926/**************************************************************************
1927 *END_TERMINATION_IN_PROGRESS *
1928 **************************************************************************/
1929
1930
1931/**
1932 * Unmount all devices in @p p_external_copy_of_mountlist.
1933 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1934 * @return 0 for success, nonzero for failure.
1935 */
1936int unmount_all_devices(struct mountlist_itself
1937 *p_external_copy_of_mountlist)
1938{
1939 struct mountlist_itself *mountlist;
1940 int retval = 0;
1941 int lino = 0;
1942 int res = 0;
1943 int i = 0;
1944 char *command = NULL;
1945 char *tmp = NULL;
1946
1947 assert(p_external_copy_of_mountlist != NULL);
1948
1949 mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
1950 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1951 sizeof(struct mountlist_itself));
1952 sort_mountlist_by_mountpoint(mountlist, 0);
1953
1954 run_program_and_log_output("df -m", 3);
1955 mvaddstr_and_log_it(g_currentY, 0, _("Unmounting devices "));
1956 open_progress_form(_("Unmounting devices"),
1957 _("Unmounting all devices that were mounted,"),
1958 _
1959 ("in preparation for the post-restoration reboot."),
1960 "", mountlist->entries);
1961 chdir("/");
1962 for (i = 0;
1963 i < 10
1964 &&
1965 run_program_and_log_output
1966 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1967 i++) {
1968 sleep(1);
1969 mr_msg(2, "Waiting for buffer() to finish");
1970 }
1971
1972 sync();
1973
1974 if (run_program_and_log_output
1975 ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/tmp/", FALSE)) {
1976 mr_msg(1,
1977 "Error. Failed to copy log to PC's /tmp dir. (Mounted read-only?)");
1978 }
1979 if (run_program_and_log_output
1980 ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/root/", FALSE)) {
1981 mr_msg(1,
1982 "Error. Failed to copy log to PC's /root 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 floppy, 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 /* Floppy? */
2121 mr_asprintf(&tmp, "mkdir -p %s", mountpt);
2122 run_program_and_log_output(tmp, FALSE);
2123 mr_free(tmp);
2124
2125 mr_asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2126 run_program_and_log_output(tmp, FALSE);
2127 mr_free(tmp);
2128
2129 mr_asprintf(&command, "mount /dev/fd0u1722 %s", mountpt);
2130 mr_asprintf(&tmp,
2131 "(sleep 15; kill `ps | grep \"%s\" | cut -d' ' -f1` 2> /dev/null) &",
2132 command);
2133 mr_msg(1, "tmp = '%s'", tmp);
2134 system(tmp);
2135 mr_free(tmp);
2136
2137 res = run_program_and_log_output(command, FALSE);
2138 mr_free(command);
2139
2140 if (res) {
2141 mr_asprintf(&command, "mount /dev/fd0H1440 %s", mountpt);
2142 res = run_program_and_log_output(command, FALSE);
2143 mr_free(command);
2144 }
2145 if (res) {
2146 try_plan_B = TRUE;
2147 } else {
2148 try_plan_B = TRUE;
2149 mr_msg(2,
2150 "Mounted floppy OK but I don't trust it because the archives might contain more up-to-date config file than the floppy does.");
2151 // NB: If busybox does not support 'mount -o loop' then Plan A WILL NOT WORK.
2152 mr_msg(2, "Processing floppy (plan A?)");
2153 mr_asprintf(&ramdisk_fname, "%s/mindi.rdz", mountpt);
2154 if (!does_file_exist(ramdisk_fname)) {
2155 mr_free(ramdisk_fname);
2156 mr_asprintf(&ramdisk_fname, "%s/initrd.img", mountpt);
2157 }
2158 if (!does_file_exist(ramdisk_fname)) {
2159 mr_msg(2,
2160 "Cannot find ramdisk file on mountpoint. Are you sure that's a boot disk in the drive?");
2161 }
2162 if (extract_config_file_from_ramdisk
2163 (bkpinfo, ramdisk_fname, cfg_file, mountlist_file)) {
2164 mr_msg(2,
2165 "Warning - failed to extract config file from ramdisk. I think this boot disk is mangled.");
2166 }
2167 mr_asprintf(&command, "umount %s", mountpt);
2168 run_program_and_log_output(command, 5);
2169 mr_free(command);
2170
2171 unlink(ramdisk_fname);
2172 mr_free(ramdisk_fname);
2173 }
2174 if (!does_file_exist(cfg_file)) {
2175 mr_msg(2, "gcffa --- we don't have cfg file yet.");
2176 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2177 try_plan_B = TRUE;
2178 } else {
2179 mr_msg(2, "gcffa --- calling mount_cdrom now :)");
2180 if (!mount_cdrom(bkpinfo)) {
2181 mr_msg(2,
2182 "gcffa --- managed to mount CD; so, no need for Plan B");
2183 try_plan_B = FALSE;
2184 } else {
2185 try_plan_B = TRUE;
2186 }
2187 if (what_number_cd_is_this(bkpinfo) > 1) {
2188 insist_on_this_cd_number(bkpinfo,
2189 (g_current_media_number = 1));
2190 }
2191 }
2192 if (try_plan_B) {
2193 mr_msg(2, "gcffa --- OK, switching to Plan B");
2194 chdir(bkpinfo->tmpdir);
2195 run_program_and_log_output("mkdir -p tmp", FALSE);
2196
2197 if (strlen(bkpinfo->media_device) == 0) {
2198 strcpy(bkpinfo->media_device, "/dev/st0");
2199 mr_msg(2, "media_device is blank; assuming %s",
2200 bkpinfo->media_device);
2201 }
2202 mr_asprintf(&tmp, bkpinfo->media_device);
2203 if (extract_cfg_file_and_mountlist_from_tape_dev
2204 (bkpinfo->media_device)) {
2205 strcpy(bkpinfo->media_device, "/dev/st0");
2206 if (extract_cfg_file_and_mountlist_from_tape_dev
2207 (bkpinfo->media_device)) {
2208 strcpy(bkpinfo->media_device, "/dev/osst0");
2209 if (extract_cfg_file_and_mountlist_from_tape_dev
2210 (bkpinfo->media_device)) {
2211 strcpy(bkpinfo->media_device, "/dev/ht0");
2212 if (extract_cfg_file_and_mountlist_from_tape_dev
2213 (bkpinfo->media_device)) {
2214 mr_msg(3,
2215 "I tried lots of devices but none worked.");
2216 strcpy(bkpinfo->media_device, tmp);
2217 }
2218 }
2219 }
2220 }
2221 mr_free(tmp);
2222
2223 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2224 log_to_screen(_
2225 ("Cannot find config info on tape/CD/floppy"));
2226 return (1);
2227 }
2228 } else {
2229 mr_msg(2,
2230 "gcffa --- looking at mounted CD for mindi-boot.2880.img");
2231 /* BERLIOS : Useless ?
2232 mr_asprintf(&command,
2233 "mount " MNT_CDROM
2234 "/images/mindi-boot.2880.img -o loop %s", mountpt);
2235 */
2236 mr_asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2237 if (!does_file_exist(mounted_cfgf_path)) {
2238 mr_msg(2,
2239 "gcffa --- Plan C, a.k.a. untarring some file from all.tar.gz");
2240 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
2241 run_program_and_log_output(command, TRUE);
2242 mr_free(command);
2243
2244 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2245 fatal_error
2246 ("Please reinsert the disk/CD and try again.");
2247 }
2248 }
2249 mr_free(mounted_cfgf_path);
2250 }
2251 }
2252 mr_free(mountpt);
2253
2254 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2255 mr_msg(1, "gcffa --- great! We've got the config file");
2256 mr_asprintf(&tmp, "%s/%s",
2257 call_program_and_get_last_line_of_output("pwd"),
2258 MONDO_CFG_FILE_STUB);
2259 mr_asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2260 iamhere(command);
2261
2262 if (strcmp(tmp, cfg_file)
2263 && run_program_and_log_output(command, 1)) {
2264 mr_msg(1,
2265 "... but an error occurred when I tried to move it to %s",
2266 cfg_file);
2267 } else {
2268 mr_msg(1, "... and I moved it successfully to %s", cfg_file);
2269 }
2270 mr_free(command);
2271
2272 mr_asprintf(&command, "cp -f %s/%s %s",
2273 call_program_and_get_last_line_of_output("pwd"),
2274 MOUNTLIST_FNAME_STUB, mountlist_file);
2275 iamhere(command);
2276 if (strcmp(tmp, cfg_file)
2277 && run_program_and_log_output(command, 1)) {
2278 mr_msg(1, "Failed to get mountlist");
2279 } else {
2280 mr_msg(1, "Got mountlist too");
2281 mr_free(command);
2282 mr_asprintf(&command, "cp -f %s %s", mountlist_file,
2283 g_mountlist_fname);
2284 if (run_program_and_log_output(command, 1)) {
2285 mr_msg(1, "Failed to copy mountlist to /tmp");
2286 } else {
2287 mr_msg(1, "Copied mountlist to /tmp as well OK");
2288 mr_free(command);
2289 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2290 run_program_and_log_output(command, 1);
2291 }
2292 }
2293 mr_free(command);
2294 mr_free(tmp);
2295 }
2296 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2297 if (!does_file_exist(cfg_file)) {
2298 iamhere(cfg_file);
2299 mr_msg(1, "%s not found", cfg_file);
2300 log_to_screen
2301 (_
2302 ("Oh dear. Unable to recover configuration file from boot disk"));
2303 return (1);
2304 }
2305
2306 log_to_screen(_("Recovered mondo-restore.cfg"));
2307 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2308 log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2309 }
2310/* start SAH */
2311 else {
2312 mr_asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2313 bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2314 run_program_and_log_output(command, FALSE);
2315 mr_free(command);
2316 }
2317/* end SAH */
2318
2319 mr_asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2320 mr_free(cfg_file);
2321 run_program_and_log_output(command, FALSE);
2322 mr_free(command);
2323
2324 mr_asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2325 mr_free(mountlist_file);
2326 run_program_and_log_output(command, FALSE);
2327 mr_free(command);
2328
2329 mr_asprintf(&command, "cp -f etc/raidtab /etc/");
2330 run_program_and_log_output(command, FALSE);
2331 mr_free(command);
2332
2333 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2334 run_program_and_log_output(command, FALSE);
2335 mr_free(command);
2336
2337 g_backup_media_type = bkpinfo->backup_media_type;
2338 strncpy(bkpinfo->backup_media_string,bkptype_to_string(bkpinfo->backup_media_type), (size_t)63);
2339 g_backup_media_string = bkpinfo->backup_media_string;
2340 return (retval);
2341}
2342/**************************************************************************
2343 *END_GET_CFG_FILE_FROM_ARCHIVE *
2344 **************************************************************************/
2345/* @} - end restoreUtilityGroup */
2346
2347
2348void wait_until_software_raids_are_prepped(int wait_for_percentage)
2349{
2350 struct raidlist_itself *raidlist = NULL;
2351 int unfinished_mdstat_devices = 9999, i = 0;
2352 char *screen_message = NULL;
2353
2354 raidlist = (struct raidlist_itself *)mr_malloc(sizeof(struct raidlist_itself));
2355
2356 assert(wait_for_percentage <= 100);
2357 iamhere("wait_until_software_raids_are_prepped");
2358 while (unfinished_mdstat_devices > 0) {
2359 // FIXME: Prefix '/dev/' should really be dynamic!
2360 if (parse_mdstat(raidlist, "/dev/")) {
2361 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2362 mr_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2363 return;
2364 }
2365 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2366 if (raidlist->el[i].progress < wait_for_percentage) {
2367 unfinished_mdstat_devices++;
2368 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2369 {
2370 continue;
2371 }
2372 mr_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2373 mr_asprintf(&screen_message, "Sync'ing %s",
2374 raidlist->el[i].raid_device);
2375 open_evalcall_form(screen_message);
2376 mr_free(screen_message);
2377
2378 while (raidlist->el[i].progress < wait_for_percentage) {
2379 mr_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2380 update_evalcall_form(raidlist->el[i].progress);
2381 sleep(2);
2382 // FIXME: Prefix '/dev/' should really be dynamic!
2383 if (parse_mdstat(raidlist, "/dev/")) {
2384 break;
2385 }
2386 }
2387 close_evalcall_form();
2388 }
2389 }
2390 }
2391 mr_free(raidlist);
2392}
Note: See TracBrowser for help on using the repository browser.