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

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

Use of conf file entries (iso_burning_*, media_device, media_size)
and adapatation of the rest of the code to that (including bkpinfo)

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