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

Last change on this file since 1769 was 1769, checked in by Bruno Cornec, 16 years ago

Continue on configuration file items (compression)

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