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

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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