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

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

bkptype_to_string is now a public function (not static anymore)

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