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

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

merge -r793:807 $SVN_M/branches/stable
src => common for the moment it's easier to manage merges

  • Property svn:keywords set to Id
File size: 73.1 KB
Line 
1/*
2 * $Id: mondo-rstr-tools.c 808 2006-09-22 21:12:37Z 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 /* We need to override prefix value in PXE mode as it's
854 * already done in start-nfs */
855 if (strstr(call_program_and_get_last_line_of_output
856 ("cat /proc/cmdline"), "pxe")) {
857 strcpy(bkpinfo->prefix,getenv("imgname"));
858 }
859
860 } else if (!strcmp(value, "tape")) {
861 bkpinfo->backup_media_type = tape;
862 } else if (!strcmp(value, "udev")) {
863 bkpinfo->backup_media_type = udev;
864 } else {
865 fatal_error("UNKNOWN bkp-media-type");
866 }
867 } else {
868 fatal_error("backup-media-type not specified!");
869 }
870 paranoid_free(value);
871
872 if (bkpinfo->disaster_recovery) {
873 if (bkpinfo->backup_media_type == cdstream) {
874 paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
875 bkpinfo->media_size[0] = 1999 * 1024;
876 bkpinfo->media_size[1] = 650; /* good guess */
877 } else if (bkpinfo->backup_media_type == tape
878 || bkpinfo->backup_media_type == udev) {
879 paranoid_free(bkpinfo->media_device);
880 if (read_cfg_var(cfg_file, "media-dev", bkpinfo->media_device)) {
881 fatal_error("Cannot get tape device name from cfg file");
882 }
883 read_cfg_var(cfg_file, "media-size", value);
884 bkpinfo->media_size[1] = atol(value);
885 paranoid_free(value);
886
887 asprintf(&tmp, "Backup medium is TAPE --- dev=%s",
888 bkpinfo->media_device);
889 log_msg(2, tmp);
890 paranoid_free(tmp);
891 } else {
892 paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
893 bkpinfo->media_size[0] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
894 bkpinfo->media_size[1] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
895 log_msg(2, "Backup medium is CD-R[W]");
896 }
897 } else {
898 log_msg(2,
899 "Not in Disaster Recovery Mode. No need to derive device name from config file.");
900 }
901
902 read_cfg_var(cfg_file, "use-star", value);
903 if (strstr(value, "yes")) {
904 bkpinfo->use_star = TRUE;
905 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
906 }
907 paranoid_free(value);
908
909 if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
910 bkpinfo->internal_tape_block_size = atol(value);
911 log_msg(1, "Internal tape block size has been custom-set to %ld",
912 bkpinfo->internal_tape_block_size);
913 } else {
914 bkpinfo->internal_tape_block_size =
915 DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
916 log_msg(1, "Internal tape block size = default (%ld)",
917 DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
918 }
919 paranoid_free(value);
920
921 read_cfg_var(cfg_file, "use-lzo", value);
922 if (strstr(value, "yes")) {
923 bkpinfo->use_lzo = TRUE;
924 paranoid_alloc(bkpinfo->zip_exe, "lzop");
925 paranoid_alloc(bkpinfo->zip_suffix, "lzo");
926 } else {
927 paranoid_free(value);
928 read_cfg_var(cfg_file, "use-comp", value);
929 if (strstr(value, "yes")) {
930 bkpinfo->use_lzo = FALSE;
931 paranoid_alloc(bkpinfo->zip_exe, "bzip2");
932 paranoid_alloc(bkpinfo->zip_suffix, "bz2");
933 } else {
934 // Just to be sure
935 bkpinfo->zip_exe = NULL;
936 bkpinfo->zip_suffix = NULL;
937 }
938 }
939 paranoid_free(value);
940
941 read_cfg_var(cfg_file, "differential", value);
942 if (!strcmp(value, "yes") || !strcmp(value, "1")) {
943 bkpinfo->differential = TRUE;
944 }
945 log_msg(2, "differential var = '%s'", value);
946 paranoid_free(value);
947
948 if (bkpinfo->differential) {
949 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
950 } else {
951 log_msg(2, "This is a regular (full) backup");
952 }
953
954 read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
955#ifdef __FreeBSD__
956 tmp1 = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
957#else
958 tmp1 = call_program_and_get_last_line_of_output("cat /proc/cmdline");
959#endif
960 if ((tmp != NULL) || strstr(tmp1,"donteject")) {
961 bkpinfo->please_dont_eject = TRUE;
962 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
963 }
964 paranoid_free(tmp);
965 paranoid_free(tmp1);
966
967 if (bkpinfo->backup_media_type == nfs) {
968 if (!cfgf) {
969 log_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount);
970 log_msg(2, "nfs_remote_dir remains %s",
971 bkpinfo->nfs_remote_dir);
972 log_msg(2,
973 "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
974 } else {
975 paranoid_free(bkpinfo->nfs_mount);
976 paranoid_free(bkpinfo->nfs_remote_dir);
977 read_cfg_var(g_mondo_cfg_file, "nfs-server-mount",
978 bkpinfo->nfs_mount);
979 read_cfg_var(g_mondo_cfg_file, "nfs-server-path",
980 bkpinfo->nfs_remote_dir);
981 log_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount);
982 log_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir);
983 }
984 /* We need to override values in PXE mode as it's
985 * already done in start-nfs */
986 if (strstr(call_program_and_get_last_line_of_output
987 ("cat /proc/cmdline"), "pxe")) {
988 strcpy(bkpinfo->nfs_mount,getenv("nfsmount"));
989 strcpy(bkpinfo->nfs_remote_dir,getenv("dirimg"));
990 }
991 } else if (bkpinfo->backup_media_type == iso) {
992 /* Patch by Conor Daly 23-june-2004
993 * to correctly mount iso-dev and set a sensible
994 * isodir in disaster recovery mode
995 */
996 paranoid_alloc(old_isodir,bkpinfo->isodir);
997 read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
998 read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
999 if (iso_mnt && iso_path) {
1000 paranoid_free(bkpinfo->isodir);
1001 asprintf(&bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1002 }
1003 paranoid_free(iso_mnt);
1004 paranoid_free(iso_path);
1005
1006 if (!bkpinfo->disaster_recovery) {
1007 if (strcmp(old_isodir, bkpinfo->isodir)) {
1008 log_it
1009 ("user nominated isodir differs from archive, keeping user's choice: %s %s\n",
1010 old_isodir, bkpinfo->isodir);
1011 }
1012 }
1013 paranoid_free(old_isodir);
1014
1015 paranoid_free(g_isodir_device);
1016 read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
1017 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
1018 if (bkpinfo->disaster_recovery) {
1019 if (is_this_device_mounted(g_isodir_device)) {
1020 log_msg(2, "NB: isodir is already mounted");
1021 /* Find out where it's mounted */
1022 asprintf(&command,
1023 "mount | grep -w %s | tail -n1 | cut -d' ' -f3",
1024 g_isodir_device);
1025 log_it("command = %s", command);
1026 tmp = call_program_and_get_last_line_of_output(command);
1027 log_it("res of it = %s", tmp);
1028 iso_mnt = tmp;
1029 paranoid_free(command);
1030 } else {
1031 asprintf(&iso_mnt, "/tmp/isodir");
1032 asprintf(&tmp, "mkdir -p %s", iso_mnt);
1033 run_program_and_log_output(tmp, 5);
1034 paranoid_free(tmp);
1035
1036 asprintf(&tmp, "mount %s %s", g_isodir_device, iso_mnt);
1037 if (run_program_and_log_output(tmp, 3)) {
1038 log_msg(1,
1039 "Unable to mount isodir. Perhaps this is really a CD backup?");
1040 bkpinfo->backup_media_type = cdr;
1041 paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
1042 paranoid_free(bkpinfo->isodir);
1043 paranoid_free(iso_mnt);
1044 paranoid_free(iso_path);
1045 asprintf(&iso_mnt, "%s", "");
1046 asprintf(&iso_path, "%s", "");
1047
1048 if (mount_cdrom(bkpinfo)) {
1049 fatal_error
1050 ("Unable to mount isodir. Failed to mount CD-ROM as well.");
1051 } else {
1052 log_msg(1,
1053 "You backed up to disk, then burned some CDs.");
1054 }
1055 }
1056 paranoid_free(tmp);
1057 }
1058 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1059 if (bkpinfo->backup_media_type == iso) {
1060 paranoid_free(bkpinfo->isodir);
1061 asprintf(&bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1062 }
1063 paranoid_free(iso_mnt);
1064 paranoid_free(iso_path);
1065 }
1066 }
1067
1068 if (media_specified_by_user != none) {
1069 if (g_restoring_live_from_cd) {
1070 if (bkpinfo->backup_media_type != media_specified_by_user) {
1071 log_msg(2,
1072 "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1073 interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
1074 media_specified_by_user = bkpinfo->backup_media_type;
1075 get_cfg_file_from_archive(bkpinfo);
1076/*
1077 if (media_specified_by_user != cdr && media_specified_by_user == cdrw)
1078 { g_restoring_live_from_cd = FALSE; }
1079*/
1080 }
1081 }
1082 bkpinfo->backup_media_type = media_specified_by_user;
1083 }
1084 g_backup_media_type = bkpinfo->backup_media_type;
1085 bkpinfo->backup_media_string = bkptype_to_string(bkpinfo->backup_media_type);
1086 g_backup_media_string = bkpinfo->backup_media_string;
1087 return (0);
1088}
1089/**************************************************************************
1090 *END_READ_CFG_FILE_INTO_BKPINFO *
1091 **************************************************************************/
1092
1093
1094/**
1095 * Allow the user to edit the filelist and biggielist.
1096 * The filelist is unlinked after it is read.
1097 * @param bkpinfo The backup information structure. Fields used:
1098 * - @c bkpinfo->backup_media_type
1099 * - @c bkpinfo->isodir
1100 * - @c bkpinfo->media_device
1101 * - @c bkpinfo->tmpdir
1102 * @return The filelist structure containing the information read from disk.
1103 */
1104struct
1105s_node *process_filelist_and_biggielist(struct s_bkpinfo *bkpinfo)
1106{
1107 struct s_node *filelist;
1108
1109 char *command = NULL;
1110 char *tmp = NULL;
1111 int res = 0;
1112 size_t n = 0;
1113 pid_t pid;
1114
1115 assert(bkpinfo != NULL);
1116 malloc_string(tmp);
1117
1118 if (does_file_exist(g_filelist_full)
1119 && does_file_exist(g_biggielist_txt)) {
1120 log_msg(1, "%s exists", g_filelist_full);
1121 log_msg(1, "%s exists", g_biggielist_txt);
1122 log_msg(2,
1123 "Filelist and biggielist already recovered from media. Yay!");
1124 } else {
1125 getcwd(tmp, MAX_STR_LEN);
1126 chdir(bkpinfo->tmpdir);
1127 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1128 log_to_screen("Extracting filelist and biggielist from media...");
1129 unlink("/tmp/filelist.full");
1130 unlink("/" FILELIST_FULL_STUB);
1131 unlink("/tmp/i-want-my-lvm");
1132 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1133 asprintf(&command,
1134 "tar -zxf %s %s %s %s %s %s",
1135 bkpinfo->media_device,
1136 MOUNTLIST_FNAME_STUB,
1137 BIGGIELIST_TXT_STUB,
1138 FILELIST_FULL_STUB,
1139 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1140 log_msg(1, "tarcommand = %s", command);
1141 run_program_and_log_output(command, 1);
1142 paranoid_free(command);
1143 } else {
1144 log_msg(2,
1145 "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1146 bkpinfo->isodir);
1147 insist_on_this_cd_number(bkpinfo, 1);
1148 log_msg(2, "Back from iotcn");
1149 run_program_and_log_output("mount", 1);
1150 asprintf(&command,
1151 "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1152 MNT_CDROM,
1153 MOUNTLIST_FNAME_STUB,
1154 BIGGIELIST_TXT_STUB,
1155 FILELIST_FULL_STUB,
1156 "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1157
1158 log_msg(1, "tarcommand = %s", command);
1159 run_program_and_log_output(command, 1);
1160 paranoid_free(command);
1161
1162 if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1163 fatal_error
1164 ("all.tar.gz did not include tmp/biggielist.txt");
1165 }
1166 if (!does_file_exist(FILELIST_FULL_STUB)) {
1167 fatal_error
1168 ("all.tar.gz did not include tmp/filelist.full.gz");
1169 }
1170 }
1171 asprintf(&command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1172 g_mondo_cfg_file);
1173 run_program_and_log_output(command, FALSE);
1174 paranoid_free(command);
1175
1176 asprintf(&command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1177 BIGGIELIST_TXT_STUB, g_biggielist_txt);
1178 log_msg(1, "command = %s", command);
1179 paranoid_system(command);
1180 paranoid_free(command);
1181
1182 asprintf(&command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1183 FILELIST_FULL_STUB, g_filelist_full);
1184 log_msg(1, "command = %s", command);
1185 paranoid_system(command);
1186 paranoid_free(command);
1187 }
1188
1189 if (am_I_in_disaster_recovery_mode()
1190 &&
1191 ask_me_yes_or_no(_
1192 ("Do you want to retrieve the mountlist as well?")))
1193 {
1194 asprintf(&command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1195 bkpinfo->tmpdir);
1196 paranoid_system(command);
1197 paranoid_free(command);
1198 }
1199
1200 chdir(tmp);
1201 paranoid_free(tmp);
1202
1203 if (!does_file_exist(g_biggielist_txt)) {
1204 log_msg(1, "Warning - %s not found", g_biggielist_txt);
1205 }
1206 if (!does_file_exist(g_filelist_full)) {
1207 log_msg(1, "Warning - %s does not exist", g_filelist_full);
1208 }
1209// popup_and_OK("Wonderful.");
1210
1211 log_msg(2, "Forking");
1212 pid = fork();
1213 switch (pid) {
1214 case -1:
1215 fatal_error("Forking error");
1216 break;
1217
1218 case 0:
1219 log_to_screen(("Pre-processing filelist"));
1220 if (!does_file_exist(g_biggielist_txt)) {
1221 asprintf(&command, "> %s", g_biggielist_txt);
1222 paranoid_system(command);
1223 paranoid_free(command);
1224 }
1225 asprintf(&command, "grep -x \"/dev/.*\" %s > %s",
1226 g_biggielist_txt, g_filelist_imagedevs);
1227 paranoid_system(command);
1228 paranoid_free(command);
1229 exit(0);
1230 break;
1231
1232 default:
1233 open_evalcall_form(_("Pre-processing filelist"));
1234 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1235 usleep(100000);
1236 update_evalcall_form(0);
1237 }
1238 }
1239 close_evalcall_form();
1240
1241 log_msg(3, "loading filelist");
1242 filelist = load_filelist(g_filelist_full);
1243 log_msg(3, "deleting original filelist");
1244 unlink(g_filelist_full);
1245 if (g_text_mode) {
1246 printf(_("Restore which directory? --> "));
1247 getline(&tmp, &n, stdin);
1248 toggle_path_selection(filelist, tmp, TRUE);
1249 if (strlen(tmp) == 0) {
1250 res = 1;
1251 } else {
1252 res = 0;
1253 }
1254 paranoid_free(tmp);
1255 } else {
1256 res = edit_filelist(filelist);
1257 }
1258 if (res) {
1259 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1260 free_filelist(filelist);
1261 return (NULL);
1262 }
1263 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1264 close_evalcall_form();
1265
1266 // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1267 // file. The filelist.full file already contains the filename of EVERY
1268 // file backed up - regular and biggie files.
1269
1270 // However, we do want to make sure the imagedevs selected by the user
1271 // are flagged for restoring.
1272 if (length_of_file(g_imagedevs_restthese) > 2) {
1273 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1274 TRUE);
1275 }
1276 return (filelist);
1277}
1278/**************************************************************************
1279 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1280 **************************************************************************/
1281
1282
1283/**
1284 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1285 * The backup filename is the filename of the original with ".pristine" added.
1286 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1287 * @param filename The filename (absolute path) within @p path_root.
1288 * @return 0 for success, nonzero for failure.
1289 */
1290int backup_crucial_file(char *path_root, char *filename)
1291{
1292 char *command = NULL;
1293 int res = 0;
1294
1295 assert(path_root != NULL);
1296 assert_string_is_neither_NULL_nor_zerolength(filename);
1297
1298 asprintf(&command, "cp -f %s/%s %s/%s.pristine", path_root, filename,path_root, filename);
1299 res = run_program_and_log_output(command, 5);
1300 paranoid_free(command);
1301 return (res);
1302}
1303
1304
1305/**
1306 * Install the user's boot loader in the MBR.
1307 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1308 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1309 * @return 0 for success, nonzero for failure.
1310 */
1311int run_boot_loader(bool offer_to_hack_scripts)
1312{
1313 int res;
1314 int retval = 0;
1315
1316 char *device = NULL;
1317 char *tmp = NULL;
1318 char *name = NULL;
1319
1320 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1321 backup_crucial_file(MNT_RESTORING, "/etc/grub.conf");
1322 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1323 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1324 read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1325 read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1326 asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1327 log_msg(2, tmp);
1328 paranoid_free(tmp);
1329
1330 sync();
1331 if (!strcmp(name, "LILO")) {
1332 res = run_lilo(offer_to_hack_scripts);
1333 } else if (!strcmp(name, "ELILO")) {
1334 res = run_elilo(offer_to_hack_scripts);
1335 } else if (!strcmp(name, "GRUB")) {
1336// 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?")))
1337// {
1338 res = run_grub(offer_to_hack_scripts, device);
1339// unlink(DO_MBR_PLEASE);
1340// }
1341// else
1342// {
1343// log_msg(1, "Not running run_grub(). Was a bad idea anyway.");
1344// res = 1;
1345// }
1346 } else if (!strcmp(name, "RAW")) {
1347 res = run_raw_mbr(offer_to_hack_scripts, device);
1348 }
1349#ifdef __FreeBSD__
1350 else if (!strcmp(name, "BOOT0")) {
1351 asprintf(&tmp, "boot0cfg -B %s", device);
1352 res = run_program_and_log_output(tmp, FALSE);
1353 paranoid_free(tmp);
1354 } else {
1355 asprintf(&tmp, "ls /dev | grep -xq %ss[1-4].*", device);
1356 if (!system(tmp)) {
1357 paranoid_free(tmp);
1358 asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1359 res = run_program_and_log_output(tmp, 3);
1360 } else {
1361 log_msg(1,
1362 "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1363 }
1364 paranoid_free(tmp);
1365 }
1366#else
1367 else {
1368 log_to_screen
1369 (_
1370 ("Unable to determine type of boot loader. Defaulting to LILO."));
1371 res = run_lilo(offer_to_hack_scripts);
1372 }
1373#endif
1374 paranoid_free(device);
1375 paranoid_free(name);
1376
1377 retval += res;
1378 if (res) {
1379 log_to_screen(_("Your boot loader returned an error"));
1380 } else {
1381 log_to_screen(_("Your boot loader ran OK"));
1382 }
1383 return (retval);
1384}
1385/**************************************************************************
1386 *END_ RUN_BOOT_LOADER *
1387 **************************************************************************/
1388
1389
1390/**
1391 * Attempt to find the user's editor.
1392 * @return The editor found ("vi" if none could be found).
1393 * @note The returned string points to malloced storage that needs to be freed by caller
1394 */
1395char *find_my_editor(void)
1396{
1397 char *output = NULL;
1398 char *tmp = NULL;
1399
1400 /* BERLIOS: This should use $EDITOR + conf file rather first */
1401 tmp = find_home_of_exe("pico");
1402 if (tmp) {
1403 asprintf(&output, "pico");
1404 } else {
1405 tmp = find_home_of_exe("nano");
1406 if (tmp) {
1407 asprintf(&output, "nano");
1408 } else {
1409 tmp = find_home_of_exe("vi");
1410 if (tmp) {
1411 asprintf(&output, "vi");
1412 } else {
1413 asprintf(&output, "emacs");
1414 }
1415 }
1416 }
1417 paranoid_free(tmp);
1418
1419 tmp = find_home_of_exe(output);
1420 if (!tmp) {
1421 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1422 }
1423 paranoid_free(tmp);
1424 return (output);
1425}
1426
1427
1428/**
1429 * Install GRUB on @p bd.
1430 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1431 * @param bd The boot device where GRUB is installed.
1432 * @return 0 for success, nonzero for failure.
1433 */
1434int run_grub(bool offer_to_run_stabgrub, char *bd)
1435{
1436 char *command = NULL;
1437 char *tmp = NULL;
1438 char *editor = NULL;
1439
1440 int res = 0;
1441 int done = 0;
1442
1443 assert_string_is_neither_NULL_nor_zerolength(bd);
1444
1445 if (offer_to_run_stabgrub
1446 && ask_me_yes_or_no(_("Did you change the mountlist?")))
1447 /* interactive mode */
1448 {
1449 mvaddstr_and_log_it(g_currentY,
1450 0,
1451 _
1452 ("Modifying fstab and grub.conf, and running GRUB... "));
1453 for (done = FALSE; !done;) {
1454 popup_and_get_string(_("Boot device"),
1455 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), bd);
1456 asprintf(&command, "stabgrub-me %s", bd);
1457 res = run_program_and_log_output(command, 1);
1458 paranoid_free(command);
1459
1460 if (res) {
1461 popup_and_OK
1462 (_
1463 ("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."));
1464 newtSuspend();
1465 system("chroot " MNT_RESTORING);
1466 newtResume();
1467 popup_and_OK(_("Thank you."));
1468 } else {
1469 done = TRUE;
1470 }
1471 popup_and_OK(_("You will now edit fstab and grub.conf"));
1472 if (!g_text_mode) {
1473 newtSuspend();
1474 }
1475 editor = find_my_editor();
1476 asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1477 paranoid_system(tmp);
1478 paranoid_free(tmp);
1479
1480 asprintf(&tmp, "%s " MNT_RESTORING "/etc/grub.conf", editor);
1481 paranoid_free(editor);
1482
1483 paranoid_system(tmp);
1484 paranoid_free(tmp);
1485
1486 if (!g_text_mode) {
1487 newtResume();
1488 }
1489 }
1490 } else {
1491 /* nuke mode */
1492 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1493 log_msg(1, "Yay! grub-MR found...");
1494 asprintf(&command, "grub-MR %s /tmp/mountlist.txt", bd);
1495 log_msg(1, "command = %s", command);
1496 } else {
1497 asprintf(&command, "chroot " MNT_RESTORING " grub-install %s", bd);
1498 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1499 }
1500 mvaddstr_and_log_it(g_currentY,
1501 0,
1502 _
1503 ("Running GRUB... "));
1504 iamhere(command);
1505 res = run_program_and_log_output(command, 1);
1506 paranoid_free(command);
1507
1508 if (res) {
1509 popup_and_OK
1510 (_
1511 ("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."));
1512 newtSuspend();
1513 system("chroot " MNT_RESTORING);
1514 newtResume();
1515 popup_and_OK(_("Thank you."));
1516 }
1517 }
1518 if (res) {
1519 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1520 log_to_screen
1521 (_
1522 ("GRUB ran w/error(s). See /tmp/mondo-restore.log for more info."));
1523 log_msg(1, "Type:-");
1524 log_msg(1, " mount-me");
1525 log_msg(1, " chroot " MNT_RESTORING);
1526 log_msg(1, " mount /boot");
1527 log_msg(1, " grub-install '(hd0)'");
1528 log_msg(1, " exit");
1529 log_msg(1, " unmount-me");
1530 log_msg(1,
1531 "If you're really stuck, please e-mail the mailing list.");
1532 } else {
1533 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1534 }
1535 return (res);
1536}
1537/**************************************************************************
1538 *END_RUN_GRUB *
1539 **************************************************************************/
1540
1541
1542/**
1543 * Install ELILO on the user's boot drive (determined by elilo.conf).
1544 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1545 * @return 0 for success, nonzero for failure.
1546 */
1547int run_elilo(bool offer_to_run_stabelilo)
1548{
1549 char *command = NULL;
1550 char *tmp = NULL;
1551 char *editor = NULL;
1552
1553 int res = 0;
1554 int done = 0;
1555
1556 if (offer_to_run_stabelilo
1557 && ask_me_yes_or_no(_("Did you change the mountlist?")))
1558
1559 /* interactive mode */
1560 {
1561 mvaddstr_and_log_it(g_currentY,
1562 0,
1563 _
1564 ("Modifying fstab and elilo.conf... "));
1565 asprintf(&command, "stabelilo-me");
1566 res = run_program_and_log_output(command, 3);
1567 paranoid_free(command);
1568
1569 if (res) {
1570 popup_and_OK
1571 (_
1572 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist."));
1573 for (done = FALSE; !done;) {
1574 if (!g_text_mode) {
1575 newtSuspend();
1576 }
1577 editor = find_my_editor();
1578 asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1579 paranoid_system(tmp);
1580 paranoid_free(tmp);
1581
1582 asprintf(&tmp, "%s " MNT_RESTORING "/etc/elilo.conf", editor);
1583 paranoid_free(editor);
1584
1585 paranoid_system(tmp);
1586 paranoid_free(tmp);
1587
1588 if (!g_text_mode) {
1589 newtResume();
1590 }
1591// newtCls();
1592 if (ask_me_yes_or_no(_("Edit them again?"))) {
1593 continue;
1594 }
1595 done = TRUE;
1596 }
1597 } else {
1598 log_to_screen(_("elilo.conf and fstab were modified OK"));
1599 }
1600 } else
1601 /* nuke mode */
1602 {
1603 res = TRUE;
1604 }
1605 return (res);
1606}
1607/**************************************************************************
1608 *END_RUN_ELILO *
1609 **************************************************************************/
1610
1611
1612/**
1613 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1614 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1615 * @return 0 for success, nonzero for failure.
1616 */
1617int run_lilo(bool offer_to_run_stablilo)
1618{
1619 /** malloc **/
1620 char *command = NULL;
1621 char *tmp = NULL;
1622 char *editor = NULL;
1623
1624 int res = 0;
1625 int done = 0;
1626 bool run_lilo_M = FALSE;
1627
1628 if (!run_program_and_log_output
1629 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1630 run_lilo_M = TRUE;
1631 }
1632
1633 if (offer_to_run_stablilo
1634 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1635 /* interactive mode */
1636 mvaddstr_and_log_it(g_currentY,
1637 0,
1638 _
1639 ("Modifying fstab and lilo.conf, and running LILO... "));
1640 asprintf(&command, "stablilo-me");
1641 res = run_program_and_log_output(command, 3);
1642 paranoid_free(command);
1643
1644 if (res) {
1645 popup_and_OK
1646 (_
1647 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."));
1648 for (done = FALSE; !done;) {
1649 if (!g_text_mode) {
1650 newtSuspend();
1651 }
1652 editor = find_my_editor();
1653 asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1654 paranoid_system(tmp);
1655 paranoid_free(tmp);
1656
1657 asprintf(&tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1658 paranoid_free(editor);
1659
1660 paranoid_system(tmp);
1661 paranoid_free(tmp);
1662
1663 if (!g_text_mode) {
1664 newtResume();
1665 }
1666// newtCls();
1667 if (ask_me_yes_or_no(_("Edit them again?"))) {
1668 continue;
1669 }
1670 res =
1671 run_program_and_log_output("chroot " MNT_RESTORING
1672 " lilo -L", 3);
1673 if (res) {
1674 res =
1675 run_program_and_log_output("chroot " MNT_RESTORING
1676 " lilo", 3);
1677 }
1678 if (res) {
1679 done =
1680 ask_me_yes_or_no
1681 (_("LILO failed. Re-edit system files?"));
1682 } else {
1683 done = TRUE;
1684 }
1685 }
1686 } else {
1687 log_to_screen(_("lilo.conf and fstab were modified OK"));
1688 }
1689 } else {
1690 /* nuke mode */
1691 mvaddstr_and_log_it(g_currentY,
1692 0,
1693 _
1694 ("Running LILO... "));
1695 res =
1696 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1697 3);
1698 if (res) {
1699 res =
1700 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1701 3);
1702 }
1703 if (res) {
1704 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1705 log_to_screen
1706 (_
1707 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."));
1708 } else {
1709 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1710 }
1711 }
1712 if (run_lilo_M) {
1713 run_program_and_log_output("chroot " MNT_RESTORING
1714 " lilo -M /dev/hda", 3);
1715 run_program_and_log_output("chroot " MNT_RESTORING
1716 " lilo -M /dev/sda", 3);
1717 }
1718 return (res);
1719}
1720
1721/**************************************************************************
1722 *END_RUN_LILO *
1723 **************************************************************************/
1724
1725
1726/**
1727 * Install a raw MBR onto @p bd.
1728 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1729 * @param bd The device to copy the stored MBR to.
1730 * @return 0 for success, nonzero for failure.
1731 */
1732int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1733{
1734 char *command = NULL;
1735 char *tmp = NULL;
1736 char *editor = NULL;
1737 int res = 0;
1738 int done = 0;
1739
1740 assert_string_is_neither_NULL_nor_zerolength(bd);
1741
1742 if (offer_to_hack_scripts
1743 && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1744 /* interactive mode */
1745 mvaddstr_and_log_it(g_currentY, 0,
1746 _
1747 ("Modifying fstab and restoring MBR... "));
1748 for (done = FALSE; !done;) {
1749 if (!run_program_and_log_output("which vi", FALSE)) {
1750 popup_and_OK(_("You will now edit fstab"));
1751 if (!g_text_mode) {
1752 newtSuspend();
1753 }
1754 editor = find_my_editor();
1755 asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1756 paranoid_free(editor);
1757
1758 paranoid_system(tmp);
1759 paranoid_free(tmp);
1760
1761 if (!g_text_mode) {
1762 newtResume();
1763 }
1764// newtCls();
1765 }
1766 popup_and_get_string(_("Boot device"),
1767 _
1768 ("Please confirm/enter the boot device. If in doubt, try /dev/hda"), bd);
1769 asprintf(&command, "stabraw-me %s", bd);
1770 res = run_program_and_log_output(command, 3);
1771 paranoid_free(command);
1772
1773 if (res) {
1774 done =
1775 ask_me_yes_or_no(_("Modifications failed. Re-try?"));
1776 } else {
1777 done = TRUE;
1778 }
1779 }
1780 } else {
1781 /* nuke mode */
1782 mvaddstr_and_log_it(g_currentY, 0,
1783 _
1784 ("Restoring MBR... "));
1785 asprintf(&command, "raw-MR %s /tmp/mountlist.txt", bd);
1786 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1787 res = run_program_and_log_output(command, 3);
1788 paranoid_free(command);
1789 }
1790 if (res) {
1791 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1792 log_to_screen
1793 (_
1794 ("MBR+fstab processed w/error(s). See /tmp/mondo-restore.log for more info."));
1795 } else {
1796 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1797 }
1798 return (res);
1799}
1800/**************************************************************************
1801 *END_RUN_RAW_MBR *
1802 **************************************************************************/
1803
1804
1805/**
1806 * Turn signal trapping on or off.
1807 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1808 * print a message and exit immediately.
1809 */
1810void set_signals(int on)
1811{
1812 int signals[] =
1813 { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1814 SIGSTOP, 0
1815 };
1816 int i;
1817 for (i = 0; signals[i]; i++) {
1818 if (on) {
1819 signal(signals[i], terminate_daemon);
1820 } else {
1821 signal(signals[i], termination_in_progress);
1822 }
1823 }
1824}
1825
1826/**************************************************************************
1827 *END_SET_SIGNALS *
1828 **************************************************************************/
1829
1830
1831/**
1832 * malloc() and set sensible defaults for the mondorestore filename variables.
1833 * @param bkpinfo The backup information structure. Fields used:
1834 * - @c bkpinfo->tmpdir
1835 * - @c bkpinfo->disaster_recovery
1836 */
1837void setup_MR_global_filenames(struct s_bkpinfo *bkpinfo)
1838{
1839 assert(bkpinfo != NULL);
1840
1841 asprintf(&g_biggielist_txt, "%s/%s",bkpinfo->tmpdir , BIGGIELIST_TXT_STUB);
1842 asprintf(&g_filelist_full, "%s/%s", bkpinfo->tmpdir, FILELIST_FULL_STUB);
1843 asprintf(&g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1844 asprintf(&g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1845 bkpinfo->tmpdir);
1846 paranoid_free(g_mondo_cfg_file);
1847 paranoid_free(g_mountlist_fname);
1848 if (bkpinfo->disaster_recovery) {
1849 asprintf(&g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1850 asprintf(&g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1851 } else {
1852 asprintf(&g_mondo_cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
1853 asprintf(&g_mountlist_fname, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
1854 }
1855}
1856/**************************************************************************
1857 *END_SET_GLOBAL_FILENAME *
1858 **************************************************************************/
1859
1860
1861/**
1862 * Copy @p input_file (containing the result of a compare) to @p output_file,
1863 * deleting spurious "changes" along the way.
1864 * @param output_file The output file to write with spurious changes removed.
1865 * @param input_file The input file, a list of changed files created by a compare.
1866 */
1867void streamline_changes_file(char *output_file, char *input_file)
1868{
1869 FILE *fin;
1870 FILE *fout;
1871 char *incoming = NULL;
1872 size_t n = 0;
1873
1874 assert_string_is_neither_NULL_nor_zerolength(output_file);
1875 assert_string_is_neither_NULL_nor_zerolength(input_file);
1876
1877 if (!(fin = fopen(input_file, "r"))) {
1878 log_OS_error(input_file);
1879 return;
1880 }
1881 if (!(fout = fopen(output_file, "w"))) {
1882 fatal_error("cannot open output_file");
1883 }
1884 for (getline(&incoming, &n, fin); !feof(fin);
1885 getline(&incoming, &n, fin)) {
1886 if (strncmp(incoming, "etc/adjtime", 11)
1887 && strncmp(incoming, "etc/mtab", 8)
1888 && strncmp(incoming, "tmp/", 4)
1889 && strncmp(incoming, "boot/map", 8)
1890 && !strstr(incoming, "incheckentry")
1891 && strncmp(incoming, "etc/mail/statistics", 19)
1892 && strncmp(incoming, "var/", 4))
1893 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1894 }
1895 paranoid_free(incoming);
1896 paranoid_fclose(fout);
1897 paranoid_fclose(fin);
1898}
1899/**************************************************************************
1900 *END_STREAMLINE_CHANGES_FILE *
1901 **************************************************************************/
1902
1903
1904/**
1905 * Exit due to a signal (normal cleanup).
1906 * @param sig The signal we're exiting due to.
1907 */
1908void terminate_daemon(int sig)
1909{
1910 log_to_screen
1911 (_
1912 ("Mondorestore is terminating in response to a signal from the OS"));
1913 paranoid_MR_finish(254);
1914}
1915/**************************************************************************
1916 *END_TERMINATE_DAEMON *
1917 **************************************************************************/
1918
1919
1920/**
1921 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1922 */
1923void twenty_seconds_til_yikes()
1924{
1925 int i;
1926 char *tmp = NULL;
1927
1928 if (does_file_exist("/tmp/NOPAUSE")) {
1929 return;
1930 }
1931 open_progress_form(_("CAUTION"),
1932 _
1933 ("Be advised: I am about to ERASE your hard disk(s)!"),
1934 _("You may press Ctrl+Alt+Del to abort safely."),
1935 "", 20);
1936 for (i = 0; i < 20; i++) {
1937 g_current_progress = i;
1938 asprintf(&tmp, _("You have %d seconds left to abort."), 20 - i);
1939 update_progress_form(tmp);
1940 paranoid_free(tmp);
1941 sleep(1);
1942 }
1943 close_progress_form();
1944}
1945/**************************************************************************
1946 *END_TWENTY_SECONDS_TIL_YIKES *
1947 **************************************************************************/
1948
1949
1950/**
1951 * Exit due to a signal (no cleanup).
1952 * @param sig The signal we're exiting due to.
1953 */
1954void termination_in_progress(int sig)
1955{
1956 log_msg(1, "Termination in progress");
1957 usleep(1000);
1958 pthread_exit(0);
1959}
1960/**************************************************************************
1961 *END_TERMINATION_IN_PROGRESS *
1962 **************************************************************************/
1963
1964
1965/**
1966 * Unmount all devices in @p p_external_copy_of_mountlist.
1967 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1968 * @return 0 for success, nonzero for failure.
1969 */
1970int unmount_all_devices(struct mountlist_itself
1971 *p_external_copy_of_mountlist)
1972{
1973 struct mountlist_itself *mountlist;
1974 int retval = 0;
1975 int lino = 0;
1976 int res = 0;
1977 int i = 0;
1978 char *command = NULL;
1979 char *tmp = NULL;
1980 char *tmp1 = NULL;
1981
1982 assert(p_external_copy_of_mountlist != NULL);
1983
1984 mountlist = malloc(sizeof(struct mountlist_itself));
1985 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1986 sizeof(struct mountlist_itself));
1987 sort_mountlist_by_mountpoint(mountlist, 0);
1988
1989 run_program_and_log_output("df -m", 3);
1990 mvaddstr_and_log_it(g_currentY, 0, _("Unmounting devices "));
1991 open_progress_form(_("Unmounting devices"),
1992 _("Unmounting all devices that were mounted,"),
1993 _
1994 ("in preparation for the post-restoration reboot."),
1995 "", mountlist->entries);
1996 chdir("/");
1997 for (i = 0;
1998 i < 10
1999 &&
2000 run_program_and_log_output
2001 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
2002 i++) {
2003 sleep(1);
2004 log_msg(2, "Waiting for buffer() to finish");
2005 }
2006
2007 sync();
2008
2009 if (run_program_and_log_output
2010 ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/tmp/", FALSE)) {
2011 log_msg(1,
2012 "Error. Failed to copy log to PC's /tmp dir. (Mounted read-only?)");
2013 }
2014 if (run_program_and_log_output
2015 ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/root/", FALSE)) {
2016 log_msg(1,
2017 "Error. Failed to copy log to PC's /root dir. (Mounted read-only?)");
2018 }
2019 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
2020 run_program_and_log_output("mkdir -p " MNT_RESTORING
2021 "/mnt/.boot.d", 5);
2022 }
2023 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
2024 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2025 continue;
2026 }
2027 asprintf(&tmp, _("Unmounting device %s "),
2028 mountlist->el[lino].device);
2029
2030 update_progress_form(tmp);
2031
2032 if (is_this_device_mounted(mountlist->el[lino].device)) {
2033 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2034 asprintf(&command, "swapoff %s", mountlist->el[lino].device);
2035 } else {
2036 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2037 asprintf(&command, "umount %s/", MNT_RESTORING);
2038 log_msg(3,
2039 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2040 } else {
2041 asprintf(&command, "umount " MNT_RESTORING "%s",
2042 mountlist->el[lino].mountpoint);
2043 }
2044 }
2045 log_msg(10, "The 'umount' command is '%s'", command);
2046 res = run_program_and_log_output(command, 3);
2047 paranoid_free(command);
2048 } else {
2049 asprintf(&tmp1, "%s%s", tmp, _("...not mounted anyway :-) OK"));
2050 paranoid_free(tmp);
2051 tmp = tmp1;
2052 res = 0;
2053 }
2054 g_current_progress++;
2055 if (res) {
2056 asprintf(&tmp1, "%s%s", tmp, _("...Failed"));
2057 paranoid_free(tmp);
2058 tmp = tmp1;
2059 retval++;
2060 log_to_screen(tmp);
2061 } else {
2062 log_msg(2, tmp);
2063 }
2064 paranoid_free(tmp);
2065 }
2066 close_progress_form();
2067 if (retval) {
2068 mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
2069 } else {
2070 mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2071 }
2072 if (retval) {
2073 log_to_screen(_("Unable to unmount some of your partitions."));
2074 } else {
2075 log_to_screen(_("All partitions were unmounted OK."));
2076 }
2077 free(mountlist);
2078 return (retval);
2079}
2080/**************************************************************************
2081 *END_UNMOUNT_ALL_DEVICES *
2082 **************************************************************************/
2083
2084
2085/**
2086 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2087 * to the ./tmp/ directory.
2088 * @param dev The tape device to read from.
2089 * @return 0 for success, nonzero for failure.
2090 */
2091int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2092{
2093 char *command = NULL;
2094 int res = 0;
2095 // BERLIOS: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2096 long tape_block_size = 32768;
2097
2098 // tar -zxvf-
2099 asprintf(&command,
2100 "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2101 dev,
2102 tape_block_size,
2103 1024L * 1024 * 32 / tape_block_size,
2104 MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2105 BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2106 log_msg(2, "command = '%s'", command);
2107 res = run_program_and_log_output(command, -1);
2108 paranoid_free(command);
2109
2110 if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2111 res = 0;
2112 }
2113 return (res);
2114}
2115
2116
2117/**
2118 * Get the configuration file from the floppy, tape, or CD.
2119 * @param bkpinfo The backup information structure. Fields used:
2120 * - @c bkpinfo->backup_media_type
2121 * - @c bkpinfo->media_device
2122 * - @c bkpinfo->tmpdir
2123 * @return 0 for success, nonzero for failure.
2124 */
2125int get_cfg_file_from_archive(struct s_bkpinfo *bkpinfo)
2126{
2127 int retval = 0;
2128 char *command = NULL;
2129 char *cfg_file = NULL;
2130 char *mounted_cfgf_path = NULL;
2131 char *tmp = NULL;
2132 char *tmp1 = NULL;
2133 char *sav = NULL;
2134 char *mountpt = NULL;
2135 char *ramdisk_fname = NULL;
2136 char *mountlist_file = NULL;
2137 int res = 0;
2138
2139 bool try_plan_B;
2140
2141 assert(bkpinfo != NULL);
2142 log_msg(2, "gcffa --- starting");
2143 log_to_screen(_("I'm thinking..."));
2144 asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2145 chdir(bkpinfo->tmpdir);
2146 // MONDO_CFG_FILE_STUB is missing the '/' at the start, FYI, by intent
2147 unlink(MONDO_CFG_FILE_STUB);
2148
2149 unlink(FILELIST_FULL_STUB);
2150 unlink(BIGGIELIST_TXT_STUB);
2151 unlink("tmp/i-want-my-lvm");
2152 asprintf(&command, "mkdir -p %s", mountpt);
2153 run_program_and_log_output(command, FALSE);
2154 paranoid_free(command);
2155
2156 asprintf(&cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2157 asprintf(&mountlist_file, "%s/%s", bkpinfo->tmpdir,
2158 MOUNTLIST_FNAME_STUB);
2159 log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2160
2161 /* Floppy? */
2162 asprintf(&tmp, "mkdir -p %s", mountpt);
2163 run_program_and_log_output(tmp, FALSE);
2164 paranoid_free(tmp);
2165
2166 asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2167 run_program_and_log_output(tmp, FALSE);
2168 paranoid_free(tmp);
2169
2170 asprintf(&command, "mount /dev/fd0u1722 %s", mountpt);
2171 asprintf(&tmp,
2172 "(sleep 15; kill `ps | grep \"%s\" | cut -d' ' -f1` 2> /dev/null) &",
2173 command);
2174 log_msg(1, "tmp = '%s'", tmp);
2175 system(tmp);
2176 paranoid_free(tmp);
2177
2178 res = run_program_and_log_output(command, FALSE);
2179 paranoid_free(command);
2180
2181 if (res) {
2182 asprintf(&command, "mount /dev/fd0H1440 %s", mountpt);
2183 res = run_program_and_log_output(command, FALSE);
2184 paranoid_free(command);
2185 }
2186 if (res) {
2187 try_plan_B = TRUE;
2188 } else {
2189 try_plan_B = TRUE;
2190 log_msg(2,
2191 "Mounted floppy OK but I don't trust it because the archives might contain more up-to-date config file than the floppy does.");
2192// NB: If busybox does not support 'mount -o loop' then Plan A WILL NOT WORK.
2193 log_msg(2, "Processing floppy (plan A?)");
2194 asprintf(&ramdisk_fname, "%s/mindi.rdz", mountpt);
2195 if (!does_file_exist(ramdisk_fname)) {
2196 paranoid_free(ramdisk_fname);
2197 asprintf(&ramdisk_fname, "%s/initrd.img", mountpt);
2198 }
2199 if (!does_file_exist(ramdisk_fname)) {
2200 log_msg(2,
2201 "Cannot find ramdisk file on mountpoint. Are you sure that's a boot disk in the drive?");
2202 }
2203 if (extract_config_file_from_ramdisk
2204 (bkpinfo, ramdisk_fname, cfg_file, mountlist_file)) {
2205 log_msg(2,
2206 "Warning - failed to extract config file from ramdisk. I think this boot disk is mangled.");
2207 }
2208 asprintf(&command, "umount %s", mountpt);
2209 run_program_and_log_output(command, 5);
2210 paranoid_free(command);
2211
2212 unlink(ramdisk_fname);
2213 paranoid_free(ramdisk_fname);
2214 }
2215 if (!does_file_exist(cfg_file)) {
2216 log_msg(2, "gcffa --- we don't have cfg file yet.");
2217 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2218 try_plan_B = TRUE;
2219 } else {
2220 log_msg(2, "gcffa --- calling mount_cdrom now :)");
2221 if (!mount_cdrom(bkpinfo)) {
2222 log_msg(2,
2223 "gcffa --- managed to mount CD; so, no need for Plan B");
2224 try_plan_B = FALSE;
2225 } else {
2226 try_plan_B = TRUE;
2227 }
2228 if (what_number_cd_is_this(bkpinfo) > 1) {
2229 insist_on_this_cd_number(bkpinfo,
2230 (g_current_media_number = 1));
2231 }
2232 }
2233 if (try_plan_B) {
2234 log_msg(2, "gcffa --- OK, switching to Plan B");
2235 chdir(bkpinfo->tmpdir);
2236 run_program_and_log_output("mkdir -p tmp", FALSE);
2237
2238 if (bkpinfo->media_device == NULL) {
2239 asprintf(&bkpinfo->media_device, "/dev/st0");
2240 log_msg(2, "media_device is blank; assuming %s",
2241 bkpinfo->media_device);
2242 }
2243 asprintf(&sav, bkpinfo->media_device);
2244 if (extract_cfg_file_and_mountlist_from_tape_dev
2245 (bkpinfo->media_device)) {
2246 paranoid_alloc(bkpinfo->media_device, "/dev/st0");
2247 if (extract_cfg_file_and_mountlist_from_tape_dev
2248 (bkpinfo->media_device)) {
2249 paranoid_alloc(bkpinfo->media_device, "/dev/osst0");
2250 if (extract_cfg_file_and_mountlist_from_tape_dev
2251 (bkpinfo->media_device)) {
2252 paranoid_alloc(bkpinfo->media_device, "/dev/ht0");
2253 if (extract_cfg_file_and_mountlist_from_tape_dev
2254 (bkpinfo->media_device)) {
2255 log_msg(3,
2256 "I tried lots of devices but none worked.");
2257 paranoid_alloc(bkpinfo->media_device, sav);
2258 }
2259 }
2260 }
2261 }
2262 paranoid_free(sav);
2263
2264 if (!does_file_exist("tmp/mondo-restore.cfg")) {
2265 log_to_screen(_
2266 ("Cannot find config info on tape/CD/floppy"));
2267 return (1);
2268 }
2269 } else {
2270 log_msg(2,
2271 "gcffa --- looking at mounted CD for mindi-boot.2880.img");
2272 /* BERLIOS : Useless ?
2273 asprintf(&command,
2274 "mount " MNT_CDROM
2275 "/images/mindi-boot.2880.img -o loop %s", mountpt);
2276 */
2277 asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2278 if (!does_file_exist(mounted_cfgf_path)) {
2279 log_msg(2,
2280 "gcffa --- Plan C, a.k.a. untarring some file from all.tar.gz");
2281 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
2282 run_program_and_log_output(command, TRUE);
2283 paranoid_free(command);
2284
2285 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2286 fatal_error
2287 ("Please reinsert the disk/CD and try again.");
2288 }
2289 }
2290 paranoid_free(mounted_cfgf_path);
2291 }
2292 }
2293 paranoid_free(mountpt);
2294
2295 if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2296 log_msg(1, "gcffa --- great! We've got the config file");
2297 tmp1 = call_program_and_get_last_line_of_output("pwd");
2298 asprintf(&tmp, "%s/%s", tmp1,MONDO_CFG_FILE_STUB);
2299 asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2300 iamhere(command);
2301
2302 if (strcmp(tmp, cfg_file)
2303 && run_program_and_log_output(command, 1)) {
2304 log_msg(1,
2305 "... but an error occurred when I tried to move it to %s",
2306 cfg_file);
2307 } else {
2308 log_msg(1, "... and I moved it successfully to %s", cfg_file);
2309 }
2310 paranoid_free(command);
2311
2312 asprintf(&command, "cp -f %s/%s %s",tmp1,
2313 MOUNTLIST_FNAME_STUB, mountlist_file);
2314 paranoid_free(tmp1);
2315
2316 iamhere(command);
2317 if (strcmp(tmp, cfg_file)
2318 && run_program_and_log_output(command, 1)) {
2319 log_msg(1, "Failed to get mountlist");
2320 } else {
2321 log_msg(1, "Got mountlist too");
2322 paranoid_free(command);
2323 asprintf(&command, "cp -f %s %s", mountlist_file,
2324 g_mountlist_fname);
2325 if (run_program_and_log_output(command, 1)) {
2326 log_msg(1, "Failed to copy mountlist to /tmp");
2327 } else {
2328 log_msg(1, "Copied mountlist to /tmp as well OK");
2329 paranoid_free(command);
2330 asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2331 run_program_and_log_output(command, 1);
2332 }
2333 }
2334 paranoid_free(command);
2335 paranoid_free(tmp);
2336 }
2337 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2338 if (!does_file_exist(cfg_file)) {
2339 iamhere(cfg_file);
2340 log_msg(1, "%s not found", cfg_file);
2341 log_to_screen
2342 (_
2343 ("Oh dear. Unable to recover configuration file from boot disk"));
2344 return (1);
2345 }
2346
2347 log_to_screen(_("Recovered mondo-restore.cfg"));
2348 if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2349 log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2350 }
2351/* start SAH */
2352 else {
2353 asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2354 bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2355 run_program_and_log_output(command, FALSE);
2356 paranoid_free(command);
2357 }
2358/* end SAH */
2359
2360 asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2361 paranoid_free(cfg_file);
2362
2363 run_program_and_log_output(command, FALSE);
2364 paranoid_free(command);
2365
2366 asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2367 paranoid_free(mountlist_file);
2368
2369 run_program_and_log_output(command, FALSE);
2370 paranoid_free(command);
2371
2372 asprintf(&command, "cp -f etc/raidtab /etc/");
2373 run_program_and_log_output(command, FALSE);
2374 paranoid_free(command);
2375
2376 asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2377 run_program_and_log_output(command, FALSE);
2378 paranoid_free(command);
2379
2380 g_backup_media_type = bkpinfo->backup_media_type;
2381 bkpinfo->backup_media_string = bkptype_to_string(bkpinfo->backup_media_type);
2382 g_backup_media_string = bkpinfo->backup_media_string;
2383 return (retval);
2384}
2385/**************************************************************************
2386 *END_GET_CFG_FILE_FROM_ARCHIVE *
2387 **************************************************************************/
2388/* @} - end restoreUtilityGroup */
2389
2390
2391void wait_until_software_raids_are_prepped(char *mdstat_file,
2392 int wait_for_percentage)
2393{
2394 struct raidlist_itself *raidlist = NULL;
2395 int unfinished_mdstat_devices = 9999, i = 0;
2396 char *screen_message = NULL;
2397
2398 raidlist = malloc(sizeof(struct raidlist_itself));
2399
2400 assert(wait_for_percentage <= 100);
2401 iamhere("wait_until_software_raids_are_prepped");
2402 while (unfinished_mdstat_devices > 0) {
2403 if (parse_mdstat(raidlist, "/dev/")) {
2404 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2405 log_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2406 return;
2407 }
2408 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries;
2409 i++) {
2410 if (raidlist->el[i].progress < wait_for_percentage) {
2411 unfinished_mdstat_devices++;
2412 log_msg(1, "Sync'ing %s (i=%d)",
2413 raidlist->el[i].raid_device, i);
2414 asprintf(&screen_message, "Sync'ing %s",
2415 raidlist->el[i].raid_device);
2416 open_evalcall_form(screen_message);
2417 paranoid_free(screen_message);
2418
2419 if (raidlist->el[i].progress == -1) { // delayed while another partition inits
2420 continue;
2421 }
2422 while (raidlist->el[i].progress < wait_for_percentage) {
2423 log_msg(1, "Percentage sync'ed: %d",
2424 raidlist->el[i].progress);
2425 update_evalcall_form(raidlist->el[i].progress);
2426 sleep(2);
2427 // FIXME: Prefix '/dev/' should really be dynamic!
2428 if (parse_mdstat(raidlist, "/dev/")) {
2429 break;
2430 }
2431 }
2432 close_evalcall_form();
2433 }
2434 }
2435 }
2436 paranoid_free(raidlist);
2437}
Note: See TracBrowser for help on using the repository browser.