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

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

svn merge -r 1923:1938 $SVN_M/branches/2.2.6

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