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

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