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

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

merge -r 1842:1889 2.2.5

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