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

Last change on this file since 1663 was 1663, checked in by Bruno Cornec, 17 years ago
  • Fix bug #197 (based on an initial patch of Scott Cummings)
  • Fix a bug where df was using locale to print messages and wasn't filtered correctly
  • mkdtemp checked in configure
  • reset_bkpinfo called as early as possible by both main program.
  • It creates a tmpdir cleanly with mkdtemp in setup_tmpdir subfunction, which takes in account TMPIR and TMP env var. Remains to see what tmpfs does and tests
  • configure.in should also be filtered.
  • Remove g_bkpinfo_DONTUSETHIS
  • remove bkpinfo also from header files
  • Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
  • Apply patch from Andree Leidenfrost, modified a bit to use bkpinfo->tmpdir instead of /tmp or MINDI_CACHE when appropriate. Fix security issues in mondo. Thanks al ot Andree for catching all those issues.
  • /tmp => /var/log for mondorestore.log in mindi
  • Update linux terminfo to fix a color issue (Andree Leidenfrost)
  • Removes useless log file (Andree Leidenfrost)
  • replace vi with find_my_editor during restore (Andree Leidenfrost)
  • sync in bg in mindi (VMWare issue to look at)
  • mindi/mindi-busybox have a different version than mondo for pb
  • PB-SUF also added to spec file
  • Fix a bug for pb build (omission of PB-SUF declaration)

(merge -r1631:1662 $SVN_M/branches/2.2.5)

  • Property svn:keywords set to Id
File size: 70.5 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-tools.c 1663 2007-09-27 10:21:18Z bruno $
3*/
4
5
6#include <pthread.h>
7#include <unistd.h>
8#include "my-stuff.h"
9#include "mr_mem.h"
10#include "mr_msg.h"
11#include "mr_str.h"
12#include "mr_gettext.h"
13
14#include "mondostructures.h"
15#include "libmondo.h"
16#include "mr-externs.h"
17#include "mondo-rstr-tools.h"
18
19#define STD_PREFIX "mondorescue"
20
21extern char *bkptype_to_string(t_bkptype bt);
22
23extern bool g_sigpipe_caught;
24extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
25extern bool g_I_have_just_nuked;
26extern char *g_tmpfs_mountpt;
27extern char *g_isodir_device;
28extern char *g_isodir_format;
29extern long g_current_progress, g_maximum_progress;
30extern char *g_biggielist_txt; // where 'biggielist.txt' is stored, on ramdisk / tempdir;
31 // biggielist.txt is the list of big files stored on the
32 // backup media set in question
33extern char *g_filelist_full; // filelist.full.gz is the list of all regular files
34 // (excluding big files) stored on the backup media set
35extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the
36 // user chooses them
37extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which
38 // were archived as images, not just /dev entries
39 // ... e.g. NTFS, BeOS partitions
40extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
41 // restore only these
42extern char *g_mondo_cfg_file; // where m*ndo-restore.cfg (the config file) is stored
43extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
44
45extern t_bkptype g_backup_media_type;
46extern char *g_backup_media_string;
47
48extern int g_partition_table_locked_up;
49extern char *MONDO_LOGFILE;
50
51/* Reference to global bkpinfo */
52extern struct s_bkpinfo *bkpinfo;
53
54/* Should we use or not extended attributes and acl when restoring */
55char *g_getfattr = NULL;
56char *g_getfacl = NULL;
57
58/**
59 * @addtogroup restoreUtilityGroup
60 * @{
61 */
62/**
63 * Free the malloc()s for the filename variables.
64 */
65void free_MR_global_filenames(void)
66{
67 mr_free(g_biggielist_txt);
68 mr_free(g_filelist_full);
69 mr_free(g_filelist_imagedevs);
70 mr_free(g_imagedevs_restthese);
71 mr_free(g_mondo_cfg_file);
72 mr_free(g_mountlist_fname);
73 mr_free(g_tmpfs_mountpt);
74 mr_free(g_isodir_device);
75 mr_free(g_isodir_format);
76}
77
78
79/**
80 * Ask the user which imagedevs from the list contained in @p infname should
81 * actually be restored.
82 * @param infname The file containing a list of all imagedevs.
83 * @param outfname The location of the output file containing the imagedevs the user wanted to restore.
84 * @ingroup restoreUtilityGroup
85 */
86void ask_about_these_imagedevs(char *infname, char *outfname)
87{
88 FILE *fin = NULL;
89 FILE *fout = NULL;
90 /************************************************************************
91 * allocate memory regions. test and set -sab 16 feb 2003 *
92 ************************************************************************/
93 char *incoming = NULL;
94 char *question = NULL;
95
96 size_t n = 0;
97
98 assert_string_is_neither_NULL_nor_zerolength(infname);
99 assert_string_is_neither_NULL_nor_zerolength(outfname);
100
101 if (!(fin = fopen(infname, "r"))) {
102 fatal_error("Cannot openin infname");
103 }
104 if (!(fout = fopen(outfname, "w"))) {
105 fatal_error("Cannot openin outfname");
106 }
107 for (mr_getline(&incoming, &n, fin);
108 !feof(fin); mr_getline(&incoming, &n, fin)) {
109 mr_strip_spaces(incoming);
110
111 if (incoming[0] == '\0') {
112 continue;
113 }
114
115 mr_asprintf(&question,
116 _("Should I restore the image of %s ?"), incoming);
117
118 if (ask_me_yes_or_no(question)) {
119 fprintf(fout, "%s\n", incoming);
120 }
121 mr_free(question);
122 }
123
124 /*** free memory ***********/
125 mr_free(incoming);
126
127 paranoid_fclose(fout);
128 paranoid_fclose(fin);
129}
130
131/**************************************************************************
132 *ASK_ABOUT_THESE_IMAGEDEVS *
133 **************************************************************************/
134
135
136/**
137 * Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname.
138 * @param bkpinfo The backup information structure. @c tmpdir is the only field used.
139 * @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
140 * @param output_cfg_file Where to put the configuration file extracted.
141 * @param output_mountlist_file Where to put the mountlist file extracted.
142 * @return 0 for success, nonzero for failure.
143 * @ingroup restoreUtilityGroup
144 */
145int
146extract_config_file_from_ramdisk(char *ramdisk_fname,
147 char *output_cfg_file,
148 char *output_mountlist_file)
149{
150 char *mountpt = NULL;
151 char *command = NULL;
152 char *orig_fname = NULL;
153 int retval = 0;
154
155 assert(bkpinfo != NULL);
156 assert_string_is_neither_NULL_nor_zerolength(ramdisk_fname);
157 assert_string_is_neither_NULL_nor_zerolength(output_cfg_file);
158 assert_string_is_neither_NULL_nor_zerolength(output_mountlist_file);
159 mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
160 mr_asprintf(&command, "mkdir -p %s", mountpt);
161 run_program_and_log_output(command, FALSE);
162 mr_free(command);
163
164 mr_asprintf(&command, "gzip -dc %s > %s/mindi.rd 2> /dev/null",
165 ramdisk_fname, bkpinfo->tmpdir);
166 run_program_and_log_output(command, FALSE);
167 mr_free(command);
168
169 mr_asprintf(&command, "umount %s", mountpt);
170 run_program_and_log_output(command, FALSE);
171 mr_free(command);
172
173 mr_asprintf(&command, "mount -o loop %s/mindi.rd -t ext2 %s",
174 bkpinfo->tmpdir, mountpt);
175 run_program_and_log_output(command, FALSE);
176 mr_free(command);
177
178 mr_asprintf(&command, "mkdir -p %s/tmp", bkpinfo->tmpdir);
179 run_program_and_log_output(command, FALSE);
180 mr_free(command);
181
182 mr_asprintf(&command, "cp -f %s/%s %s", // %s/%s becomes {mountpt}/tmp/m*ndo-restore.cfg
183 mountpt, g_mondo_cfg_file, output_cfg_file);
184 run_program_and_log_output(command, FALSE);
185 mr_free(command);
186
187 mr_asprintf(&orig_fname, "%s/%s", mountpt, g_mountlist_fname);
188 if (does_file_exist(orig_fname)) {
189 mr_asprintf(&command, "cp -f %s %s", orig_fname, output_mountlist_file);
190 run_program_and_log_output(command, FALSE);
191 mr_free(command);
192 }
193 mr_asprintf(&command, "umount %s", mountpt);
194 mr_free(mountpt);
195
196 run_program_and_log_output(command, FALSE);
197 mr_free(command);
198
199 if (!does_file_exist(output_cfg_file)
200 || (!does_file_exist(output_mountlist_file)
201 && does_file_exist(orig_fname))) {
202 mr_msg(2, "Failed to extract %s and/or %s from ramdisk",
203 output_cfg_file, output_mountlist_file);
204 retval = 1;
205 } else {
206 retval = 0;
207 }
208 mr_free(orig_fname);
209 return (retval);
210}
211
212
213/**
214 * Keep trying to get mondo-restore.cfg from the archive, until the user gives up.
215 */
216void get_cfg_file_from_archive_or_bust()
217{
218 while (get_cfg_file_from_archive()) {
219 if (!ask_me_yes_or_no
220 (_
221 ("Failed to find config file/archives. Choose another source?")))
222 {
223 fatal_error("Could not find config file/archives. Aborting.");
224 }
225 interactively_obtain_media_parameters_from_user(FALSE);
226 }
227}
228
229
230/**
231 * Determine whether @p list_fname contains a line containing @p f.
232 * @param f The line to search for.
233 * @param list_fname The file to search in.
234 * @param preamble Ignore this beginning part of @p f ("" to disable).
235 * @return TRUE if it's in the list, FALSE if it's not.
236 */
237bool is_file_in_list(char *f, char *list_fname, char *preamble)
238{
239
240 /** needs malloc **/
241 char *command = NULL;
242 char *file = NULL;
243 char *tmp = NULL;
244 int res = 0;
245
246 assert_string_is_neither_NULL_nor_zerolength(f);
247 assert_string_is_neither_NULL_nor_zerolength(list_fname);
248 assert(preamble != NULL);
249
250 if (strncmp(preamble, f, strlen(preamble)) == 0) {
251 mr_asprintf(&file, f + strlen(preamble));
252 } else {
253 mr_asprintf(&file, f);
254 }
255 if (file[0] == '/' && file[1] == '/') {
256 mr_asprintf(&tmp, file);
257 mr_free(file);
258 mr_asprintf(&file, tmp + 1);
259 mr_free(tmp);
260 }
261 mr_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles",
262 f, file);
263 mr_asprintf(&command, "grep -E '^%s$' %s", file, list_fname);
264 mr_free(file);
265
266 res = run_program_and_log_output(command, FALSE);
267 mr_free(command);
268 if (res) {
269 return (FALSE);
270 } else {
271 return (TRUE);
272 }
273}
274/**************************************************************************
275 *END_IS_FILE_IN_LIST *
276 **************************************************************************/
277
278
279/**
280 * Set up an ISO backup.
281 * @param bkpinfo The backup information structure. Fields used:
282 * - @c bkpinfo->backup_media_type
283 * - @c bkpinfo->disaster_recovery
284 * - @c bkpinfo->isodir
285 * @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
286 * @return 0 for success, nonzero for failure.
287 */
288int iso_fiddly_bits(bool nuke_me_please)
289{
290 char *mount_isodir_command = NULL;
291 char *command = NULL;
292 int retval = 0, i = 0;
293 bool already_mounted = FALSE;
294
295 assert(bkpinfo != NULL);
296
297 g_ISO_restore_mode = TRUE;
298 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
299 if (bkpinfo->disaster_recovery) {
300 /* Patch Conor Daly 26-june-2004
301 * Don't let this clobber an existing bkpinfo->isodir */
302 if (!bkpinfo->isodir) {
303 mr_allocstr(bkpinfo->isodir, "/tmp/isodir");
304 }
305/* End patch */
306 mr_asprintf(&command, "mkdir -p %s", bkpinfo->isodir);
307 run_program_and_log_output(command, 5);
308 mr_free(command);
309 mr_msg(2, "Setting isodir to %s", bkpinfo->isodir);
310 }
311
312 if (!get_isodir_info
313 (g_isodir_device, g_isodir_format, bkpinfo->isodir,
314 nuke_me_please)) {
315 return (1);
316 }
317 paranoid_system("umount " MNT_CDROM " 2> /dev/null"); /* just in case */
318
319 if (is_this_device_mounted(g_isodir_device)) {
320 log_to_screen(_("WARNING - isodir is already mounted"));
321 already_mounted = TRUE;
322 } else {
323 if (strlen(g_isodir_format) > 1) {
324 mr_asprintf(&mount_isodir_command, "mount %s -t %s -o ro %s", g_isodir_device, g_isodir_format, bkpinfo->isodir);
325 } else {
326 mr_asprintf(&mount_isodir_command, "mount %s -o ro %s", g_isodir_device, bkpinfo->isodir);
327 }
328 run_program_and_log_output("df -m", FALSE);
329 mr_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?",
330 mount_isodir_command);
331 if (run_program_and_log_output(mount_isodir_command, FALSE)) {
332 popup_and_OK
333 (_
334 ("Cannot mount the device where the ISO files are stored."));
335 mr_free(mount_isodir_command);
336 return (1);
337 }
338 mr_free(mount_isodir_command);
339 log_to_screen
340 (_
341 ("I have mounted the device where the ISO files are stored."));
342 }
343 if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
344 mount_cdrom();
345 }
346 i = what_number_cd_is_this(); /* has the side-effect of calling mount_cdrom() */
347 mr_msg(1, "%s #%d has been mounted via loopback mount",
348 bkpinfo->backup_media_string, i);
349 if (i < 0) {
350 popup_and_OK
351 (_("Cannot find ISO images in the directory you specified."));
352 retval = 1;
353 }
354 mr_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__,
355 bkpinfo->isodir);
356 return (retval);
357}
358
359
360/**
361 * Kill all Petris processes.
362 */
363void kill_petris(void)
364{
365 char *command = NULL;
366 mr_asprintf(&command,
367 "kill `ps 2> /dev/null | grep petris 2> /dev/null | grep -v grep | cut -d' ' -f2` 2> /dev/null");
368 paranoid_system(command);
369 mr_free(command);
370}
371
372/**************************************************************************
373 *END_KILL_PETRIS *
374 **************************************************************************/
375
376/**
377 * Mount @p device at @p mpt as @p format.
378 * @param device The device (/dev entry) to mount.
379 * @param mpt The directory to mount it on.
380 * @param format The filesystem type of @p device.
381 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
382 * @return 0 for success, nonzero for failure.
383 */
384int mount_device(char *device, char *mpt, char *format, bool writeable)
385{
386 int res = 0;
387
388 char *command = NULL;
389 char *mountdir = NULL;
390 char *mountpoint = NULL;
391 char *additional_parameters = NULL;
392
393 assert_string_is_neither_NULL_nor_zerolength(device);
394 assert_string_is_neither_NULL_nor_zerolength(mpt);
395 assert(format != NULL);
396
397 if (!strcmp(mpt, "/1")) {
398 mr_asprintf(&mountpoint, "/");
399 mr_msg(3, "Mommm! SME is being a dildo!");
400 } else {
401 mr_asprintf(&mountpoint, mpt);
402 }
403
404 if (!strcmp(mountpoint, "lvm")) {
405 mr_free(mountpoint);
406 return (0);
407 }
408 if (!strcmp(mountpoint, "image")) {
409 mr_free(mountpoint);
410 return (0);
411 }
412 mr_msg(1, "Mounting device %s ", device);
413 if (writeable) {
414 mr_asprintf(&additional_parameters, "-o rw");
415 } else {
416 mr_asprintf(&additional_parameters, "-o ro");
417 }
418 if (find_home_of_exe("setfattr")) {
419 mr_strcat(additional_parameters, ",user_xattr");
420 }
421 if (find_home_of_exe("setfacl")) {
422 mr_strcat(additional_parameters, ",acl");
423 }
424
425 if (!strcmp(mountpoint, "swap")) {
426 mr_asprintf(&command, "swapon %s", device);
427 } else {
428 if (!strcmp(mountpoint, "/")) {
429 mr_asprintf(&mountdir, MNT_RESTORING);
430 } else {
431 mr_asprintf(&mountdir, "%s%s", MNT_RESTORING, mountpoint);
432 }
433 mr_asprintf(&command, "mkdir -p %s", mountdir);
434 run_program_and_log_output(command, FALSE);
435 mr_free(command);
436
437 mr_asprintf(&command, "mount -t %s %s %s %s 2>> %s", format, device,
438 additional_parameters, mountdir, MONDO_LOGFILE);
439 mr_msg(2, "command='%s'", command);
440 }
441 mr_free(additional_parameters);
442
443 res = run_program_and_log_output(command, TRUE);
444 if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
445 mr_msg(1, "Re-trying without the fancy extra parameters");
446 mr_free(command);
447
448 mr_asprintf(&command, "mount -t %s %s %s 2>> %s", format, device,
449 mountdir, MONDO_LOGFILE);
450 res = run_program_and_log_output(command, TRUE);
451 }
452 if (res) {
453 mr_msg(1, "Unable to mount device %s (type %s) at %s", device,
454 format, mountdir);
455 mr_msg(1, "command was '%s'", command);
456 if (!strcmp(mountpoint, "swap")) {
457 log_to_screen("Unable to mount device %s (type %s) at %s", device,
458 format, mountdir);
459 } else {
460 mr_msg(2, "Retrying w/o the '-t' switch");
461 mr_free(command);
462
463 mr_asprintf(&command, "mount %s %s 2>> %s", device, mountdir,
464 MONDO_LOGFILE);
465 mr_msg(2, "2nd command = '%s'", command);
466 res = run_program_and_log_output(command, TRUE);
467 if (res == 0) {
468 mr_msg(1,
469 "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
470 }
471 }
472 }
473 mr_free(command);
474 mr_free(mountdir);
475
476 if (res && !strcmp(mountpoint, "swap")) {
477 mr_msg(2, "That's ok. It's just a swap partition.");
478 mr_msg(2, "Non-fatal error. Returning 0.");
479 res = 0;
480 }
481 mr_free(mountpoint);
482
483 return (res);
484}
485/**************************************************************************
486 *END_MOUNT_DEVICE *
487 **************************************************************************/
488
489
490/**
491 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
492 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
493 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
494 * @return The number of errors encountered (0 for success).
495 */
496int mount_all_devices(struct mountlist_itself
497 *p_external_copy_of_mountlist, bool writeable)
498{
499 int retval = 0;
500 int lino = 0;
501 int res = 0;
502 char *tmp = NULL;
503 char *these_failed = NULL;
504 char *format = NULL;
505 struct mountlist_itself *mountlist = NULL;
506
507 assert(p_external_copy_of_mountlist != NULL);
508 mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
509 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
510 sizeof(struct mountlist_itself));
511 sort_mountlist_by_mountpoint(mountlist, 0);
512
513 mvaddstr_and_log_it(g_currentY, 0, _("Mounting devices "));
514 open_progress_form(_("Mounting devices"),
515 _("I am now mounting all the drives."),
516 _("This should not take long."),
517 "", mountlist->entries);
518
519 for (lino = 0; lino < mountlist->entries; lino++) {
520 if (!strcmp(mountlist->el[lino].device, "/proc")) {
521 mr_msg(1,
522 "Again with the /proc - why is this in your mountlist?");
523 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
524 log_to_screen(_("%s is already mounted"),
525 mountlist->el[lino].device);
526 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
527 && strcmp(mountlist->el[lino].mountpoint, "lvm")
528 && strcmp(mountlist->el[lino].mountpoint, "raid")
529 && strcmp(mountlist->el[lino].mountpoint, "image")) {
530 mr_asprintf(&tmp, "Mounting %s", mountlist->el[lino].device);
531 update_progress_form(tmp);
532 mr_free(tmp);
533
534 mr_asprintf(&format, mountlist->el[lino].format);
535 if (!strcmp(format, "ext3")) {
536 mr_free(format);
537 mr_asprintf(&format, "ext2");
538 }
539 res = mount_device(mountlist->el[lino].device,
540 mountlist->el[lino].mountpoint,
541 format, writeable);
542 retval += res;
543 if (res) {
544 if (these_failed != NULL) { /* not the first time */
545 mr_strcat(these_failed, " %s", mountlist->el[lino].device);
546 } else { /* The first time */
547 mr_asprintf(&these_failed, "%s", mountlist->el[lino].device);
548 }
549 }
550 mr_free(format);
551 }
552 g_current_progress++;
553 }
554 close_progress_form();
555 run_program_and_log_output("df -m", TRUE);
556 if (retval) {
557 if (g_partition_table_locked_up > 0) {
558 log_to_screen
559 (_
560 ("fdisk's ioctl() call to refresh its copy of the partition table causes the kernel to"));
561 log_to_screen(_
562 ("lock up the partition table. You might have to reboot and use Interactive Mode to"));
563 log_to_screen(_
564 ("format and restore *without* partitioning first. Sorry for the inconvenience."));
565 }
566 mr_asprintf(&tmp, _("Could not mount devices %s- shall I abort?"),
567 these_failed);
568 mr_free(these_failed);
569
570 if (!ask_me_yes_or_no(tmp)) {
571 retval = 0;
572 log_to_screen
573 (_
574 ("Continuing, although some devices failed to be mounted"));
575 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
576 } else {
577 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
578 log_to_screen
579 (_("Unable to mount some or all of your partitions."));
580 }
581 mr_free(tmp);
582 } else {
583 log_to_screen(_("All partitions were mounted OK."));
584 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
585 }
586 run_program_and_log_output("df -m", 3);
587 mr_free(mountlist);
588 return (retval);
589}
590 /**************************************************************************
591 *END_MOUNT_ALL_DEVICES *
592 **************************************************************************/
593
594
595/**
596 * Mount the CD-ROM device at /mnt/cdrom.
597 * @param bkpinfo The backup information structure. Fields used:
598 * - @c bkpinfo->backup_media_type
599 * - @c bkpinfo->disaster_recovery
600 * - @c bkpinfo->isodir
601 * - @c bkpinfo->media_device
602 * @return 0 for success, nonzero for failure.
603 */
604int mount_cdrom()
605{
606 char *mount_cmd = NULL;
607 int i = 0, res = 0;
608#ifdef __FreeBSD__
609 char *mddev = NULL;
610#endif
611
612 assert(bkpinfo != NULL);
613
614 if (bkpinfo->backup_media_type == tape
615 || bkpinfo->backup_media_type == udev) {
616 mr_msg(8, "Tape/udev. Therefore, no need to mount CDROM.");
617 return 0;
618 }
619
620 if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
621 mr_msg(2, "mount_cdrom() - CD already mounted. Fair enough.");
622 return (0);
623 }
624
625 if (bkpinfo->backup_media_type == nfs) {
626 mr_msg(2, "Mounting for NFS thingy");
627 mr_msg(2, "isodir = %s", bkpinfo->isodir);
628 if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
629 && am_I_in_disaster_recovery_mode()) {
630 strcpy(bkpinfo->isodir, "/tmp/isodir");
631 mr_msg(1, "isodir is being set to %s", bkpinfo->isodir);
632 }
633#ifdef __FreeBSD__
634 mr_asprintf(&mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
635 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
636 g_current_media_number);
637 mddev = make_vn(mount_cmd);
638 mr_free(mount_cmd);
639
640 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
641 mr_free(mddev);
642#else
643 mr_asprintf(&mount_cmd,
644 "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
645 bkpinfo->isodir, bkpinfo->nfs_remote_dir, bkpinfo->prefix,
646 g_current_media_number, MNT_CDROM);
647#endif
648
649 } else if (bkpinfo->backup_media_type == iso) {
650#ifdef __FreeBSD__
651 mr_asprintf(&mount_cmd, "%s/%s-%d.iso", bkpinfo->isodir,
652 bkpinfo->prefix, g_current_media_number);
653 mddev = make_vn(mount_cmd);
654 mr_free(mount_cmd);
655
656 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
657 mr_free(mddev);
658#else
659 mr_asprintf(&mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
660 bkpinfo->isodir, bkpinfo->prefix, g_current_media_number,
661 MNT_CDROM);
662#endif
663 } else if (strstr(bkpinfo->media_device, "/dev/"))
664#ifdef __FreeBSD__
665 {
666 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
667 MNT_CDROM);
668 }
669#else
670 {
671 mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
672 bkpinfo->media_device, MNT_CDROM);
673 }
674#endif
675
676 else {
677 if (bkpinfo->disaster_recovery
678 && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
679 mr_allocstr(bkpinfo->media_device,
680 last_line_of_file("/tmp/CDROM-LIVES-HERE"));
681 }
682
683#ifdef __FreeBSD__
684 mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
685 MNT_CDROM);
686#else
687 mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
688 bkpinfo->media_device, MNT_CDROM);
689#endif
690
691 }
692 mr_msg(2, "(mount_cdrom) --- command = %s", mount_cmd);
693 for (i = 0; i < 2; i++) {
694 res = run_program_and_log_output(mount_cmd, FALSE);
695 if (!res) {
696 break;
697 } else {
698 mr_msg(2, "Failed to mount CD-ROM drive.");
699 sleep(5);
700 run_program_and_log_output("sync", FALSE);
701 }
702 }
703 mr_free(mount_cmd);
704
705 if (res) {
706 mr_msg(2, "Failed, despite %d attempts", i);
707 } else {
708 mr_msg(2, "Mounted CD-ROM drive OK");
709 }
710 return (res);
711}
712/**************************************************************************
713 *END_MOUNT_CDROM *
714 **************************************************************************/
715
716
717/**
718 * Fix some miscellaneous things in the filesystem so the system will come
719 * up correctly on the first boot.
720 */
721void protect_against_braindead_sysadmins()
722{
723 run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
724 FALSE);
725 run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
726 FALSE);
727 if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
728 chmod(MNT_RESTORING "/tmp",1777 );
729 }
730 run_program_and_log_output("mkdir -p " MNT_RESTORING
731 "/var/run/console", FALSE);
732 chmod(MNT_RESTORING "/dev/null",0777);
733 run_program_and_log_output("cd " MNT_RESTORING
734 "; for i in `ls home/`; do echo \"Moving $i's spurious files to $i/.disabled\"; mkdir \"$i\"/.disabled ; mv -f \"$i\"/.DCOP* \"$i\"/.MCOP* \"$i\"/.*authority \"$i\"/.kde/tmp* \"$i\"/.kde/socket* \"$i\"/.disabled/ ; done",
735 TRUE);
736 run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
737 TRUE);
738 run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
739 TRUE);
740}
741/**************************************************************************
742 *END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS *
743 **************************************************************************/
744
745
746/**
747 * Fill out @p bkpinfo based on @p cfg_file.
748 * @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo.
749 * @param bkpinfo The backup information structure to fill out with information
750 * from @p cfg_file.
751 * @return 0 for success, nonzero for failure.
752 */
753int read_cfg_file_into_bkpinfo(char *cfgf)
754{
755 char *value = NULL;
756 char *tmp = NULL;
757 char *envtmp1 = NULL;
758 char *envtmp2 = NULL;
759 char *command = NULL;
760 char *iso_mnt = NULL;
761 char *iso_path = NULL;
762 char *old_isodir = NULL;
763 char *cfg_file = NULL;
764 t_bkptype media_specified_by_user;
765
766 malloc_string(value);
767 assert(bkpinfo != NULL);
768
769 if (!cfgf) {
770 cfg_file = g_mondo_cfg_file;
771 } else {
772 cfg_file = cfgf;
773 }
774
775 media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
776
777 if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
778 if (!strcmp(value, "cdstream")) {
779 bkpinfo->backup_media_type = cdstream;
780 } else if (!strcmp(value, "cdr")) {
781 bkpinfo->backup_media_type = cdr;
782 } else if (!strcmp(value, "cdrw")) {
783 bkpinfo->backup_media_type = cdrw;
784 } else if (!strcmp(value, "dvd")) {
785 bkpinfo->backup_media_type = dvd;
786 } else if (!strcmp(value, "iso")) {
787 // Patch by Conor Daly - 2004/07/12
788 bkpinfo->backup_media_type = iso;
789 if (am_I_in_disaster_recovery_mode()) {
790 /* Check to see if CD is already mounted before mounting it... */
791 if (!is_this_device_mounted("/dev/cdrom")) {
792 mr_msg(2,
793 "NB: CDROM device not mounted, mounting...");
794 run_program_and_log_output("mount /dev/cdrom "
795 MNT_CDROM, 1);
796 }
797 if (does_file_exist(MNT_CDROM "/archives/filelist.0")) {
798 bkpinfo->backup_media_type = cdr;
799 run_program_and_log_output("umount " MNT_CDROM, 1);
800 log_it
801 ("Re-jigging configuration AGAIN. CD-R, not ISO.");
802 }
803 }
804 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
805 mr_allocstr(bkpinfo->prefix,value);
806 } else {
807 mr_allocstr(bkpinfo->prefix,STD_PREFIX);
808 }
809 } else if (!strcmp(value, "nfs")) {
810 bkpinfo->backup_media_type = nfs;
811 if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
812 mr_allocstr(bkpinfo->prefix,value);
813 } else {
814 mr_allocstr(bkpinfo->prefix,STD_PREFIX);
815 }
816 if (strstr(call_program_and_get_last_line_of_output
817 ("cat /proc/cmdline"), "pxe")) {
818 /* We need to override prefix value in PXE mode as it's
819 * already done in start-nfs */
820 envtmp1 = getenv("imgname");
821 if (envtmp1 == NULL) {
822 fatal_error("no imgname variable in environment");
823 }
824 mr_allocstr(bkpinfo->prefix,envtmp1);
825 }
826
827 } else if (!strcmp(value, "tape")) {
828 bkpinfo->backup_media_type = tape;
829 } else if (!strcmp(value, "udev")) {
830 bkpinfo->backup_media_type = udev;
831 } else {
832 fatal_error("UNKNOWN bkp-media-type");
833 }
834 } else {
835 fatal_error("backup-media-type not specified!");
836 }
837 if (bkpinfo->disaster_recovery) {
838 if (bkpinfo->backup_media_type == cdstream) {
839 mr_allocstr(bkpinfo->media_device, "/dev/cdrom");
840 bkpinfo->media_size = (long)650; /* good guess */
841 } else if (bkpinfo->backup_media_type == tape
842 || bkpinfo->backup_media_type == udev) {
843 if (read_cfg_var(cfg_file, "media-dev", value)) {
844 fatal_error("Cannot get tape device name from cfg file");
845 }
846 mr_allocstr(bkpinfo->media_device, value);
847 read_cfg_var(cfg_file, "media-size", value);
848 bkpinfo->media_size = atol(value);
849 mr_msg(2, "Backup medium is TAPE --- dev=%s",
850 bkpinfo->media_device);
851 } else {
852 mr_allocstr(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
853 bkpinfo->media_size = (long)1999*1024; /* 650, probably, but we don't need this var anyway */
854 mr_msg(2, "Backup medium is CD-R[W]");
855 }
856 } else {
857 mr_msg(2,
858 "Not in Disaster Recovery Mode. No need to derive device name from config file.");
859 }
860
861 read_cfg_var(cfg_file, "use-star", value);
862 if (strstr(value, "yes")) {
863 bkpinfo->use_star = TRUE;
864 mr_msg(1, "Goody! ... bkpinfo->use_star is now true.");
865 }
866
867 read_cfg_var(cfg_file, "acl", value);
868 if (strstr(value, "yes")) {
869 mr_asprintf(&g_getfacl,"setfacl");
870 mr_msg(1, "We will restore ACLs");
871 if (! find_home_of_exe("setfacl")) {
872 mr_msg(1, "Unable to restore ACLs as no setfacl found");
873 }
874 }
875 read_cfg_var(cfg_file, "xattr", value);
876 if (strstr(value, "yes")) {
877 mr_asprintf(&g_getfattr,"setfattr");
878 mr_msg(1, "We will restore XATTRs");
879 if (! find_home_of_exe("setfattr")) {
880 mr_msg(1, "Unable to restore XATTRs as no setfattr found");
881 }
882 }
883
884 if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
885 bkpinfo->internal_tape_block_size = atol(value);
886 mr_msg(1, "Internal tape block size has been custom-set to %ld",
887 bkpinfo->internal_tape_block_size);
888 } else {
889 bkpinfo->internal_tape_block_size = mr_conf->internal_tape_blocksize;
890 mr_msg(1, "Internal tape block size = default (%ld)", mr_conf->internal_tape_blocksize);
891 }
892
893 read_cfg_var(cfg_file, "use-lzo", value);
894 if (strstr(value, "yes")) {
895 bkpinfo->use_lzo = TRUE;
896 bkpinfo->use_gzip = FALSE;
897 strcpy(bkpinfo->zip_exe, "lzop");
898 strcpy(bkpinfo->zip_suffix, "lzo");
899 } else {
900 read_cfg_var(cfg_file, "use-gzip", value);
901 if (strstr(value, "yes")) {
902 bkpinfo->use_lzo = FALSE;
903 bkpinfo->use_gzip = TRUE;
904 strcpy(bkpinfo->zip_exe, "gzip");
905 strcpy(bkpinfo->zip_suffix, "gz");
906 } else {
907 read_cfg_var(cfg_file, "use-comp", value);
908 if (strstr(value, "yes")) {
909 bkpinfo->use_lzo = FALSE;
910 bkpinfo->use_gzip = FALSE;
911 strcpy(bkpinfo->zip_exe, "bzip2");
912 strcpy(bkpinfo->zip_suffix, "bz2");
913 } else {
914 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
915 }
916 }
917 }
918
919 value[0] = '\0';
920 read_cfg_var(cfg_file, "differential", value);
921 if (!strcmp(value, "yes") || !strcmp(value, "1")) {
922 bkpinfo->differential = TRUE;
923 }
924 mr_msg(2, "differential var = '%s'", value);
925 if (bkpinfo->differential) {
926 mr_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
927 } else {
928 mr_msg(2, "This is a regular (full) backup");
929 }
930
931 read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
932 if (tmp[0]
933 ||
934 strstr(call_program_and_get_last_line_of_output
935 ("cat /proc/cmdline"), "donteject")) {
936 bkpinfo->please_dont_eject = TRUE;
937 mr_msg(2, "Ok, I shan't eject when restoring! Groovy.");
938 }
939
940 if (bkpinfo->backup_media_type == nfs) {
941 if (!cfgf) {
942 mr_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount);
943 mr_msg(2, "nfs_remote_dir remains %s",
944 bkpinfo->nfs_remote_dir);
945 mr_msg(2,
946 "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
947 } else {
948 read_cfg_var(g_mondo_cfg_file, "nfs-server-mount",
949 bkpinfo->nfs_mount);
950 read_cfg_var(g_mondo_cfg_file, "nfs-server-path",
951 bkpinfo->nfs_remote_dir);
952 mr_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount);
953 mr_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir);
954 }
955 if (strstr(call_program_and_get_last_line_of_output
956 ("cat /proc/cmdline"), "pxe")) {
957 /* We need to override values in PXE mode as it's
958 * already done in start-nfs */
959 envtmp1 = getenv("nfsmount");
960 if (envtmp1 == NULL) {
961 fatal_error("no nfsmount variable in environment");
962 }
963 envtmp2 = getenv("dirimg");
964 if (envtmp2 == NULL) {
965 fatal_error("no dirimg variable in environment");
966 }
967 strcpy(bkpinfo->nfs_mount,envtmp1);
968 strcpy(bkpinfo->nfs_remote_dir,envtmp2);
969 }
970 } else if (bkpinfo->backup_media_type == iso) {
971 /* Patch by Conor Daly 23-june-2004
972 * to correctly mount iso-dev and set a sensible
973 * isodir in disaster recovery mode
974 */
975 mr_asprintf(&old_isodir, bkpinfo->isodir);
976 read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
977 read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
978 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
979 if (!bkpinfo->isodir[0]) {
980 strcpy(bkpinfo->isodir, old_isodir);
981 }
982 if (!bkpinfo->disaster_recovery) {
983 if (strcmp(old_isodir, bkpinfo->isodir)) {
984 log_it
985 ("user nominated isodir differs from archive, keeping user's choice: %s %s\n",
986 old_isodir, bkpinfo->isodir);
987 strcpy(bkpinfo->isodir, old_isodir);
988 }
989 }
990 mr_free(old_isodir);
991
992 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
993 mr_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
994 if (bkpinfo->disaster_recovery) {
995 if (is_this_device_mounted(g_isodir_device)) {
996 mr_msg(2, "NB: isodir is already mounted");
997 /* Find out where it's mounted */
998 mr_asprintf(&command,
999 "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3",
1000 g_isodir_device);
1001 log_it("command = %s", command);
1002 mr_asprintf(&iso_mnt, "%s",
1003 call_program_and_get_last_line_of_output(command));
1004 log_it("res of it = %s", iso_mnt);
1005 } else {
1006 mr_asprintf(&iso_mnt, "/tmp/isodir");
1007 mr_asprintf(&tmp, "mkdir -p %s", iso_mnt);
1008 run_program_and_log_output(tmp, 5);
1009 mr_free(tmp);
1010
1011 mr_asprintf(&tmp, "mount %s %s", g_isodir_device, iso_mnt);
1012 if (run_program_and_log_output(tmp, 3)) {
1013 mr_msg(1,
1014 "Unable to mount isodir. Perhaps this is really a CD backup?");
1015 bkpinfo->backup_media_type = cdr;
1016 mr_allocstr(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
1017 bkpinfo->isodir[0] = '\0';
1018 mr_free(iso_mnt);
1019 mr_free(iso_path);
1020 mr_asprintf(&iso_mnt, "");
1021 mr_asprintf(&iso_path, "");
1022 if (mount_cdrom()) {
1023 fatal_error
1024 ("Unable to mount isodir. Failed to mount CD-ROM as well.");
1025 } else {
1026 mr_msg(1,
1027 "You backed up to disk, then burned some CDs.");
1028 }
1029 }
1030 mr_free(tmp);
1031 }
1032 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1033 if (bkpinfo->backup_media_type == iso) {
1034 sprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1035 }
1036 mr_free(iso_mnt);
1037 mr_free(iso_path);
1038 }
1039 }
1040
1041 if (media_specified_by_user != none) {
1042 if (g_restoring_live_from_cd) {
1043 if (bkpinfo->backup_media_type != media_specified_by_user) {
1044 mr_msg(2,
1045 "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1046 interactively_obtain_media_parameters_from_user(FALSE);
1047 media_specified_by_user = bkpinfo->backup_media_type;
1048 get_cfg_file_from_archive();
1049 }
1050 }
1051 bkpinfo->backup_media_type = media_specified_by_user;
1052 }
1053 g_backup_media_type = bkpinfo->backup_media_type;
1054 strcpy(bkpinfo->backup_media_string, bkptype_to_string(bkpinfo->backup_media_type));
1055 strcpy(g_backup_media_string, bkpinfo->backup_media_string);
1056 mr_free(value);
1057 return (0);
1058}
1059/**************************************************************************
1060 *END_READ_CFG_FILE_INTO_BKPINFO *
1061 **************************************************************************/
1062
1063
1064/**
1065 * Allow the user to edit the filelist and biggielist.
1066 * The filelist is unlinked after it is read.
1067 * @param bkpinfo The backup information structure. Fields used:
1068 * - @c bkpinfo->backup_media_type
1069 * - @c bkpinfo->isodir
1070 * - @c bkpinfo->media_device
1071 * - @c bkpinfo->tmpdir
1072 * @return The filelist structure containing the information read from disk.
1073 */
1074struct
1075s_node *process_filelist_and_biggielist()
1076{
1077 struct s_node *filelist = NULL;
1078
1079 char *command = NULL;
1080 char *tmp = NULL;
1081 int res = 0;
1082 size_t n = 0;
1083 pid_t pid;
1084
1085 assert(bkpinfo != NULL);
1086 malloc_string(tmp);
1087
1088 if (does_file_exist(g_filelist_full)
1089 && does_file_exist(g_biggielist_txt)) {
1090 mr_msg(1, "%s exists", g_filelist_full);
1091 mr_msg(1, "%s exists", g_biggielist_txt);
1092 mr_msg(2,
1093 "Filelist and biggielist already recovered from media. Yay!");
1094 } else {
1095 getcwd(tmp, MAX_STR_LEN);
1096 chdir(bkpinfo->tmpdir);
1097 mr_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1098 log_to_screen("Extracting filelist and biggielist from media...");
1099 unlink("/tmp/filelist.full");
1100 unlink("/" FILELIST_FULL_STUB);
1101 unlink("/tmp/i-want-my-lvm");
1102 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1103 mr_asprintf(&command,
1104 "tar -b %ld -zxf %s %s %s %s %s %s",
1105 bkpinfo->internal_tape_block_size,
1106 bkpinfo->media_device,
1107 MOUNTLIST_FNAME_STUB,
1108 BIGGIELIST_TXT_STUB,
1109 FILELIST_FULL_STUB,
1110 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1111 mr_msg(1, "tarcommand = %s", command);
1112 run_program_and_log_output(command, 1);
1113 mr_free(command);
1114 } else {
1115 mr_msg(2,
1116 "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1117 bkpinfo->isodir);
1118 insist_on_this_cd_number(1);
1119 mr_msg(2, "Back from iotcn");
1120 run_program_and_log_output("mount", 1);
1121 mr_asprintf(&command,
1122 "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1123 MNT_CDROM,
1124 MOUNTLIST_FNAME_STUB,
1125 BIGGIELIST_TXT_STUB,
1126 FILELIST_FULL_STUB,
1127 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
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()
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(struct s_bkpinfo *bkpinfo)
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
2056 // tar -zxvf-
2057 mr_asprintf(&command,
2058 "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2059 bkpinfo->media_device,
2060 bkpinfo->internal_tape_block_size,
2061 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size,
2062 MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2063 BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2064 mr_msg(2, "command = '%s'", command);
2065 res = run_program_and_log_output(command, -1);
2066 mr_free(command);
2067
2068 if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2069 res = 0;
2070 }
2071 return (res);
2072}
2073
2074
2075/**
2076 * Get the configuration file from the tape, or CD.
2077 * @param bkpinfo The backup information structure. Fields used:
2078 * - @c bkpinfo->backup_media_type
2079 * - @c bkpinfo->media_device
2080 * - @c bkpinfo->tmpdir
2081 * @return 0 for success, nonzero for failure.
2082 */
2083int get_cfg_file_from_archive()
2084{
2085 int retval = 0;
2086 char *command = NULL;
2087 char *cfg_file = NULL;
2088 char *mounted_cfgf_path = NULL;
2089 char *tmp = NULL;
2090 char *mountpt = NULL;
2091 char *ramdisk_fname = NULL;
2092 char *mountlist_file = NULL;
2093 int res = 0;
2094
2095 bool try_plan_B = FALSE;
2096
2097 assert(bkpinfo != NULL);
2098 mr_msg(2, "gcffa --- starting");
2099 log_to_screen(_("I'm thinking..."));
2100 mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2101 chdir(bkpinfo->tmpdir);
2102 // MONDO_CFG_FILE_STUB is missing the '/' at the start, FYI, by intent
2103 unlink(MONDO_CFG_FILE_STUB);
2104
2105 unlink(FILELIST_FULL_STUB);
2106 unlink(BIGGIELIST_TXT_STUB);
2107 unlink("tmp/i-want-my-lvm");
2108 mr_asprintf(&command, "mkdir -p %s", mountpt);
2109 run_program_and_log_output(command, FALSE);
2110 mr_free(command);
2111
2112 mr_asprintf(&cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2113 mr_asprintf(&mountlist_file, "%s/%s", bkpinfo->tmpdir,
2114 MOUNTLIST_FNAME_STUB);
2115 mr_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2116
2117 mr_asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2118 run_program_and_log_output(tmp, FALSE);
2119 mr_free(tmp);
2120
2121 if (!does_file_exist(cfg_file)) {
2122 mr_msg(2, "gcffa --- we don't have cfg file yet.");
2123 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2124 try_plan_B = TRUE;
2125 } else {
2126 mr_msg(2, "gcffa --- calling mount_cdrom now :)");
2127 if (!mount_cdrom()) {
2128 mr_msg(2,
2129 "gcffa --- managed to mount CD; so, no need for Plan B");
2130 try_plan_B = FALSE;
2131 } else {
2132 try_plan_B = TRUE;
2133 }
2134 if (what_number_cd_is_this() > 1) {
2135 insist_on_this_cd_number((g_current_media_number = 1));
2136 }
2137 }
2138 if (try_plan_B) {
2139 mr_msg(2, "gcffa --- OK, switching to Plan B");
2140 chdir(bkpinfo->tmpdir);
2141 run_program_and_log_output("mkdir -p tmp", FALSE);
2142
2143 if (strlen(bkpinfo->media_device) == 0) {
2144 mr_allocstr(bkpinfo->media_device, "/dev/st0");
2145 mr_msg(2, "media_device is blank; assuming %s",
2146 bkpinfo->media_device);
2147 }
2148 /* extract_cfg_file_and_mountlist_from_tape_dev needs
2149 * the internal block size to be setup */
2150 if (bkpinfo->internal_tape_blocksize == 0) {
2151 /* Guessing a value */
2152 bkpinfo->internal_tape_blocksize = 32768;
2153 }
2154 mr_asprintf(&tmp, bkpinfo->media_device);
2155 if (extract_cfg_file_and_mountlist_from_tape_dev
2156 (bkpinfo)) {
2157 mr_allocstr(bkpinfo->media_device, "/dev/st0");
2158 if (extract_cfg_file_and_mountlist_from_tape_dev
2159 (bkpinfo)) {
2160 mr_allocstr(bkpinfo->media_device, "/dev/osst0");
2161 if (extract_cfg_file_and_mountlist_from_tape_dev
2162 (bkpinfo)) {
2163 mr_allocstr(bkpinfo->media_device, "/dev/ht0");
2164 if (extract_cfg_file_and_mountlist_from_tape_dev
2165 (bkpinfo)) {
2166 mr_msg(3,
2167 "I tried lots of devices but none worked.");
2168 mr_allocstr(bkpinfo->media_device, tmp);
2169 }
2170 }
2171 }
2172 }
2173 mr_free(tmp);
2174
2175 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2176 log_to_screen(_
2177 ("Cannot find config info on tape/CD"));
2178 return (1);
2179 }
2180 } else {
2181 mr_asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2182 if (!does_file_exist(mounted_cfgf_path)) {
2183 mr_msg(2,
2184 "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2185 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
2186 run_program_and_log_output(command, TRUE);
2187 mr_free(command);
2188
2189 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2190 fatal_error
2191 ("Please reinsert the disk/CD and try again.");
2192 }
2193 }
2194 mr_free(mounted_cfgf_path);
2195 }
2196 }
2197 mr_free(mountpt);
2198
2199 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2200 mr_msg(1, "gcffa --- great! We've got the config file");
2201 mr_asprintf(&tmp, "%s/%s",
2202 call_program_and_get_last_line_of_output("pwd"),
2203 MONDO_CFG_FILE_STUB);
2204 mr_asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2205 iamhere(command);
2206
2207 if (strcmp(tmp, cfg_file)
2208 && run_program_and_log_output(command, 1)) {
2209 mr_msg(1,
2210 "... but an error occurred when I tried to move it to %s",
2211 cfg_file);
2212 } else {
2213 mr_msg(1, "... and I moved it successfully to %s", cfg_file);
2214 }
2215 mr_free(command);
2216
2217 mr_asprintf(&command, "cp -f %s/%s %s",
2218 call_program_and_get_last_line_of_output("pwd"),
2219 MOUNTLIST_FNAME_STUB, mountlist_file);
2220 iamhere(command);
2221 if (strcmp(tmp, cfg_file)
2222 && run_program_and_log_output(command, 1)) {
2223 mr_msg(1, "Failed to get mountlist");
2224 } else {
2225 mr_msg(1, "Got mountlist too");
2226 mr_free(command);
2227 mr_asprintf(&command, "cp -f %s %s", mountlist_file,
2228 g_mountlist_fname);
2229 if (run_program_and_log_output(command, 1)) {
2230 mr_msg(1, "Failed to copy mountlist to /tmp");
2231 } else {
2232 mr_msg(1, "Copied mountlist to /tmp as well OK");
2233 mr_free(command);
2234 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2235 run_program_and_log_output(command, 1);
2236 }
2237 }
2238 mr_free(command);
2239 mr_free(tmp);
2240 }
2241 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2242 if (!does_file_exist(cfg_file)) {
2243 iamhere(cfg_file);
2244 mr_msg(1, "%s not found", cfg_file);
2245 log_to_screen
2246 (_
2247 ("Oh dear. Unable to recover configuration file from boot disk"));
2248 return (1);
2249 }
2250
2251 log_to_screen(_("Recovered mondo-restore.cfg"));
2252 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2253 log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2254 }
2255/* start SAH */
2256 else {
2257 mr_asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2258 bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2259 run_program_and_log_output(command, FALSE);
2260 mr_free(command);
2261 }
2262/* end SAH */
2263
2264 mr_asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2265 mr_free(cfg_file);
2266 run_program_and_log_output(command, FALSE);
2267 mr_free(command);
2268
2269 mr_asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2270 mr_free(mountlist_file);
2271 run_program_and_log_output(command, FALSE);
2272 mr_free(command);
2273
2274 mr_asprintf(&command, "cp -f etc/raidtab /etc/");
2275 run_program_and_log_output(command, FALSE);
2276 mr_free(command);
2277
2278 mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2279 run_program_and_log_output(command, FALSE);
2280 mr_free(command);
2281
2282 g_backup_media_type = bkpinfo->backup_media_type;
2283 strncpy(bkpinfo->backup_media_string,bkptype_to_string(bkpinfo->backup_media_type), (size_t)63);
2284 g_backup_media_string = bkpinfo->backup_media_string;
2285 return (retval);
2286}
2287/**************************************************************************
2288 *END_GET_CFG_FILE_FROM_ARCHIVE *
2289 **************************************************************************/
2290/* @} - end restoreUtilityGroup */
2291
2292
2293void wait_until_software_raids_are_prepped(int wait_for_percentage)
2294{
2295 struct raidlist_itself *raidlist = NULL;
2296 int unfinished_mdstat_devices = 9999, i = 0;
2297 char *screen_message = NULL;
2298
2299 raidlist = (struct raidlist_itself *)mr_malloc(sizeof(struct raidlist_itself));
2300
2301 assert(wait_for_percentage <= 100);
2302 iamhere("wait_until_software_raids_are_prepped");
2303 while (unfinished_mdstat_devices > 0) {
2304 // FIXME: Prefix '/dev/' should really be dynamic!
2305 if (parse_mdstat(raidlist, "/dev/")) {
2306 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2307 mr_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2308 return;
2309 }
2310 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2311 if (raidlist->el[i].progress < wait_for_percentage) {
2312 unfinished_mdstat_devices++;
2313 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2314 {
2315 continue;
2316 }
2317 mr_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2318 mr_asprintf(&screen_message, "Sync'ing %s",
2319 raidlist->el[i].raid_device);
2320 open_evalcall_form(screen_message);
2321 mr_free(screen_message);
2322
2323 while (raidlist->el[i].progress < wait_for_percentage) {
2324 mr_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2325 update_evalcall_form(raidlist->el[i].progress);
2326 sleep(2);
2327 // FIXME: Prefix '/dev/' should really be dynamic!
2328 if (parse_mdstat(raidlist, "/dev/")) {
2329 break;
2330 }
2331 }
2332 close_evalcall_form();
2333 }
2334 }
2335 }
2336 mr_free(raidlist);
2337}
Note: See TracBrowser for help on using the repository browser.