source: MondoRescue/trunk/mondo/mondo/mondorestore/mondo-rstr-tools.c@ 794

Last change on this file since 794 was 794, checked in by Bruno Cornec, 18 years ago

merge -r781:793 $SVN_M/branches/stable

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