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

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

Integrates trunk memory mngt for mondo-rstr-tools.c
This ends the first round of modifications for memory management.

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