source: MondoRescue/branches/2.2.5/mondo/src/mondorestore/mondo-restore.c@ 1881

Last change on this file since 1881 was 1881, checked in by Bruno Cornec, 16 years ago

Should fix the problem with the prefix always asked at restore time, even when it's not NFS

  • Property svn:keywords set to Id
File size: 100.5 KB
Line 
1/***************************************************************************
2$Id: mondo-restore.c 1881 2008-01-27 20:25:35Z bruno $
3restores mondoarchive data
4***************************************************************************/
5
6/**
7 * @file
8 * The main file for mondorestore.
9 */
10
11/**************************************************************************
12 * #include statements *
13 **************************************************************************/
14#include <pthread.h>
15#include "../common/my-stuff.h"
16#include "../common/mondostructures.h"
17#include "../common/libmondo.h"
18#include "mr-externs.h"
19#include "mondo-restore.h"
20#include "mondorestore.h"
21#include "mondo-rstr-compare-EXT.h"
22#include "mondo-rstr-tools-EXT.h"
23
24extern void twenty_seconds_til_yikes(void);
25
26/* Reference to global bkpinfo */
27struct s_bkpinfo *bkpinfo;
28
29
30/* For use in other programs (ex. XMondo) */
31#ifdef MONDORESTORE_MODULE
32#define main __mondorestore_main
33#define g_ISO_restore_mode __mondorestore_g_ISO_restore_mode
34#endif
35
36//static char cvsid[] = "$Id: mondo-restore.c 1881 2008-01-27 20:25:35Z bruno $";
37
38/**************************************************************************
39 * Globals *
40 **************************************************************************/
41extern char *g_tmpfs_mountpt; // declared in libmondo-tools.c
42extern bool g_text_mode;
43extern FILE *g_fprep;
44extern double g_kernel_version;
45extern int g_partition_table_locked_up;
46extern int g_noof_rows;
47
48extern int partition_everything(struct mountlist_itself *mountlist);
49
50
51/**
52 * @name Restore-Time Globals
53 * @ingroup globalGroup
54 * @{
55 */
56/**
57 * If TRUE, then SIGPIPE was just caught.
58 * Set by the signal handler; cleared after it's handled.
59 */
60bool g_sigpipe_caught = FALSE;
61
62/**
63 * If TRUE, then we're restoring from ISOs or an NFS server.
64 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
65 */
66bool g_ISO_restore_mode = FALSE; /* are we in Iso Mode? */
67
68/**
69 * If TRUE, then we have had a successful "nuke" restore.
70 */
71bool g_I_have_just_nuked = FALSE;
72
73/**
74 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
75 */
76char *g_isodir_device;
77
78/**
79 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
80 */
81char *g_isodir_format;
82
83/**
84 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
85 */
86char *g_biggielist_txt;
87
88/**
89 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
90 * the current archive set.
91 */
92char *g_filelist_full;
93
94/**
95 * The location of a file containing a list of the devices that were archived
96 * as images, not as individual files.
97 */
98char *g_filelist_imagedevs;
99
100/**
101 * The location of a file containing a list of imagedevs to actually restore.
102 * @see g_filelist_imagedevs
103 */
104char *g_imagedevs_restthese;
105
106/**
107 * The location of 'mondo-restore.cfg', containing the metadata
108 * information for this backup.
109 */
110char *g_mondo_cfg_file;
111
112/**
113 * The location of 'mountlist.txt', containing the information on the
114 * user's partitions and hard drives.
115 */
116char *g_mountlist_fname;
117
118/**
119 * Mondo's home directory during backup. Unused in mondorestore; included
120 * to avoid link errors.
121 */
122char *g_mondo_home;
123
124extern char *g_getfacl;
125extern char *g_getfattr;
126
127/* @} - end of "Restore-Time Globals" in globalGroup */
128
129
130
131extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
132 char direction);
133
134
135
136/**************************************************************************
137 * COMPAQ PROLIANT Stuff: needs some special help *
138**************************************************************************/
139
140/**
141 * The message to display if we detect that the user is using a Compaq Proliant.
142 */
143#define COMPAQ_PROLIANTS_SUCK "Partition and format your disk using Compaq's disaster recovery CD. After you've done that, please reboot with your Mondo CD/floppy in Interactive Mode."
144
145
146
147
148/**
149 * Allow the user to modify the mountlist before we partition & format their drives.
150 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
151 * @param mountlist The mountlist to let the user modify.
152 * @param raidlist The raidlist that goes with @p mountlist.
153 * @return 0 for success, nonzero for failure.
154 * @ingroup restoreGuiGroup
155 */
156int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
157 struct raidlist_itself *raidlist)
158{
159 int retval = 0, res = 0;
160
161 log_msg(2, "let_user_edit_the_mountlist() --- starting");
162
163 assert(bkpinfo != NULL);
164 assert(mountlist != NULL);
165 assert(raidlist != NULL);
166 if (!bkpinfo->disaster_recovery) {
167 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
168 log_msg(2, "I guess you're testing edit_mountlist()");
169 }
170 if (!does_file_exist(g_mountlist_fname)) {
171 log_to_screen(g_mountlist_fname);
172 log_to_screen("does not exist");
173 return (1);
174 }
175
176 retval = load_mountlist(mountlist, g_mountlist_fname);
177 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
178 if (retval) {
179 log_to_screen
180 ("Warning - load_raidtab_into_raidlist returned an error");
181 }
182 res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
183 if (res) {
184 return (1);
185 }
186
187 save_mountlist_to_disk(mountlist, g_mountlist_fname);
188 save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
189
190 log_to_screen("I have finished editing the mountlist for you.");
191
192 return (retval);
193}
194
195
196
197
198
199/**
200 * Determine whether @p mountlist contains a Compaq diagnostic partition.
201 * @param mountlist The mountlist to examine.
202 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
203 * @ingroup restoreUtilityGroup
204 */
205bool
206partition_table_contains_Compaq_diagnostic_partition(struct
207 mountlist_itself *
208 mountlist)
209{
210 int i;
211
212 assert(mountlist != NULL);
213
214 for (i = 0; i < mountlist->entries; i++) {
215 if (strstr(mountlist->el[i].format, "ompaq")) {
216 log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
217 i, mountlist->el[i].device, mountlist->el[i].format);
218
219 return (TRUE);
220 }
221 }
222 return (FALSE);
223}
224
225/**************************************************************************
226 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION *
227 **************************************************************************/
228
229
230/**
231 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
232 * @note This function does not actually check for the presence of a Compaq partition.
233 * @ingroup restoreUtilityGroup
234 */
235void offer_to_abort_because_Compaq_Proliants_suck(void)
236{
237 popup_and_OK(COMPAQ_PROLIANTS_SUCK);
238 if (ask_me_yes_or_no
239 ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
240 {
241 fatal_error
242 ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
243 }
244}
245
246/**************************************************************************
247 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK *
248 **************************************************************************/
249
250
251
252/**
253 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
254 * @param bkpinfo The backup information structure. Most fields are used.
255 * @param mountlist The mountlist containing information about the user's partitions.
256 * @param raidlist The raidlist to go with @p mountlist.
257 * @return The return code from the mode function called.
258 * @ingroup restoreGroup
259 */
260int
261catchall_mode(struct mountlist_itself *mountlist,
262 struct raidlist_itself *raidlist)
263{
264 char c, *tmp;
265 int retval = 0;
266
267 iamhere("inside catchall");
268 assert(bkpinfo != NULL);
269 assert(mountlist != NULL);
270 assert(raidlist != NULL);
271 malloc_string(tmp);
272 iamhere("pre wrm");
273 c = which_restore_mode();
274 iamhere("post wrm");
275 if (c == 'I' || c == 'N' || c == 'C') {
276 interactively_obtain_media_parameters_from_user(FALSE);
277 } else {
278 popup_and_OK("No restoring or comparing will take place today.");
279 if (is_this_device_mounted("/mnt/cdrom")) {
280 run_program_and_log_output("umount /mnt/cdrom", FALSE);
281 }
282 if (g_ISO_restore_mode) {
283 sprintf(tmp, "umount %s", bkpinfo->isodir);
284 run_program_and_log_output(tmp, FALSE);
285 }
286 paranoid_MR_finish(0);
287 }
288
289 iamhere("post int");
290
291 if (bkpinfo->backup_media_type == iso) {
292 if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
293 log_msg(2,
294 "catchall_mode --- iso_fiddly_bits returned w/ error");
295 return (1);
296 } else {
297 log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
298 }
299 }
300
301 if (c == 'I') {
302 log_msg(2, "IM selected");
303 retval += interactive_mode(mountlist, raidlist);
304 } else if (c == 'N') {
305 log_msg(2, "NM selected");
306 retval += nuke_mode(mountlist, raidlist);
307 } else if (c == 'C') {
308 log_msg(2, "CM selected");
309 retval += compare_mode(mountlist, raidlist);
310 }
311 paranoid_free(tmp);
312 return (retval);
313}
314
315/**************************************************************************
316 *END_CATCHALL_MODE *
317 **************************************************************************/
318
319/**************************************************************************
320 *END_ EXTRACT_CONFIG_FILE_FROM_RAMDISK *
321 **************************************************************************/
322
323
324/**
325 * Locate an executable in the directory structure rooted at @p restg.
326 * @param out_path Where to put the executable.
327 * @param fname The basename of the executable.
328 * @param restg The directory structure to look in.
329 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
330 * @ingroup restoreUtilityGroup
331 */
332void
333find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
334 char *fname,
335 char *restg)
336{
337 assert(out_path != NULL);
338 assert_string_is_neither_NULL_nor_zerolength(fname);
339
340 sprintf(out_path, "%s/sbin/%s", restg, fname);
341 if (does_file_exist(out_path)) {
342 sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
343 if (does_file_exist(out_path)) {
344 sprintf(out_path, "%s/bin/%s", restg, fname);
345 if (does_file_exist(out_path)) {
346 sprintf(out_path, "%s/usr/bin/%s", restg, fname);
347 if (does_file_exist(out_path)) {
348 strcpy(out_path, fname);
349 }
350 }
351 }
352 }
353}
354
355/**************************************************************************
356 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING *
357 **************************************************************************/
358
359static void clean_blkid() {
360
361 char *tmp1 = NULL;
362
363 /* Clean up blkid cache file if they exist */
364 asprintf(&tmp1,"%s/etc/blkid.tab",bkpinfo->restore_path);
365 (void)unlink(tmp1);
366 paranoid_free(tmp1);
367 asprintf(&tmp1,"%s/etc/blkid.tab.old",bkpinfo->restore_path);
368 (void)unlink(tmp1);
369 paranoid_free(tmp1);
370}
371
372
373
374
375/**
376 * @addtogroup restoreGroup
377 * @{
378 */
379/**
380 * Restore the user's data, in a disaster recovery situation, prompting the
381 * user about whether or not to do every step.
382 * The user can edit the mountlist, choose files to restore, etc.
383 * @param bkpinfo The backup information structure. Most fields are used.
384 * @param mountlist The mountlist containing information about the user's partitions.
385 * @param raidlist The raidlist to go with @p mountlist.
386 * @return 0 for success, or the number of errors encountered.
387 */
388int
389interactive_mode(struct mountlist_itself *mountlist,
390 struct raidlist_itself *raidlist)
391{
392 int retval = 0;
393 int res;
394 int ptn_errs = 0;
395 int fmt_errs = 0;
396
397 bool done;
398 bool restore_all;
399
400 /** needs malloc **********/
401 char *tmp;
402 char *fstab_fname;
403 char *old_restpath;
404
405 struct s_node *filelist;
406
407 /* try to partition and format */
408
409 log_msg(2, "interactive_mode --- starting (great, assertions OK)");
410
411 malloc_string(tmp);
412 malloc_string(fstab_fname);
413 malloc_string(old_restpath);
414 assert(bkpinfo != NULL);
415 assert(mountlist != NULL);
416 assert(raidlist != NULL);
417
418 log_msg(2, "interactive_mode --- assertions OK");
419
420 if (g_text_mode) {
421 if (!ask_me_yes_or_no
422 ("Interactive Mode + textonly = experimental! Proceed anyway?"))
423 {
424 fatal_error("Wise move.");
425 }
426 }
427
428 iamhere("About to load config file");
429 get_cfg_file_from_archive_or_bust();
430 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
431 iamhere("Done loading config file; resizing ML");
432 if (bkpinfo->backup_media_type == nfs) {
433 strcpy(tmp, bkpinfo->prefix);
434 if (popup_and_get_string
435 ("Prefix", "Prefix of your ISO images ?", tmp, MAX_STR_LEN / 4)) {
436 strcpy(bkpinfo->prefix, tmp);
437 log_msg(1, "Prefix set to %s",bkpinfo->prefix);
438 }
439 }
440
441#ifdef __FreeBSD__
442 if (strstr
443 (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
444 "noresize"))
445#else
446 if (strstr
447 (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
448 "noresize"))
449#endif
450 {
451 log_msg(1, "Not resizing mountlist.");
452 } else {
453 resize_mountlist_proportionately_to_suit_new_drives(mountlist);
454 }
455 for (done = FALSE; !done;) {
456 iamhere("About to edit mountlist");
457 if (g_text_mode) {
458 save_mountlist_to_disk(mountlist, g_mountlist_fname);
459 sprintf(tmp, "%s %s", find_my_editor(), g_mountlist_fname);
460 res = system(tmp);
461 load_mountlist(mountlist, g_mountlist_fname);
462 } else {
463 res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
464 }
465 iamhere("Finished editing mountlist");
466 if (res) {
467 paranoid_MR_finish(1);
468 }
469 log_msg(2, "Proceeding...");
470 save_mountlist_to_disk(mountlist, g_mountlist_fname);
471 save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
472 mvaddstr_and_log_it(1, 30, "Restoring Interactively");
473 if (bkpinfo->differential) {
474 log_to_screen("Because this is a differential backup, disk");
475 log_to_screen
476 (" partitioning and formatting will not take place.");
477 done = TRUE;
478 } else {
479 if (ask_me_yes_or_no
480 ("Do you want to erase and partition your hard drives?")) {
481 if (partition_table_contains_Compaq_diagnostic_partition
482 (mountlist)) {
483 offer_to_abort_because_Compaq_Proliants_suck();
484 done = TRUE;
485 } else {
486 twenty_seconds_til_yikes();
487 g_fprep = fopen("/tmp/prep.sh", "w");
488 ptn_errs = partition_everything(mountlist);
489 if (ptn_errs) {
490 log_to_screen
491 ("Warning. Errors occurred during disk partitioning.");
492 }
493
494 fmt_errs = format_everything(mountlist, FALSE, raidlist);
495 if (!fmt_errs) {
496 log_to_screen
497 ("Errors during disk partitioning were handled OK.");
498 log_to_screen
499 ("Partitions were formatted OK despite those errors.");
500 ptn_errs = 0;
501 }
502 if (!ptn_errs && !fmt_errs) {
503 done = TRUE;
504 }
505 }
506 paranoid_fclose(g_fprep);
507 } else {
508 mvaddstr_and_log_it(g_currentY++, 0,
509 "User opted not to partition the devices");
510 if (ask_me_yes_or_no
511 ("Do you want to format your hard drives?")) {
512 fmt_errs = format_everything(mountlist, TRUE, raidlist);
513 if (!fmt_errs) {
514 done = TRUE;
515 }
516 } else {
517 ptn_errs = fmt_errs = 0;
518 done = TRUE;
519 }
520 }
521 if (fmt_errs) {
522 mvaddstr_and_log_it(g_currentY++,
523 0,
524 "Errors occurred. Please repartition and format drives manually.");
525 done = FALSE;
526 }
527 if (ptn_errs & !fmt_errs) {
528 mvaddstr_and_log_it(g_currentY++,
529 0,
530 "Errors occurred during partitioning. Formatting, however, went OK.");
531 done = TRUE;
532 }
533 if (!done) {
534 if (!ask_me_yes_or_no("Re-edit the mountlist?")) {
535 retval++;
536 goto end_of_func;
537 }
538 }
539 }
540 }
541
542 /* mount */
543 if (mount_all_devices(mountlist, TRUE)) {
544 unmount_all_devices(mountlist);
545 retval++;
546 goto end_of_func;
547 }
548 /* restore */
549 if ((restore_all =
550 ask_me_yes_or_no("Do you want me to restore all of your data?")))
551 {
552 log_msg(1, "Restoring all data");
553 retval += restore_everything(NULL);
554 } else
555 if ((restore_all =
556 ask_me_yes_or_no
557 ("Do you want me to restore _some_ of your data?"))) {
558 strcpy(old_restpath, bkpinfo->restore_path);
559 for (done = FALSE; !done;) {
560 unlink("/tmp/filelist.full");
561 filelist = process_filelist_and_biggielist();
562 /* Now you have /tmp/tmpfs/filelist.restore-these and /tmp/tmpfs/biggielist.restore-these;
563 the former is a list of regular files; the latter, biggiefiles and imagedevs.
564 */
565 if (filelist) {
566 gotos_suck:
567 strcpy(tmp, old_restpath);
568// (NB: %s is where your filesystem is mounted now, by default)", MNT_RESTORING);
569 if (popup_and_get_string
570 ("Restore path", "Restore files to where?", tmp,
571 MAX_STR_LEN / 4)) {
572 if (!strcmp(tmp, "/")) {
573 if (!ask_me_yes_or_no("Are you sure?")) {
574 goto gotos_suck;
575 }
576 tmp[0] = '\0'; // so we restore to [blank]/file/name :)
577 }
578 strcpy(bkpinfo->restore_path, tmp);
579 log_msg(1, "Restoring subset");
580 retval += restore_everything(filelist);
581 free_filelist(filelist);
582 } else {
583 strcpy(bkpinfo->restore_path, old_restpath);
584 free_filelist(filelist);
585 }
586 if (!ask_me_yes_or_no
587 ("Restore another subset of your backup?")) {
588 done = TRUE;
589 }
590 } else {
591 done = TRUE;
592 }
593 }
594 strcpy(old_restpath, bkpinfo->restore_path);
595 } else {
596 mvaddstr_and_log_it(g_currentY++,
597 0,
598 "User opted not to restore any data. ");
599 }
600 if (retval) {
601 mvaddstr_and_log_it(g_currentY++,
602 0,
603 "Errors occurred during the restore phase. ");
604 }
605
606 if (ask_me_yes_or_no("Initialize the boot loader?")) {
607 run_boot_loader(TRUE);
608 } else {
609 mvaddstr_and_log_it(g_currentY++,
610 0,
611 "User opted not to initialize the boot loader.");
612 }
613
614 clean_blkid();
615 protect_against_braindead_sysadmins();
616 retval += unmount_all_devices(mountlist);
617 /* if (restore_some || restore_all || */
618 if (ask_me_yes_or_no
619 ("Label/Identify your ext2 and ext3 partitions if necessary?")) {
620 mvaddstr_and_log_it(g_currentY, 0,
621 "Using tune2fs to identify your ext2,3 partitions");
622 if (does_file_exist("/tmp/fstab.new")) {
623 strcpy(fstab_fname, "/tmp/fstab.new");
624 } else {
625 strcpy(fstab_fname, "/tmp/fstab");
626 }
627 sprintf(tmp,
628 "label-partitions-as-necessary %s < %s >> %s 2>> %s",
629 g_mountlist_fname, fstab_fname, MONDO_LOGFILE,
630 MONDO_LOGFILE);
631 res = system(tmp);
632 if (res) {
633 log_to_screen
634 ("label-partitions-as-necessary returned an error");
635 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
636 } else {
637 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
638 }
639 retval += res;
640 }
641
642 iamhere("About to leave interactive_mode()");
643 if (retval) {
644 mvaddstr_and_log_it(g_currentY++,
645 0,
646 "Warning - errors occurred during the restore phase.");
647 }
648 end_of_func:
649 paranoid_free(tmp);
650 paranoid_free(fstab_fname);
651 paranoid_free(old_restpath);
652 iamhere("Leaving interactive_mode()");
653 return (retval);
654}
655
656/**************************************************************************
657 *END_INTERACTIVE_MODE *
658 **************************************************************************/
659
660
661
662/**
663 * Run an arbitrary restore mode (prompt the user), but from ISO images
664 * instead of real media.
665 * @param mountlist The mountlist containing information about the user's partitions.
666 * @param raidlist The raidlist that goes with @p mountlist.
667 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
668 * @return 0 for success, or the number of errors encountered.
669 */
670int
671iso_mode(struct mountlist_itself *mountlist,
672 struct raidlist_itself *raidlist, bool nuke_me_please)
673{
674 char c;
675 int retval = 0;
676
677 assert(mountlist != NULL);
678 assert(raidlist != NULL);
679 if (iso_fiddly_bits(nuke_me_please)) {
680 log_msg(1, "iso_mode --- returning w/ error");
681 return (1);
682 } else {
683 c = which_restore_mode();
684 if (c == 'I' || c == 'N' || c == 'C') {
685 interactively_obtain_media_parameters_from_user(FALSE);
686 }
687 if (c == 'I') {
688 retval += interactive_mode(mountlist, raidlist);
689 } else if (c == 'N') {
690 retval += nuke_mode(mountlist, raidlist);
691 } else if (c == 'C') {
692 retval += compare_mode(mountlist, raidlist);
693 } else {
694 log_to_screen("OK, I shan't restore/compare any files.");
695 }
696 }
697 if (is_this_device_mounted(MNT_CDROM)) {
698 paranoid_system("umount " MNT_CDROM);
699 }
700// if (! already_mounted)
701// {
702 if (system("umount /tmp/isodir 2> /dev/null")) {
703 log_to_screen
704 ("WARNING - unable to unmount device where the ISO files are stored.");
705 }
706// }
707 return (retval);
708}
709
710/**************************************************************************
711 *END_ISO_MODE *
712 **************************************************************************/
713
714
715/* MONDO - saving your a$$ since Feb 18th, 2000 */
716
717
718
719
720/**
721 * Restore the user's data automatically (no prompts), after a twenty-second
722 * warning period.
723 * @param bkpinfo The backup information structure. Most fields are used.
724 * @param mountlist The mountlist containing information about the user's partitions.
725 * @param raidlist The raidlist that goes with @p mountlist.
726 * @return 0 for success, or the number of errors encountered.
727 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
728 */
729int
730nuke_mode(struct mountlist_itself *mountlist,
731 struct raidlist_itself *raidlist)
732{
733 int retval = 0;
734 int res = 0;
735 bool boot_loader_installed = FALSE;
736 /** malloc **/
737 char tmp[MAX_STR_LEN], tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
738 tmpC[MAX_STR_LEN];
739
740 assert(bkpinfo != NULL);
741 assert(mountlist != NULL);
742 assert(raidlist != NULL);
743
744 log_msg(2, "nuke_mode --- starting");
745
746 get_cfg_file_from_archive_or_bust();
747 load_mountlist(mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo updated the mountlist
748#ifdef __FreeBSD__
749 if (strstr
750 (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
751 "noresize"))
752#else
753 if (strstr
754 (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
755 "noresize"))
756#endif
757 {
758 log_msg(2, "Not resizing mountlist.");
759 } else {
760 resize_mountlist_proportionately_to_suit_new_drives(mountlist);
761 }
762 if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
763 sprintf(tmp,
764 "Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?",
765 tmpA, tmpB, tmpC);
766 if (ask_me_yes_or_no(tmp)) {
767 retval = interactive_mode(mountlist, raidlist);
768 goto after_the_nuke;
769 } else {
770 fatal_error("Nuke Mode aborted. ");
771 }
772 }
773 save_mountlist_to_disk(mountlist, g_mountlist_fname);
774 mvaddstr_and_log_it(1, 30, "Restoring Automatically");
775 if (bkpinfo->differential) {
776 log_to_screen("Because this is a differential backup, disk");
777 log_to_screen("partitioning and formatting will not take place.");
778 res = 0;
779 } else {
780 if (partition_table_contains_Compaq_diagnostic_partition
781 (mountlist)) {
782 offer_to_abort_because_Compaq_Proliants_suck();
783 } else {
784 twenty_seconds_til_yikes();
785 g_fprep = fopen("/tmp/prep.sh", "w");
786#ifdef __FreeBSD__
787 if (strstr
788 (call_program_and_get_last_line_of_output
789 ("cat /tmp/cmdline"), "nopart"))
790#else
791 if (strstr
792 (call_program_and_get_last_line_of_output
793 ("cat /proc/cmdline"), "nopart"))
794#endif
795 {
796 log_msg(2,
797 "Not partitioning drives due to 'nopart' option.");
798 res = 0;
799 } else {
800 res = partition_everything(mountlist);
801 if (res) {
802 log_to_screen
803 ("Warning. Errors occurred during partitioning.");
804 res = 0;
805 }
806 }
807 retval += res;
808 if (!res) {
809 log_to_screen("Preparing to format your disk(s)");
810 sleep(1);
811 system("sync");
812 log_to_screen("Please wait. This may take a few minutes.");
813 res += format_everything(mountlist, FALSE, raidlist);
814 }
815 paranoid_fclose(g_fprep);
816 }
817 }
818 retval += res;
819 if (res) {
820 mvaddstr_and_log_it(g_currentY++,
821 0,
822 "Failed to partition and/or format your hard drives.");
823
824 if (ask_me_yes_or_no("Try in interactive mode instead?")) {
825 retval = interactive_mode(mountlist, raidlist);
826 goto after_the_nuke;
827 } else
828 if (!ask_me_yes_or_no
829 ("Would you like to try to proceed anyway?")) {
830 return (retval);
831 }
832 }
833 retval = mount_all_devices(mountlist, TRUE);
834 if (retval) {
835 unmount_all_devices(mountlist);
836 log_to_screen
837 ("Unable to mount all partitions. Sorry, I cannot proceed.");
838 return (retval);
839 }
840 iamhere("Restoring everything");
841 retval += restore_everything(NULL);
842 if (!run_boot_loader(FALSE)) {
843 log_msg(1,
844 "Great! Boot loader was installed. No need for msg at end.");
845 boot_loader_installed = TRUE;
846 }
847 clean_blkid();
848 protect_against_braindead_sysadmins();
849 retval += unmount_all_devices(mountlist);
850 mvaddstr_and_log_it(g_currentY,
851 0,
852 "Using tune2fs to identify your ext2,3 partitions");
853
854 sprintf(tmp, "label-partitions-as-necessary %s < /tmp/fstab",
855 g_mountlist_fname);
856 res = run_program_and_log_output(tmp, TRUE);
857 if (res) {
858 log_to_screen("label-partitions-as-necessary returned an error");
859 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
860 } else {
861 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
862 }
863 retval += res;
864
865 after_the_nuke:
866 if (retval) {
867 log_to_screen("Errors occurred during the nuke phase.");
868 } else if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "RESTORE")) {
869 log_to_screen
870 ("PC was restored successfully. Thank you for using Mondo Rescue.");
871 log_to_screen
872 ("Please visit our website at http://www.mondorescue.org for more information.");
873 } else {
874 strcpy(tmp,"Mondo has restored your system.\n\nPlease wait for the command prompt. Then remove the backup media and reboot.\n\nPlease visit our website at http://www.mondorescue.org for more information.");
875 popup_and_OK(tmp);
876 log_to_screen
877 ("Mondo has restored your system. Please wait for the command prompt.");
878 log_to_screen
879 ("Then remove the backup media and reboot.");
880 log_to_screen
881 ("Please visit our website at http://www.mondorescue.org for more information.");
882 }
883 g_I_have_just_nuked = TRUE;
884/*
885 if (!boot_loader_installed && !does_file_exist(DO_MBR_PLEASE))
886 {
887 log_to_screen("PLEASE RUN 'mondorestore --mbr' NOW TO INITIALIZE YOUR BOOT SECTOR");
888 write_one_liner_data_file(DO_MBR_PLEASE, "mondorestore --mbr");
889 }
890*/
891 return (retval);
892}
893
894/**************************************************************************
895 *END_NUKE_MODE *
896 **************************************************************************/
897
898
899
900/**
901 * Restore the user's data (or a subset of it) to the live filesystem.
902 * This should not be called if we're booted from CD!
903 * @param bkpinfo The backup information structure. Most fields are used.
904 * @return 0 for success, or the number of errors encountered.
905 */
906int restore_to_live_filesystem()
907{
908 int retval = 0;
909
910 /** malloc **/
911 char *old_restpath;
912
913 struct mountlist_itself *mountlist;
914// static
915 struct raidlist_itself *raidlist;
916 struct s_node *filelist;
917
918 log_msg(1, "restore_to_live_filesystem() - starting");
919 assert(bkpinfo != NULL);
920 malloc_string(old_restpath);
921 mountlist = malloc(sizeof(struct mountlist_itself));
922 raidlist = malloc(sizeof(struct raidlist_itself));
923 if (!mountlist || !raidlist) {
924 fatal_error("Cannot malloc() mountlist and/or raidlist");
925 }
926
927 strcpy(bkpinfo->restore_path, "/");
928 if (!g_restoring_live_from_cd) {
929 popup_and_OK
930 ("Please insert tape/CD/USB Key/boot floppy, then hit 'OK' to continue.");
931 sleep(1);
932 }
933 interactively_obtain_media_parameters_from_user(FALSE);
934 log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
935 if (!bkpinfo->media_device[0]) {
936 log_msg(2, "Warning - failed to find media dev");
937 }
938
939
940 log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
941
942 open_evalcall_form("Thinking...");
943
944 get_cfg_file_from_archive_or_bust();
945 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
946 load_mountlist(mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo
947
948 close_evalcall_form();
949 retval = load_mountlist(mountlist, g_mountlist_fname);
950 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
951 filelist = process_filelist_and_biggielist();
952 if (filelist) {
953 save_filelist(filelist, "/tmp/selected-files.txt");
954 strcpy(old_restpath, bkpinfo->restore_path);
955 if (popup_and_get_string("Restore path",
956 "Restore files to where? )",
957 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
958 iamhere("Restoring everything");
959 retval += restore_everything(filelist);
960 free_filelist(filelist);
961 strcpy(bkpinfo->restore_path, old_restpath);
962 } else {
963 free_filelist(filelist);
964 }
965 strcpy(bkpinfo->restore_path, old_restpath);
966 }
967 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
968 log_msg(2,
969 "Tape : I don't need to unmount or eject the CD-ROM.");
970 } else {
971 run_program_and_log_output("umount " MNT_CDROM, FALSE);
972 if (!bkpinfo->please_dont_eject) {
973 eject_device(bkpinfo->media_device);
974 }
975 }
976 run_program_and_log_output("umount " MNT_CDROM, FALSE);
977 if (!bkpinfo->please_dont_eject) {
978 eject_device(bkpinfo->media_device);
979 }
980 paranoid_free(old_restpath);
981 free(mountlist);
982 free(raidlist);
983 return (retval);
984}
985
986/**************************************************************************
987 *END_RESTORE_TO_LIVE_FILESYSTEM *
988 **************************************************************************/
989
990/* @} - end of restoreGroup */
991
992
993#include <utime.h>
994/**
995 * @addtogroup LLrestoreGroup
996 * @{
997 */
998/**
999 * Restore biggiefile @p bigfileno from the currently mounted CD.
1000 * @param bkpinfo The backup information structure. Fields used:
1001 * - @c bkpinfo->backup_media_type
1002 * - @c bkpinfo->restore_path
1003 * @param bigfileno The biggiefile number (starting from 0) to restore.
1004 * @param filelist The node structure containing the list of files to restore.
1005 * If the biggiefile is not in this list, it will be skipped (return value will
1006 * still indicate success).
1007 * @return 0 for success (or skip), nonzero for failure.
1008 */
1009int
1010restore_a_biggiefile_from_CD(long bigfileno,
1011 struct s_node *filelist,
1012 char *pathname_of_last_file_restored)
1013{
1014 FILE *fin;
1015 FILE *fout;
1016 FILE *fbzip2;
1017
1018 /** malloc ***/
1019 char *checksum, *outfile_fname, *tmp, *bzip2_command,
1020 *ntfsprog_command, *suffix, *sz_devfile;
1021 char *bigblk;
1022 char *p;
1023 int retval = 0;
1024 int finished = FALSE;
1025 long sliceno;
1026 long siz;
1027 char ntfsprog_fifo[MAX_STR_LEN];
1028 char *file_to_openout = NULL;
1029 struct s_filename_and_lstat_info biggiestruct;
1030 struct utimbuf the_utime_buf, *ubuf;
1031 bool use_ntfsprog_hack = FALSE;
1032 pid_t pid;
1033 int res = 0;
1034 int old_loglevel;
1035 char sz_msg[MAX_STR_LEN];
1036 struct s_node *node;
1037
1038 old_loglevel = g_loglevel;
1039 ubuf = &the_utime_buf;
1040 assert(bkpinfo != NULL);
1041
1042 malloc_string(checksum);
1043 malloc_string(outfile_fname);
1044 malloc_string(tmp);
1045 malloc_string(bzip2_command);
1046 malloc_string(ntfsprog_command);
1047 malloc_string(suffix);
1048 malloc_string(sz_devfile);
1049
1050 pathname_of_last_file_restored[0] = '\0';
1051 if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
1052 fatal_error("Cannot malloc bigblk");
1053 }
1054
1055 if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1056 log_to_screen("Cannot even open bigfile's info file");
1057 return (1);
1058 }
1059
1060 memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1061 if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1062 sizeof(biggiestruct)) {
1063 log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1064 bigfileno + 1);
1065 }
1066 paranoid_fclose(fin);
1067
1068 strcpy(checksum, biggiestruct.checksum);
1069
1070 if (!checksum[0]) {
1071 sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
1072 bigfileno + 1);
1073 log_msg(3, tmp);
1074 p = checksum;
1075 }
1076
1077 if (!strncmp(biggiestruct.filename, "/dev/", 5)) // Whether NTFS or not :)
1078 {
1079 strcpy(outfile_fname, biggiestruct.filename);
1080 } else {
1081 sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1082 biggiestruct.filename);
1083 }
1084
1085 /* skip file if we have a selective restore subset & it doesn't match */
1086 if (filelist != NULL) {
1087 node = find_string_at_node(filelist, biggiestruct.filename);
1088 if (!node) {
1089 log_msg(0, "Skipping %s (name isn't in filelist)",
1090 biggiestruct.filename);
1091 pathname_of_last_file_restored[0] = '\0';
1092 return (0);
1093 } else if (!(node->selected)) {
1094 log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1095 biggiestruct.filename);
1096 pathname_of_last_file_restored[0] = '\0';
1097 return (0);
1098 }
1099 }
1100 /* otherwise, continue */
1101
1102 log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1103 if (biggiestruct.use_ntfsprog) {
1104 if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1105 log_msg(1,
1106 "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1107 log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1108 biggiestruct.use_ntfsprog = FALSE;
1109 }
1110 }
1111
1112 if (biggiestruct.use_ntfsprog) // if it's an NTFS device
1113// if (!strncmp ( biggiestruct.filename, "/dev/", 5))
1114 {
1115 g_loglevel = 4;
1116 use_ntfsprog_hack = TRUE;
1117 log_msg(2,
1118 "Calling ntfsclone in background because %s is an NTFS /dev entry",
1119 outfile_fname);
1120 sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
1121 (int) (random() % 32768));
1122 mkfifo(sz_devfile, 0x770);
1123 strcpy(ntfsprog_fifo, sz_devfile);
1124 file_to_openout = ntfsprog_fifo;
1125 switch (pid = fork()) {
1126 case -1:
1127 fatal_error("Fork failure");
1128 case 0:
1129 log_msg(3,
1130 "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1131 biggiestruct.filename, ntfsprog_fifo);
1132 res =
1133 feed_outfrom_ntfsprog(biggiestruct.filename,
1134 ntfsprog_fifo);
1135// log_msg(3, "CHILD - fip - exiting");
1136 exit(res);
1137 break;
1138 default:
1139 log_msg(3,
1140 "feed_into_ntfsprog() called in background --- pid=%ld",
1141 (long int) (pid));
1142 }
1143 } else {
1144 use_ntfsprog_hack = FALSE;
1145 ntfsprog_fifo[0] = '\0';
1146 file_to_openout = outfile_fname;
1147 if (!does_file_exist(outfile_fname)) // yes, it looks weird with the '!' but it's correct that way
1148 {
1149 make_hole_for_file(outfile_fname);
1150 }
1151 }
1152
1153 sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
1154 outfile_fname);
1155 log_msg(2, tmp);
1156
1157 /*
1158 last slice is zero-length and uncompressed; when we find it, we stop.
1159 We DON'T wait until there are no more slices; if we did that,
1160 We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1161 */
1162
1163 strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1164 MAX_STR_LEN - 1);
1165 pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1166
1167 log_msg(3, "file_to_openout = %s", file_to_openout);
1168 if (!(fout = fopen(file_to_openout, "w"))) {
1169 log_to_screen("Cannot openout outfile_fname - hard disk full?");
1170 return (1);
1171 }
1172 log_msg(3, "Opened out to %s", outfile_fname); // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1173
1174 for (sliceno = 1, finished = FALSE; !finished;) {
1175 if (!does_file_exist
1176 (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1177 &&
1178 !does_file_exist(slice_fname
1179 (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1180 &&
1181 !does_file_exist(slice_fname
1182 (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1183 &&
1184 !does_file_exist(slice_fname
1185 (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1186 log_msg(3,
1187 "Cannot find a data slice or terminator slice on CD %d",
1188 g_current_media_number);
1189 g_current_media_number++;
1190 sprintf(tmp,
1191 "Asking for %s #%d so that I may read slice #%ld\n",
1192 media_descriptor_string(bkpinfo->backup_media_type),
1193 g_current_media_number, sliceno);
1194 log_msg(2, tmp);
1195 sprintf(tmp, "Restoring from %s #%d",
1196 media_descriptor_string(bkpinfo->backup_media_type),
1197 g_current_media_number);
1198 log_to_screen(tmp);
1199 insist_on_this_cd_number(g_current_media_number);
1200 log_to_screen("Continuing to restore.");
1201 } else {
1202 strcpy(tmp,
1203 slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1204 if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1205 log_msg(2,
1206 "End of bigfile # %ld (slice %ld is the terminator)",
1207 bigfileno + 1, sliceno);
1208 finished = TRUE;
1209 continue;
1210 } else {
1211 if (does_file_exist
1212 (slice_fname
1213 (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1214 strcpy(bzip2_command, "lzop");
1215 strcpy(suffix, "lzo");
1216 } else
1217 if (does_file_exist
1218 (slice_fname
1219 (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1220 strcpy(bzip2_command, "gzip");
1221 strcpy(suffix, "gz");
1222 } else
1223 if (does_file_exist
1224 (slice_fname
1225 (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1226 strcpy(bzip2_command, "bzip2");
1227 strcpy(suffix, "bz2");
1228 } else
1229 if (does_file_exist
1230 (slice_fname
1231 (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1232 strcpy(bzip2_command, "");
1233 strcpy(suffix, "");
1234 } else {
1235 log_to_screen("OK, that's pretty fsck0red...");
1236 return (1);
1237 }
1238 }
1239 if (bzip2_command[0] != '\0') {
1240 sprintf(bzip2_command + strlen(bzip2_command),
1241 " -dc %s 2>> %s",
1242 slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1243 suffix), MONDO_LOGFILE);
1244 } else {
1245 sprintf(bzip2_command, "cat %s 2>> %s",
1246 slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1247 suffix), MONDO_LOGFILE);
1248 }
1249 sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld ",
1250 media_descriptor_string(bkpinfo->backup_media_type),
1251 g_current_media_number, bigfileno + 1, sliceno);
1252 log_msg(2, tmp);
1253
1254 if (!g_text_mode) {
1255 newtDrawRootText(0, g_noof_rows - 2, tmp);
1256 newtRefresh();
1257 strip_spaces(tmp);
1258 update_progress_form(tmp);
1259 }
1260 if (!(fbzip2 = popen(bzip2_command, "r"))) {
1261 fatal_error("Can't run popen command");
1262 }
1263 while (!feof(fbzip2)) {
1264 siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1265 if (siz > 0) {
1266 sprintf(sz_msg, "Read %ld from fbzip2", siz);
1267 siz = fwrite(bigblk, 1, siz, fout);
1268 sprintf(sz_msg + strlen(sz_msg),
1269 "; written %ld to fout", siz);
1270// log_msg(2. sz_msg);
1271 }
1272 }
1273 paranoid_pclose(fbzip2);
1274
1275
1276 sliceno++;
1277 g_current_progress++;
1278 }
1279 }
1280/*
1281 memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
1282 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1283 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1284 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1285 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1286*/
1287 paranoid_fclose(fout);
1288 g_loglevel = old_loglevel;
1289
1290 if (use_ntfsprog_hack) {
1291 log_msg(3, "Waiting for ntfsclone to finish");
1292 sprintf(tmp,
1293 " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1294 while (system(tmp) == 0) {
1295 sleep(1);
1296 }
1297 log_it("OK, ntfsclone has really finished");
1298 }
1299
1300 if (strcmp(outfile_fname, "/dev/null")) {
1301 chown(outfile_fname, biggiestruct.properties.st_uid,
1302 biggiestruct.properties.st_gid);
1303 chmod(outfile_fname, biggiestruct.properties.st_mode);
1304 ubuf->actime = biggiestruct.properties.st_atime;
1305 ubuf->modtime = biggiestruct.properties.st_mtime;
1306 utime(outfile_fname, ubuf);
1307 }
1308 paranoid_free(bigblk);
1309 paranoid_free(checksum);
1310 paranoid_free(outfile_fname);
1311 paranoid_free(tmp);
1312 paranoid_free(bzip2_command);
1313 paranoid_free(ntfsprog_command);
1314 paranoid_free(suffix);
1315 paranoid_free(sz_devfile);
1316
1317 return (retval);
1318}
1319
1320/**************************************************************************
1321 *END_ RESTORE_A_BIGGIEFILE_FROM_CD *
1322 **************************************************************************/
1323
1324
1325
1326/**
1327 * Restore a biggiefile from the currently opened stream.
1328 * @param bkpinfo The backup information structure. Fields used:
1329 * - @c bkpinfo->restore_path
1330 * - @c bkpinfo->zip_exe
1331 * @param orig_bf_fname The original filename of the biggiefile.
1332 * @param biggiefile_number The number of the biggiefile (starting from 0).
1333 * @param orig_checksum Unused.
1334 * @param biggiefile_size Unused.
1335 * @param filelist The node structure containing the list of files to be restored.
1336 * If @p orig_bf_fname is not in the list, it will be ignored.
1337 * @return 0 for success (or skip), nonzero for failure.
1338 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
1339 */
1340int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum, //UNUSED
1341 long long biggiefile_size, //UNUSED
1342 struct s_node *filelist,
1343 int use_ntfsprog,
1344 char *pathname_of_last_file_restored)
1345{
1346 FILE *pout;
1347 FILE *fin;
1348
1349 /** mallocs ********/
1350 char *tmp;
1351 char *command;
1352 char *outfile_fname;
1353 char *ntfsprog_command;
1354 char *sz_devfile;
1355 char *ntfsprog_fifo;
1356 char *file_to_openout = NULL;
1357
1358 struct s_node *node;
1359
1360 int old_loglevel;
1361 long current_slice_number = 0;
1362 int retval = 0;
1363 int res = 0;
1364 int ctrl_chr = '\0';
1365 long long slice_siz;
1366 bool dummy_restore = FALSE;
1367 bool use_ntfsprog_hack = FALSE;
1368 pid_t pid;
1369 struct s_filename_and_lstat_info biggiestruct;
1370 struct utimbuf the_utime_buf, *ubuf;
1371 ubuf = &the_utime_buf;
1372
1373 malloc_string(tmp);
1374 malloc_string(ntfsprog_fifo);
1375 malloc_string(outfile_fname);
1376 malloc_string(command);
1377 malloc_string(sz_devfile);
1378 malloc_string(ntfsprog_command);
1379 old_loglevel = g_loglevel;
1380 assert(bkpinfo != NULL);
1381 assert(orig_bf_fname != NULL);
1382 assert(orig_checksum != NULL);
1383
1384 pathname_of_last_file_restored[0] = '\0';
1385 if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1386 use_ntfsprog = 1;
1387 log_msg(1, "%s --- pih=YES", orig_bf_fname);
1388 } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1389 use_ntfsprog = 0;
1390 log_msg(1, "%s --- pih=NO", orig_bf_fname);
1391 } else {
1392 use_ntfsprog = 0;
1393 log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1394 }
1395
1396 strncpy(pathname_of_last_file_restored, orig_bf_fname,
1397 MAX_STR_LEN - 1);
1398 pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1399
1400 /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1401
1402 if (filelist != NULL) {
1403 node = find_string_at_node(filelist, orig_bf_fname);
1404 if (!node) {
1405 dummy_restore = TRUE;
1406 log_msg(1,
1407 "Skipping big file %ld (%s) - not in biggielist subset",
1408 biggiefile_number + 1, orig_bf_fname);
1409 pathname_of_last_file_restored[0] = '\0';
1410 } else if (!(node->selected)) {
1411 dummy_restore = TRUE;
1412 log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1413 orig_bf_fname);
1414 pathname_of_last_file_restored[0] = '\0';
1415 }
1416 }
1417
1418 if (use_ntfsprog) {
1419 if (strncmp(orig_bf_fname, "/dev/", 5)) {
1420 log_msg(1,
1421 "I was in error when I set use_ntfsprog to TRUE.");
1422 log_msg(1, "%s isn't even in /dev", orig_bf_fname);
1423 use_ntfsprog = FALSE;
1424 }
1425 }
1426
1427 if (use_ntfsprog) {
1428 g_loglevel = 4;
1429 strcpy(outfile_fname, orig_bf_fname);
1430 use_ntfsprog_hack = TRUE;
1431 log_msg(2,
1432 "Calling ntfsclone in background because %s is a /dev entry",
1433 outfile_fname);
1434 sprintf(sz_devfile, "%s/%d.%d.000",
1435 bkpinfo->tmpdir,
1436 (int) (random() % 32768),
1437 (int) (random() % 32768));
1438 mkfifo(sz_devfile, 0x770);
1439 strcpy(ntfsprog_fifo, sz_devfile);
1440 file_to_openout = ntfsprog_fifo;
1441 switch (pid = fork()) {
1442 case -1:
1443 fatal_error("Fork failure");
1444 case 0:
1445 log_msg(3,
1446 "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1447 outfile_fname, ntfsprog_fifo);
1448 res =
1449 feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1450// log_msg(3, "CHILD - fip - exiting");
1451 exit(res);
1452 break;
1453 default:
1454 log_msg(3,
1455 "feed_into_ntfsprog() called in background --- pid=%ld",
1456 (long int) (pid));
1457 }
1458 } else {
1459 if (!strncmp(orig_bf_fname, "/dev/", 5)) // non-NTFS partition
1460 {
1461 strcpy(outfile_fname, orig_bf_fname);
1462 } else // biggiefile
1463 {
1464 sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1465 orig_bf_fname);
1466 }
1467 use_ntfsprog_hack = FALSE;
1468 ntfsprog_fifo[0] = '\0';
1469 file_to_openout = outfile_fname;
1470 if (!does_file_exist(outfile_fname)) // yes, it looks weird with the '!' but it's correct that way
1471 {
1472 make_hole_for_file(outfile_fname);
1473 }
1474 sprintf(tmp, "Reassembling big file %ld (%s)",
1475 biggiefile_number + 1, orig_bf_fname);
1476 log_msg(2, tmp);
1477 }
1478
1479 if (dummy_restore) {
1480 sprintf(outfile_fname, "/dev/null");
1481 }
1482
1483 if (!bkpinfo->zip_exe[0]) {
1484 sprintf(command, "cat > \"%s\"", file_to_openout);
1485 } else {
1486 sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1487 file_to_openout, MONDO_LOGFILE);
1488 }
1489 sprintf(tmp, "Pipe command = '%s'", command);
1490 log_msg(3, tmp);
1491
1492 /* restore biggiefile, one slice at a time */
1493 if (!(pout = popen(command, "w"))) {
1494 fatal_error("Cannot pipe out");
1495 }
1496 for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1497 ctrl_chr != BLK_STOP_A_BIGGIE;
1498 res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
1499 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1500 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1501 }
1502 sprintf(tmp, "Working on file #%ld, slice #%ld ",
1503 biggiefile_number + 1, current_slice_number);
1504 log_msg(2, tmp);
1505 if (!g_text_mode) {
1506 newtDrawRootText(0, g_noof_rows - 2, tmp);
1507 newtRefresh();
1508 }
1509 strip_spaces(tmp);
1510 update_progress_form(tmp);
1511 if (current_slice_number == 0) {
1512 res =
1513 read_file_from_stream_to_file("/tmp/biggie-blah.txt",
1514 slice_siz);
1515 if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1516 log_OS_error("blah blah");
1517 } else {
1518 if (fread
1519 ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1520 fin) < sizeof(biggiestruct)) {
1521 log_msg(2,
1522 "Warning - unable to get biggiestruct of bigfile #%d",
1523 biggiefile_number + 1);
1524 }
1525 paranoid_fclose(fin);
1526 }
1527 } else {
1528 res =
1529 read_file_from_stream_to_stream(pout, slice_siz);
1530 }
1531 retval += res;
1532 res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1533 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1534 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1535 }
1536 current_slice_number++;
1537 g_current_progress++;
1538 }
1539 paranoid_pclose(pout);
1540
1541 log_msg(1, "pathname_of_last_file_restored is now %s",
1542 pathname_of_last_file_restored);
1543
1544 if (use_ntfsprog_hack) {
1545 log_msg(3, "Waiting for ntfsclone to finish");
1546 sprintf(tmp,
1547 " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1548 while (system(tmp) == 0) {
1549 sleep(1);
1550 }
1551 log_msg(3, "OK, ntfsclone has really finished");
1552 }
1553
1554 log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1555 log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1556 if (strcmp(outfile_fname, "/dev/null")) {
1557 chmod(outfile_fname, biggiestruct.properties.st_mode);
1558 chown(outfile_fname, biggiestruct.properties.st_uid,
1559 biggiestruct.properties.st_gid);
1560 ubuf->actime = biggiestruct.properties.st_atime;
1561 ubuf->modtime = biggiestruct.properties.st_mtime;
1562 utime(outfile_fname, ubuf);
1563 }
1564
1565 paranoid_free(tmp);
1566 paranoid_free(outfile_fname);
1567 paranoid_free(command);
1568 paranoid_free(ntfsprog_command);
1569 paranoid_free(sz_devfile);
1570 paranoid_free(ntfsprog_fifo);
1571 g_loglevel = old_loglevel;
1572 return (retval);
1573}
1574
1575/**************************************************************************
1576 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM *
1577 **************************************************************************/
1578
1579
1580
1581/**
1582 * Restore @p tarball_fname from CD.
1583 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1584 * This will be used unmodified.
1585 * @param current_tarball_number The number (starting from 0) of the fileset
1586 * we're restoring now.
1587 * @param filelist The node structure containing the list of files to be
1588 * restored. If no file in the afioball is in this list, afio will still be
1589 * called, but nothing will be written.
1590 * @return 0 for success, nonzero for failure.
1591 */
1592int
1593restore_a_tarball_from_CD(char *tarball_fname,
1594 long current_tarball_number,
1595 struct s_node *filelist)
1596{
1597 int retval = 0;
1598 int res;
1599 char *p;
1600
1601 /** malloc **/
1602 char *command;
1603 char *tmp;
1604 char *filelist_name;
1605 char *filelist_subset_fname;
1606 char *executable;
1607 char *temp_log;
1608 char screen_message[100];
1609 long matches = 0;
1610 bool use_star;
1611 char *xattr_fname;
1612 char *acl_fname;
1613// char files_to_restore_this_time_fname[MAX_STR_LEN];
1614
1615 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1616 malloc_string(command);
1617 malloc_string(tmp);
1618 malloc_string(filelist_name);
1619 malloc_string(filelist_subset_fname);
1620 malloc_string(executable);
1621 malloc_string(temp_log);
1622 malloc_string(xattr_fname);
1623 malloc_string(acl_fname);
1624
1625 log_msg(5, "Entering");
1626 filelist_subset_fname[0] = '\0';
1627 use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1628// sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
1629 sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
1630 run_program_and_log_output(command, 9);
1631 sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1632 (int) (random() % 32768));
1633
1634 sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
1635 current_tarball_number);
1636 if (length_of_file(filelist_name) <= 2) {
1637 log_msg(2, "There are _zero_ files in filelist '%s'",
1638 filelist_name);
1639 log_msg(2,
1640 "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1641 log_msg(2,
1642 "but it's non-critical. It's cosmetic. Don't worry about it.");
1643 retval = 0;
1644 goto leave_sub;
1645 }
1646 if (count_lines_in_file(filelist_name) <= 0
1647 || length_of_file(tarball_fname) <= 0) {
1648 log_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1649 length_of_file(tarball_fname));
1650 sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
1651 current_tarball_number);
1652 log_to_screen(tmp);
1653 retval = 1;
1654 goto leave_sub;
1655 }
1656
1657 if (filelist) {
1658 sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1659 current_tarball_number);
1660 if ((matches =
1661 save_filelist_entries_in_common(filelist_name, filelist,
1662 filelist_subset_fname,
1663 use_star))
1664 <= 0) {
1665 sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1666 log_msg(1, tmp);
1667 } else {
1668 log_msg(3, "Saved fileset %ld's subset to %s",
1669 current_tarball_number, filelist_subset_fname);
1670 }
1671 sprintf(screen_message, "Tarball #%ld --- %ld matches",
1672 current_tarball_number, matches);
1673 log_to_screen(screen_message);
1674 } else {
1675 filelist_subset_fname[0] = '\0';
1676 }
1677
1678 if (filelist == NULL || matches > 0) {
1679 if (g_getfattr) {
1680 sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1681 MNT_CDROM "/archives", current_tarball_number);
1682 }
1683 if (g_getfacl) {
1684 sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1685 current_tarball_number);
1686 }
1687 if (strstr(tarball_fname, ".bz2")) {
1688 strcpy(executable, "bzip2");
1689 } else if (strstr(tarball_fname, ".gz")) {
1690 strcpy(executable, "gzip");
1691 } else if (strstr(tarball_fname, ".lzo")) {
1692 strcpy(executable, "lzop");
1693 } else {
1694 executable[0] = '\0';
1695 }
1696 if (executable[0]) {
1697 sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
1698 if (run_program_and_log_output(tmp, FALSE)) {
1699 log_to_screen
1700 ("(compare_a_tarball) Compression program not found - oh no!");
1701 paranoid_MR_finish(1);
1702 }
1703 strcpy(tmp, executable);
1704 sprintf(executable, "-P %s -Z", tmp);
1705 }
1706#ifdef __FreeBSD__
1707#define BUFSIZE 512
1708#else
1709#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1710#endif
1711
1712// if (strstr(tarball_fname, ".star."))
1713 if (use_star) {
1714 sprintf(command,
1715 "star -x -force-remove -U " STAR_ACL_SZ
1716 " errctl= file=%s", tarball_fname);
1717 if (strstr(tarball_fname, ".bz2")) {
1718 strcat(command, " -bz");
1719 }
1720 } else {
1721 if (filelist_subset_fname[0] != '\0') {
1722 sprintf(command,
1723 "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1724 TAPE_BLOCK_SIZE,
1725 BUFSIZE, executable, filelist_subset_fname,
1726// files_to_restore_this_time_fname,
1727 tarball_fname);
1728 } else {
1729 sprintf(command,
1730 "afio -i -b %ld -c %ld -M 8m %s %s",
1731 TAPE_BLOCK_SIZE,
1732 BUFSIZE, executable, tarball_fname);
1733 }
1734 }
1735#undef BUFSIZE
1736 sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
1737 temp_log);
1738 log_msg(1, "command = '%s'", command);
1739 unlink(temp_log);
1740 res = system(command);
1741 if (res) {
1742 p = strstr(command, "-acl ");
1743 if (p) {
1744 p[0] = p[1] = p[2] = p[3] = ' ';
1745 log_msg(1, "new command = '%s'", command);
1746 res = system(command);
1747 }
1748 }
1749 if (res && length_of_file(temp_log) < 5) {
1750 res = 0;
1751 }
1752
1753 if (g_getfattr) {
1754 log_msg(1, "Setting fattr list %s", xattr_fname);
1755 if (length_of_file(xattr_fname) > 0) {
1756 res = set_fattr_list(filelist_subset_fname, xattr_fname);
1757 if (res) {
1758 log_to_screen
1759 ("Errors occurred while setting extended attributes");
1760 } else {
1761 log_msg(1, "I set xattr OK");
1762 }
1763 retval += res;
1764 }
1765 }
1766 if (g_getfacl) {
1767 log_msg(1, "Setting acl list %s", acl_fname);
1768 if (length_of_file(acl_fname) > 0) {
1769 res = set_acl_list(filelist_subset_fname, acl_fname);
1770 if (res) {
1771 log_to_screen
1772 ("Errors occurred while setting access control lists");
1773 } else {
1774 log_msg(1, "I set ACL OK");
1775 }
1776 retval += res;
1777 }
1778 }
1779 if (retval) {
1780 sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1781 system(command);
1782 log_msg(2, "Errors occurred while processing fileset #%d",
1783 current_tarball_number);
1784 } else {
1785 log_msg(2, "Fileset #%d processed OK", current_tarball_number);
1786 }
1787 }
1788 if (does_file_exist("/PAUSE")) {
1789 popup_and_OK
1790 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
1791 }
1792 unlink(filelist_subset_fname);
1793 unlink(xattr_fname);
1794 unlink(acl_fname);
1795 unlink(temp_log);
1796
1797 leave_sub:
1798 paranoid_free(command);
1799 paranoid_free(tmp);
1800 paranoid_free(filelist_name);
1801 paranoid_free(filelist_subset_fname);
1802 paranoid_free(executable);
1803 paranoid_free(temp_log);
1804 paranoid_free(xattr_fname);
1805 paranoid_free(acl_fname);
1806 log_msg(5, "Leaving");
1807 return (retval);
1808}
1809
1810/**************************************************************************
1811 *END_RESTORE_A_TARBALL_FROM_CD *
1812 **************************************************************************/
1813
1814
1815/**
1816 * Restore a tarball from the currently opened stream.
1817 * @param bkpinfo The backup information structure. Fields used:
1818 * - @c bkpinfo->backup_media_type
1819 * - @c bkpinfo->media_device
1820 * - @c bkpinfo->zip_exe
1821 * @param tarball_fname The filename of the afioball to restore.
1822 * @param current_tarball_number The number (starting from 0) of the fileset
1823 * we're restoring now.
1824 * @param filelist The node structure containing the list of files to be
1825 * restored. If no file in the afioball is in this list, afio will still be
1826 * called, but nothing will be written.
1827 * @param size The size (in @b bytes) of the afioball.
1828 * @return 0 for success, nonzero for failure.
1829 */
1830int
1831restore_a_tarball_from_stream(char *tarball_fname,
1832 long current_tarball_number,
1833 struct s_node *filelist,
1834 long long size, char *xattr_fname,
1835 char *acl_fname)
1836{
1837 int retval = 0;
1838 int res = 0;
1839
1840 /** malloc add ***/
1841 char *tmp;
1842 char *command;
1843 char *afio_fname;
1844 char *filelist_fname;
1845 char *filelist_subset_fname;
1846 char *executable;
1847 long matches = 0;
1848 bool restore_this_fileset = FALSE;
1849 bool use_star;
1850
1851 assert(bkpinfo != NULL);
1852 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1853 malloc_string(filelist_subset_fname);
1854 malloc_string(filelist_fname);
1855 malloc_string(afio_fname);
1856 malloc_string(executable);
1857 malloc_string(command);
1858 malloc_string(tmp);
1859 filelist_subset_fname[0] = '\0';
1860 /* to do it with a file... */
1861 use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1862 sprintf(tmp,
1863 "Restoring from fileset #%ld (%ld KB) on %s #%d",
1864 current_tarball_number, (long) size >> 10,
1865 media_descriptor_string(bkpinfo->backup_media_type),
1866 g_current_media_number);
1867 log_msg(2, tmp);
1868 run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1869
1870 /****************************************************************************
1871 * Use RAMDISK's /tmp; saves time; oh wait, it's too small *
1872 * Well, pipe from tape to afio, then; oh wait, can't do that either: bug *
1873 * in afio or someting; oh darn.. OK, use tmpfs :-) *
1874 ****************************************************************************/
1875 filelist_fname[0] = filelist_subset_fname[0] = '\0';
1876 sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1877 current_tarball_number);
1878 sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1879 current_tarball_number);
1880 sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1881 bkpinfo->tmpdir, current_tarball_number);
1882// sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
1883 res = read_file_from_stream_to_file(afio_fname, size);
1884 if (strstr(tarball_fname, ".star")) {
1885 bkpinfo->use_star = TRUE;
1886 }
1887 if (res) {
1888 log_msg(1, "Warning - error reading afioball from tape");
1889 }
1890 if (bkpinfo->compression_level == 0) {
1891 executable[0] = '\0';
1892 } else {
1893 if (bkpinfo->use_star) {
1894 strcpy(executable, " -bz");
1895 } else {
1896 sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
1897 }
1898 }
1899
1900 if (!filelist) // if unconditional restore then restore entire fileset
1901 {
1902 restore_this_fileset = TRUE;
1903 } else // If restoring selectively then get TOC from tarball
1904 {
1905 if (strstr(tarball_fname, ".star.")) {
1906 use_star = TRUE;
1907 sprintf(command, "star -t file=%s %s", afio_fname, executable);
1908 } else {
1909 use_star = FALSE;
1910 sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1911 executable, afio_fname);
1912 }
1913 sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
1914 MONDO_LOGFILE);
1915 log_msg(1, "command = %s", command);
1916 if (system(command)) {
1917 log_msg(4, "Warning - error occurred while retrieving TOC");
1918 }
1919 if ((matches =
1920 save_filelist_entries_in_common(filelist_fname, filelist,
1921 filelist_subset_fname,
1922 use_star))
1923 <= 0 || length_of_file(filelist_subset_fname) < 2) {
1924 if (length_of_file(filelist_subset_fname) < 2) {
1925 log_msg(1, "No matches found in fileset %ld",
1926 current_tarball_number);
1927 }
1928 sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1929 log_msg(2, tmp);
1930 restore_this_fileset = FALSE;
1931 } else {
1932 log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1933 matches, current_tarball_number,
1934 filelist_subset_fname);
1935 restore_this_fileset = TRUE;
1936 }
1937 }
1938
1939// Concoct the call to star/afio to restore files
1940 if (strstr(tarball_fname, ".star.")) // star
1941 {
1942 sprintf(command, "star -x file=%s %s", afio_fname, executable);
1943 if (filelist) {
1944 sprintf(command + strlen(command), " list=%s",
1945 filelist_subset_fname);
1946 }
1947 } else // afio
1948 {
1949 sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
1950 executable);
1951 if (filelist) {
1952 sprintf(command + strlen(command), " -w %s",
1953 filelist_subset_fname);
1954 }
1955 sprintf(command + strlen(command), " %s", afio_fname);
1956 }
1957 sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
1958
1959// Call if IF there are files to restore (selectively/unconditionally)
1960 if (restore_this_fileset) {
1961 log_msg(1, "Calling command='%s'", command);
1962 paranoid_system(command);
1963
1964 if (g_getfattr) {
1965 iamhere("Restoring xattr stuff");
1966 res = set_fattr_list(filelist_subset_fname, xattr_fname);
1967 if (res) {
1968 log_msg(1, "Errors occurred while setting xattr");
1969 } else {
1970 log_msg(1, "I set xattr OK");
1971 }
1972 retval += res;
1973 }
1974
1975 if (g_getfacl) {
1976 iamhere("Restoring acl stuff");
1977 res = set_acl_list(filelist_subset_fname, acl_fname);
1978 if (res) {
1979 log_msg(1, "Errors occurred while setting ACL");
1980 } else {
1981 log_msg(1, "I set ACL OK");
1982 }
1983 retval += res;
1984 }
1985
1986 } else {
1987 log_msg(1, "NOT CALLING '%s'", command);
1988 }
1989
1990 if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1991 log_to_screen("Paused after set %ld", current_tarball_number);
1992 popup_and_OK("Pausing. Press ENTER to continue.");
1993 }
1994
1995 unlink(filelist_subset_fname);
1996 unlink(filelist_fname);
1997 unlink(afio_fname);
1998
1999 paranoid_free(filelist_subset_fname);
2000 paranoid_free(filelist_fname);
2001 paranoid_free(afio_fname);
2002 paranoid_free(command);
2003 paranoid_free(tmp);
2004 return (retval);
2005}
2006
2007/**************************************************************************
2008 *END_RESTORE_A_TARBALL_FROM_STREAM *
2009 **************************************************************************/
2010
2011
2012
2013
2014/**
2015 * Restore all biggiefiles from all media in this CD backup.
2016 * The CD with the last afioball should be currently mounted.
2017 * @param bkpinfo The backup information structure. @c backup_media_type is the
2018 * only field used in this function.
2019 * @param filelist The node structure containing the list of files to be
2020 * restored. If a prospective biggiefile is not in this list, it will be ignored.
2021 * @return 0 for success, nonzero for failure.
2022 */
2023int
2024restore_all_biggiefiles_from_CD(struct s_node *filelist)
2025{
2026 int retval = 0;
2027 int res = 0;
2028 long noof_biggiefiles, bigfileno = 0, total_slices;
2029 /** malloc **/
2030 char *tmp;
2031 bool just_changed_cds = FALSE;
2032 char *xattr_fname;
2033 char *acl_fname;
2034 char *biggies_whose_EXATs_we_should_set; // EXtended ATtributes
2035 char *pathname_of_last_biggie_restored;
2036 FILE *fbw = NULL;
2037
2038 malloc_string(xattr_fname);
2039 malloc_string(acl_fname);
2040 malloc_string(tmp);
2041 malloc_string(biggies_whose_EXATs_we_should_set);
2042 malloc_string(pathname_of_last_biggie_restored);
2043 assert(bkpinfo != NULL);
2044
2045 sprintf(biggies_whose_EXATs_we_should_set,
2046 "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2047 if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2048 log_msg(1, "Warning - cannot openout %s",
2049 biggies_whose_EXATs_we_should_set);
2050 }
2051
2052 read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2053 total_slices = atol(tmp);
2054 sprintf(tmp, "Reassembling large files ");
2055 mvaddstr_and_log_it(g_currentY, 0, tmp);
2056 if (length_of_file(BIGGIELIST) < 6) {
2057 log_msg(1, "OK, no biggielist; not restoring biggiefiles");
2058 return (0);
2059 }
2060 noof_biggiefiles = count_lines_in_file(BIGGIELIST);
2061 if (noof_biggiefiles <= 0) {
2062 log_msg(2,
2063 "OK, no biggiefiles in biggielist; not restoring biggiefiles");
2064 return (0);
2065 }
2066 sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2067 noof_biggiefiles);
2068 log_msg(2, tmp);
2069
2070 open_progress_form("Reassembling large files",
2071 "I am now reassembling all the large files.",
2072 "Please wait. This may take some time.",
2073 "", total_slices);
2074 for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
2075 log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
2076 if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
2077 log_msg(3,
2078 "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
2079 log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
2080 bigfileno + 1,
2081 media_descriptor_string(bkpinfo->backup_media_type),
2082 g_current_media_number);
2083 log_msg(3, "Slicename would have been %s",
2084 slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
2085 // I'm not positive 'just_changed_cds' is even necessary...
2086 if (just_changed_cds) {
2087 just_changed_cds = FALSE;
2088 log_msg(3,
2089 "I'll continue to scan this CD for bigfiles to be restored.");
2090 } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2091 insist_on_this_cd_number(++g_current_media_number);
2092 sprintf(tmp, "Restoring from %s #%d",
2093 media_descriptor_string(bkpinfo->backup_media_type),
2094 g_current_media_number);
2095 log_to_screen(tmp);
2096 just_changed_cds = TRUE;
2097 } else {
2098 /* That big file doesn't exist, but the followings may */
2099 /* So we need to continue looping */
2100 log_msg(2, "There was no bigfile #%ld. That's OK.",
2101 bigfileno + 1);
2102 log_msg(2, "I'm going to stop restoring bigfiles now.");
2103 retval++;
2104 bigfileno++;
2105 }
2106 } else {
2107 just_changed_cds = FALSE;
2108 sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
2109 update_progress_form(tmp);
2110 res =
2111 restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
2112 iamhere(pathname_of_last_biggie_restored);
2113 if (fbw && pathname_of_last_biggie_restored[0]) {
2114 fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2115 }
2116 retval += res;
2117 bigfileno++;
2118
2119 }
2120 }
2121
2122 if (fbw) {
2123 fclose(fbw);
2124 if (g_getfattr) {
2125 sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2126 if (length_of_file(xattr_fname) > 0) {
2127 set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2128 }
2129 }
2130 if (g_getfacl) {
2131 sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2132 if (length_of_file(acl_fname) > 0) {
2133 set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2134 }
2135 }
2136 }
2137 if (does_file_exist("/PAUSE")) {
2138 popup_and_OK
2139 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2140 }
2141 close_progress_form();
2142 if (retval) {
2143 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2144 } else {
2145 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2146 }
2147 paranoid_free(xattr_fname);
2148 paranoid_free(acl_fname);
2149 paranoid_free(tmp);
2150 paranoid_free(biggies_whose_EXATs_we_should_set);
2151 paranoid_free(pathname_of_last_biggie_restored);
2152 return (retval);
2153}
2154
2155/**************************************************************************
2156 *END_RESTORE_ALL_BIGGIFILES_FROM_CD *
2157 **************************************************************************/
2158
2159
2160
2161/**
2162 * Restore all afioballs from all CDs in the backup.
2163 * The first CD should be inserted (if not, it will be asked for).
2164 * @param bkpinfo The backup information structure. @c backup_media_type is the
2165 * only field used in @e this function.
2166 * @param filelist The node structure containing the list of files to be
2167 * restored. If no file in some particular afioball is in this list, afio will
2168 * still be called for that fileset, but nothing will be written.
2169 * @return 0 for success, or the number of filesets that failed.
2170 */
2171int
2172restore_all_tarballs_from_CD(struct s_node *filelist)
2173{
2174 int retval = 0;
2175 int res;
2176 int attempts;
2177 long current_tarball_number = 0;
2178 long max_val;
2179 /**malloc ***/
2180 char *tmp;
2181 char *tarball_fname;
2182 char *progress_str;
2183 char *comment;
2184
2185 malloc_string(tmp);
2186 malloc_string(tarball_fname);
2187 malloc_string(progress_str);
2188 malloc_string(comment);
2189
2190 assert(bkpinfo != NULL);
2191
2192 mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2193 log_msg(2,
2194 "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2195 if (g_current_media_number != 1) {
2196 log_msg(3, "OK, that's jacked up.");
2197 g_current_media_number = 1;
2198 }
2199 insist_on_this_cd_number(g_current_media_number);
2200 read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2201 max_val = atol(tmp) + 1;
2202 sprintf(progress_str, "Restoring from %s #%d",
2203 media_descriptor_string(bkpinfo->backup_media_type),
2204 g_current_media_number);
2205 log_to_screen(progress_str);
2206 open_progress_form("Restoring from archives",
2207 "Restoring data from the archives.",
2208 "Please wait. This may take some time.",
2209 progress_str, max_val);
2210 for (;;) {
2211 insist_on_this_cd_number(g_current_media_number);
2212 update_progress_form(progress_str);
2213 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2214 current_tarball_number);
2215 if (!does_file_exist(tarball_fname)) {
2216 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2217 current_tarball_number);
2218 }
2219 if (!does_file_exist(tarball_fname)) {
2220 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2221 current_tarball_number);
2222 }
2223 if (!does_file_exist(tarball_fname)) {
2224 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2225 current_tarball_number);
2226 }
2227 if (!does_file_exist(tarball_fname)) {
2228 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2229 current_tarball_number);
2230 }
2231 if (!does_file_exist(tarball_fname)) {
2232 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
2233 current_tarball_number);
2234 }
2235 if (!does_file_exist(tarball_fname)) {
2236 if (current_tarball_number == 0) {
2237 log_to_screen
2238 ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
2239 return (0);
2240 }
2241 if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2242 || system("find " MNT_CDROM
2243 "/archives/slice* > /dev/null 2> /dev/null") ==
2244 0) {
2245 break;
2246 }
2247 g_current_media_number++;
2248 sprintf(progress_str, "Restoring from %s #%d",
2249 media_descriptor_string(bkpinfo->backup_media_type),
2250 g_current_media_number);
2251 log_to_screen(progress_str);
2252 } else {
2253 sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2254 current_tarball_number,
2255 media_descriptor_string(bkpinfo->backup_media_type),
2256 g_current_media_number);
2257// log_msg(3, "progress_str = %s", progress_str);
2258 for (res = 999, attempts = 0; attempts < 3 && res != 0;
2259 attempts++) {
2260 res =
2261 restore_a_tarball_from_CD(tarball_fname,
2262 current_tarball_number,
2263 filelist);
2264 }
2265 sprintf(tmp, "%s #%d, fileset #%ld - restore ",
2266 media_descriptor_string(bkpinfo->backup_media_type),
2267 g_current_media_number, current_tarball_number);
2268 if (res) {
2269 strcat(tmp, "reported errors");
2270 } else if (attempts > 1) {
2271 strcat(tmp, "succeeded");
2272 } else {
2273 strcat(tmp, "succeeded");
2274 }
2275 if (attempts > 1) {
2276 sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
2277 attempts);
2278 }
2279 strcpy(comment, tmp);
2280 if (attempts > 1) {
2281 log_to_screen(comment);
2282 }
2283
2284 retval += res;
2285 current_tarball_number++;
2286 g_current_progress++;
2287 }
2288 }
2289 close_progress_form();
2290 if (retval) {
2291 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2292 } else {
2293 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2294 }
2295 paranoid_free(tmp);
2296 paranoid_free(tarball_fname);
2297 paranoid_free(progress_str);
2298 paranoid_free(comment);
2299
2300 return (retval);
2301}
2302
2303/**************************************************************************
2304 *END_RESTORE_ALL_TARBALLS_FROM_CD *
2305 **************************************************************************/
2306
2307
2308
2309/**
2310 * Restore all biggiefiles from the currently opened stream.
2311 * @param bkpinfo The backup information structure. Passed to other functions.
2312 * @param filelist The node structure containing the list of files to be
2313 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2314 * @return 0 for success, or the number of biggiefiles that failed.
2315 */
2316int
2317restore_all_biggiefiles_from_stream(struct s_node *filelist)
2318{
2319 long noof_biggiefiles;
2320 long current_bigfile_number = 0;
2321 long total_slices;
2322
2323 int retval = 0;
2324 int res = 0;
2325 int ctrl_chr;
2326
2327 /** malloc add ****/
2328 char *tmp;
2329 char *biggie_fname;
2330 char *biggie_cksum;
2331 char *xattr_fname;
2332 char *acl_fname;
2333 char *p;
2334 char *pathname_of_last_biggie_restored;
2335 char *biggies_whose_EXATs_we_should_set; // EXtended ATtributes
2336 long long biggie_size;
2337 FILE *fbw = NULL;
2338
2339 malloc_string(tmp);
2340 malloc_string(biggie_fname);
2341 malloc_string(biggie_cksum);
2342 malloc_string(xattr_fname);
2343 malloc_string(acl_fname);
2344 malloc_string(biggies_whose_EXATs_we_should_set);
2345 malloc_string(pathname_of_last_biggie_restored);
2346 assert(bkpinfo != NULL);
2347
2348 read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2349
2350 total_slices = atol(tmp);
2351 sprintf(tmp, "Reassembling large files ");
2352 if (g_getfattr) {
2353 sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2354 }
2355 if (g_getfacl) {
2356 sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2357 }
2358 mvaddstr_and_log_it(g_currentY, 0, tmp);
2359 sprintf(biggies_whose_EXATs_we_should_set,
2360 "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2361 if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2362 log_msg(1, "Warning - cannot openout %s",
2363 biggies_whose_EXATs_we_should_set);
2364 }
2365// get xattr and acl files if they're there
2366 res =
2367 read_header_block_from_stream(&biggie_size, biggie_fname,
2368 &ctrl_chr);
2369 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2370 res =
2371 read_EXAT_files_from_tape(&biggie_size, biggie_fname,
2372 &ctrl_chr, xattr_fname, acl_fname);
2373 }
2374
2375 noof_biggiefiles = atol(biggie_fname);
2376 sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2377 noof_biggiefiles);
2378 log_msg(2, tmp);
2379 open_progress_form("Reassembling large files",
2380 "I am now reassembling all the large files.",
2381 "Please wait. This may take some time.",
2382 "", total_slices);
2383
2384 for (res =
2385 read_header_block_from_stream(&biggie_size, biggie_fname,
2386 &ctrl_chr);
2387 ctrl_chr != BLK_STOP_BIGGIEFILES;
2388 res =
2389 read_header_block_from_stream(&biggie_size, biggie_fname,
2390 &ctrl_chr)) {
2391 if (ctrl_chr != BLK_START_A_NORMBIGGIE
2392 && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2393 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2394 }
2395 p = strrchr(biggie_fname, '/');
2396 if (!p) {
2397 p = biggie_fname;
2398 } else {
2399 p++;
2400 }
2401 sprintf(tmp, "Restoring big file %ld (%lld K)",
2402 current_bigfile_number + 1, biggie_size / 1024);
2403 update_progress_form(tmp);
2404 res = restore_a_biggiefile_from_stream(biggie_fname,
2405 current_bigfile_number,
2406 biggie_cksum,
2407 biggie_size,
2408 filelist, ctrl_chr,
2409 pathname_of_last_biggie_restored);
2410 log_msg(1, "I believe I have restored %s",
2411 pathname_of_last_biggie_restored);
2412 if (fbw && pathname_of_last_biggie_restored[0]) {
2413 fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2414 }
2415 retval += res;
2416 current_bigfile_number++;
2417
2418 }
2419 if (current_bigfile_number != noof_biggiefiles
2420 && noof_biggiefiles != 0) {
2421 sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2422 current_bigfile_number, noof_biggiefiles);
2423 } else {
2424 sprintf(tmp,
2425 "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2426 noof_biggiefiles, current_bigfile_number);
2427 }
2428 log_msg(1, tmp);
2429
2430 if (fbw) {
2431 fclose(fbw);
2432 if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2433 iamhere("Setting biggie-EXATs");
2434 if (g_getfattr) {
2435 if (length_of_file(xattr_fname) > 0) {
2436 log_msg(1, "set_fattr_List(%s,%s)",
2437 biggies_whose_EXATs_we_should_set, xattr_fname);
2438 set_fattr_list(biggies_whose_EXATs_we_should_set,
2439 xattr_fname);
2440 }
2441 }
2442 if (g_getfacl) {
2443 if (length_of_file(acl_fname) > 0) {
2444 log_msg(1, "set_acl_list(%s,%s)",
2445 biggies_whose_EXATs_we_should_set, acl_fname);
2446 set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2447 }
2448 }
2449 } else {
2450 iamhere
2451 ("No biggiefiles selected. So, no biggie-EXATs to set.");
2452 }
2453 }
2454 if (does_file_exist("/PAUSE")) {
2455 popup_and_OK
2456 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2457 }
2458
2459 close_progress_form();
2460 if (retval) {
2461 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2462 } else {
2463 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2464 }
2465 paranoid_free(biggies_whose_EXATs_we_should_set);
2466 paranoid_free(pathname_of_last_biggie_restored);
2467 paranoid_free(biggie_fname);
2468 paranoid_free(biggie_cksum);
2469 paranoid_free(xattr_fname);
2470 paranoid_free(acl_fname);
2471 paranoid_free(tmp);
2472 return (retval);
2473}
2474
2475/**************************************************************************
2476 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM *
2477 **************************************************************************/
2478
2479
2480
2481
2482
2483
2484/**
2485 * Restore all afioballs from the currently opened tape stream.
2486 * @param bkpinfo The backup information structure. Fields used:
2487 * - @c bkpinfo->backup_media_type
2488 * - @c bkpinfo->restore_path
2489 * @param filelist The node structure containing the list of files to be
2490 * restored. If no file in an afioball is in this list, afio will still be
2491 * called for that fileset, but nothing will be written.
2492 * @return 0 for success, or the number of filesets that failed.
2493 */
2494int
2495restore_all_tarballs_from_stream(struct s_node *filelist)
2496{
2497 int retval = 0;
2498 int res;
2499 long current_afioball_number = 0;
2500 int ctrl_chr;
2501 long max_val /*, total_noof_files */ ;
2502
2503 /** malloc **/
2504 char *tmp;
2505 char *progress_str;
2506 char *tmp_fname;
2507 char *xattr_fname;
2508 char *acl_fname;
2509
2510 long long tmp_size;
2511
2512 malloc_string(tmp);
2513 malloc_string(progress_str);
2514 malloc_string(tmp_fname);
2515 assert(bkpinfo != NULL);
2516 malloc_string(xattr_fname);
2517 malloc_string(acl_fname);
2518 mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2519 read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2520 max_val = atol(tmp) + 1;
2521
2522 chdir(bkpinfo->restore_path); /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2523
2524 run_program_and_log_output("pwd", 5);
2525
2526 sprintf(progress_str, "Restoring from media #%d",
2527 g_current_media_number);
2528 log_to_screen(progress_str);
2529 open_progress_form("Restoring from archives",
2530 "Restoring data from the archives.",
2531 "Please wait. This may take some time.",
2532 progress_str, max_val);
2533
2534 log_msg(3, "hey");
2535
2536 res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2537 if (res) {
2538 log_msg(2, "Warning - error reading afioball from tape");
2539 }
2540 retval += res;
2541 if (ctrl_chr != BLK_START_AFIOBALLS) {
2542 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2543 }
2544 log_msg(2, "ho");
2545 res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2546 while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2547 update_progress_form(progress_str);
2548 if (g_getfattr) {
2549 sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2550 current_afioball_number);
2551 unlink(xattr_fname);
2552 }
2553 if (g_getfacl) {
2554 sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2555 current_afioball_number);
2556 unlink(acl_fname);
2557 }
2558 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2559 iamhere("Reading EXAT files from tape");
2560 res =
2561 read_EXAT_files_from_tape(&tmp_size, tmp_fname,
2562 &ctrl_chr, xattr_fname,
2563 acl_fname);
2564 }
2565 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2566 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2567 }
2568 sprintf(tmp,
2569 "Restoring from fileset #%ld (name=%s, size=%ld K)",
2570 current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2571 res =
2572 restore_a_tarball_from_stream(tmp_fname,
2573 current_afioball_number,
2574 filelist, tmp_size, xattr_fname,
2575 acl_fname);
2576 retval += res;
2577 if (res) {
2578 sprintf(tmp, "Fileset %ld - errors occurred",
2579 current_afioball_number);
2580 log_to_screen(tmp);
2581 }
2582 res =
2583 read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2584 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2585 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2586 }
2587
2588 current_afioball_number++;
2589 g_current_progress++;
2590 sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2591 current_afioball_number,
2592 media_descriptor_string(bkpinfo->backup_media_type),
2593 g_current_media_number);
2594 res =
2595 read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2596 if (g_getfattr) {
2597 unlink(xattr_fname);
2598 }
2599 if (g_getfacl) {
2600 unlink(acl_fname);
2601 }
2602 } // next
2603 log_msg(1, "All done with afioballs");
2604 close_progress_form();
2605 if (retval) {
2606 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2607 } else {
2608 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2609 }
2610 paranoid_free(tmp);
2611 paranoid_free(progress_str);
2612 paranoid_free(tmp_fname);
2613 paranoid_free(xattr_fname);
2614 paranoid_free(acl_fname);
2615 return (retval);
2616}
2617
2618/**************************************************************************
2619 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM *
2620 **************************************************************************/
2621
2622/* @} - end of LLrestoreGroup */
2623
2624
2625/**
2626 * Restore all files in @p filelist.
2627 * @param bkpinfo The backup information structure. Most fields are used.
2628 * @param filelist The node structure containing the list of files to be
2629 * restored.
2630 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2631 * @ingroup restoreGroup
2632 */
2633int restore_everything(struct s_node *filelist)
2634{
2635 int resA;
2636 int resB;
2637
2638 /** mallco ***/
2639 char *cwd;
2640 char *newpath;
2641 char *tmp;
2642 assert(bkpinfo != NULL);
2643
2644 malloc_string(cwd);
2645 malloc_string(newpath);
2646 malloc_string(tmp);
2647 log_msg(2, "restore_everything() --- starting");
2648 g_current_media_number = 1;
2649 getcwd(cwd, MAX_STR_LEN - 1);
2650 sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
2651 run_program_and_log_output(tmp, FALSE);
2652 log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2653 chdir(bkpinfo->restore_path);
2654 getcwd(newpath, MAX_STR_LEN - 1);
2655 log_msg(1, "path is now %s", newpath);
2656 log_msg(1, "restoring everything");
2657 if (!find_home_of_exe("petris") && !g_text_mode) {
2658 newtDrawRootText(0, g_noof_rows - 2,
2659 "Press ALT-<left cursor> twice to play Petris :-) ");
2660 newtRefresh();
2661 }
2662 mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
2663 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2664 mount_media();
2665 mvaddstr_and_log_it(g_currentY++, 0,
2666 "Restoring OS and data from streaming media");
2667 if (bkpinfo->backup_media_type == cdstream) {
2668 openin_cdstream();
2669 } else {
2670 assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
2671 openin_tape();
2672 }
2673 resA = restore_all_tarballs_from_stream(filelist);
2674 resB = restore_all_biggiefiles_from_stream(filelist);
2675 if (bkpinfo->backup_media_type == cdstream) {
2676 closein_cdstream();
2677 } else {
2678 closein_tape();
2679 }
2680 } else {
2681 mvaddstr_and_log_it(g_currentY++, 0,
2682 "Restoring OS and data from CD/USB ");
2683 mount_media();
2684 resA = restore_all_tarballs_from_CD(filelist);
2685 resB = restore_all_biggiefiles_from_CD(filelist);
2686 }
2687 chdir(cwd);
2688 if (resA + resB) {
2689 log_to_screen("Errors occurred while data was being restored.");
2690 }
2691 if (length_of_file("/etc/raidtab") > 0) {
2692 log_msg(2, "Copying local raidtab to restored filesystem");
2693 run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2694 "/etc/raidtab", FALSE);
2695 }
2696 kill_petris();
2697 log_msg(2, "restore_everything() --- leaving");
2698 paranoid_free(cwd);
2699 paranoid_free(newpath);
2700 paranoid_free(tmp);
2701 return (resA + resB);
2702}
2703
2704/**************************************************************************
2705 *END_RESTORE_EVERYTHING *
2706 **************************************************************************/
2707
2708
2709
2710/**
2711 * @brief Haha. You wish! (This function is not implemented :-)
2712 */
2713int
2714restore_live_from_monitas_server(char *monitas_device,
2715 char *restore_this_directory,
2716 char *restore_here)
2717 /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2718{
2719 FILE *fout;
2720 int retval = 0;
2721 int i;
2722 int j;
2723 struct mountlist_itself the_mountlist;
2724 static struct raidlist_itself the_raidlist;
2725 /** malloc **/
2726 char tmp[MAX_STR_LEN + 1];
2727 char command[MAX_STR_LEN + 1];
2728 char datablock[256 * 1024];
2729 char datadisks_fname[MAX_STR_LEN + 1];
2730 long k;
2731 long length;
2732 long long llt;
2733 struct s_node *filelist = NULL;
2734 assert(bkpinfo != NULL);
2735 assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2736 assert(restore_this_directory != NULL);
2737 assert(restore_here != NULL);
2738
2739 sprintf(tmp, "restore_here = '%s'", restore_here);
2740
2741 log_msg(2, tmp);
2742
2743 log_msg(2, "restore_live_from_monitas_server() - starting");
2744 unlink("/tmp/mountlist.txt");
2745 unlink("/tmp/filelist.full");
2746 unlink("/tmp/biggielist.txt");
2747 if (restore_here[0] == '\0') {
2748 strcpy(bkpinfo->restore_path, MNT_RESTORING);
2749 } else {
2750 strcpy(bkpinfo->restore_path, restore_here);
2751 }
2752 log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2753 sprintf(tmp, "FYI - data will be restored to %s",
2754 bkpinfo->restore_path);
2755 log_msg(3, tmp);
2756 log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2757 sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2758 (int) (random() % 32768));
2759 chdir(bkpinfo->tmpdir);
2760
2761 sprintf(command, "cat %s", monitas_device);
2762 g_tape_stream = popen(command, "r"); // for compatibility with openin_tape()
2763 if (!(fout = fopen(datadisks_fname, "w"))) {
2764 log_OS_error(datadisks_fname);
2765 return (1);
2766 }
2767 for (i = 0; i < 32; i++) {
2768 for (j = 0; j < 4; j++) {
2769 for (length = k = 0; length < 256 * 1024; length += k) {
2770 k = fread(datablock + length, 1, 256 * 1024 - length,
2771 g_tape_stream);
2772 }
2773 fwrite(datablock, 1, length, fout);
2774 g_tape_posK += length;
2775 }
2776 }
2777 paranoid_fclose(fout);
2778 sprintf(command,
2779 "tar -zxvf %s tmp/mondo-restore.cfg tmp/mountlist.txt tmp/filelist.full tmp/biggielist.txt",
2780 datadisks_fname);
2781 run_program_and_log_output(command, 4);
2782 read_header_block_from_stream(&llt, tmp, &i);
2783 read_header_block_from_stream(&llt, tmp, &i);
2784
2785 unlink(datadisks_fname);
2786 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
2787 retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo strcpy(bkpinfo->media_device, monitas_device);
2788
2789
2790 load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2791 iamhere("FIXME");
2792 fatal_error("This will fail");
2793 sprintf(command,
2794 "grep -E '^%s.*$' %s > %s",
2795 restore_this_directory, g_filelist_full, g_filelist_full);
2796 if (system(command)) {
2797 retval++;
2798 log_to_screen
2799 ("Error(s) occurred while processing filelist and wildcard");
2800 }
2801 iamhere("FIXME");
2802 fatal_error("This will fail");
2803 sprintf(command,
2804 "grep -E '^%s.*$' %s > %s",
2805 restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2806 if (system(command)) {
2807 log_msg(1,
2808 "Error(s) occurred while processing biggielist and wildcard");
2809 }
2810 sprintf(command, "touch %s", g_biggielist_txt);
2811 run_program_and_log_output(command, FALSE);
2812// filelist = load_filelist(g_filelist_restthese); // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2813 retval += restore_everything(filelist);
2814 free_filelist(filelist);
2815 log_msg(2, "--------End of restore_live_from_monitas_server--------");
2816 return (retval);
2817}
2818
2819/**************************************************************************
2820 *END_RESTORE_LIVE_FROM_MONITAS_SERVER *
2821 **************************************************************************/
2822
2823
2824
2825
2826extern void wait_until_software_raids_are_prepped(char *, int);
2827
2828
2829char which_restore_mode(void);
2830
2831
2832/**
2833 * Log a "don't panic" message to the logfile.
2834 */
2835void welcome_to_mondorestore()
2836{
2837 log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2838 log_msg(0,
2839 "DON'T PANIC! Mondorestore logs almost everything, so please ");
2840 log_msg(0,
2841 "don't break out in a cold sweat just because you see a few ");
2842 log_msg(0,
2843 "error messages in the log. Read them; analyze them; see if ");
2844 log_msg(0,
2845 "they are significant; above all, verify your backups! Please");
2846 log_msg(0,
2847 "attach a compressed copy of this log to any e-mail you send ");
2848 log_msg(0,
2849 "to the Mondo mailing list when you are seeking technical ");
2850 log_msg(0,
2851 "support. Without it, we can't help you. - DevTeam");
2852 log_msg(0,
2853 "------------------------------------------------------------");
2854 log_msg(0,
2855 "BTW, despite (or perhaps because of) the wealth of messages,");
2856 log_msg(0,
2857 "some users are inclined to stop reading this log. If Mondo ");
2858 log_msg(0,
2859 "stopped for some reason, chances are it's detailed here. ");
2860 log_msg(0,
2861 "More than likely there's a message at the very end of this ");
2862 log_msg(0,
2863 "log that will tell you what is wrong. Please read it! ");
2864 log_msg(0,
2865 "------------------------------------------------------------");
2866}
2867
2868
2869
2870/**
2871 * Restore the user's data.
2872 * What did you think it did, anyway? :-)
2873 */
2874int main(int argc, char *argv[])
2875{
2876 FILE *fin;
2877 FILE *fout;
2878 int retval = 0;
2879 int res;
2880// int c;
2881 char *tmp;
2882
2883 struct mountlist_itself *mountlist;
2884 struct raidlist_itself *raidlist;
2885 struct s_node *filelist;
2886 char *a, *b;
2887 bool run_postnuke = FALSE;
2888
2889 /**************************************************************************
2890 * hugo- *
2891 * busy stuff here - it needs some comments -stan *
2892 * *
2893 **************************************************************************/
2894 if (getuid() != 0) {
2895 fprintf(stderr, "Please run as root.\r\n");
2896 exit(127);
2897 }
2898 if (!
2899 (bkpinfo = malloc(sizeof(struct s_bkpinfo)))) {
2900 fatal_error("Cannot malloc bkpinfo");
2901 }
2902 reset_bkpinfo();
2903
2904 g_loglevel = DEFAULT_MR_LOGLEVEL;
2905 malloc_string(tmp);
2906
2907/* Configure global variables */
2908#ifdef __FreeBSD__
2909 if (strstr
2910 (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2911 "textonly"))
2912#else
2913 if (strstr
2914 (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2915 "textonly"))
2916#endif
2917 {
2918 g_text_mode = TRUE;
2919 log_msg(1, "TEXTONLY MODE");
2920 } else {
2921 g_text_mode = FALSE;
2922 } // newt :-)
2923 if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
2924 fatal_error("Cannot malloc mountlist");
2925 }
2926 if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
2927 fatal_error("Cannot malloc raidlist");
2928 }
2929
2930 malloc_libmondo_global_strings();
2931
2932 strcpy(g_mondo_home,
2933 call_program_and_get_last_line_of_output("which mondorestore"));
2934 sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2935 make_hole_for_dir(g_tmpfs_mountpt);
2936 g_current_media_number = 1; // precaution
2937
2938 run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2939 run_program_and_log_output("mkdir -p /mnt/floppy", FALSE);
2940
2941 malloc_string(tmp);
2942 malloc_string(a);
2943 malloc_string(b);
2944 setup_MR_global_filenames(); // malloc() and set globals, using bkpinfo->tmpdir etc.
2945 bkpinfo->backup_media_type = none; // in case boot disk was made for one backup type but user wants to restore from another backup type
2946 bkpinfo->restore_data = TRUE; // Well, yeah :-)
2947 if (am_I_in_disaster_recovery_mode()) {
2948 run_program_and_log_output("mount / -o remount,rw", 2);
2949 } // for b0rken distros
2950 g_main_pid = getpid();
2951 srandom((int) (time(NULL)));
2952 register_pid(getpid(), "mondo");
2953 set_signals(TRUE);
2954 g_kernel_version = get_kernel_version();
2955
2956 log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2957 if (strlen(g_mountlist_fname) < 3) {
2958 fatal_error
2959 ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2960 }
2961 mkdir(MNT_CDROM, 0x770);
2962 make_hole_for_dir(MONDO_CACHE);
2963
2964/* Backup original mountlist.txt */
2965 sprintf(tmp, "%s.orig", g_mountlist_fname);
2966 if (!does_file_exist(g_mountlist_fname)) {
2967 log_msg(2,
2968 "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2969 __LINE__, g_mountlist_fname);
2970 } else if (!does_file_exist(tmp)) {
2971 sprintf(tmp, "cp -f %s %s.orig", g_mountlist_fname,
2972 g_mountlist_fname);
2973 run_program_and_log_output(tmp, FALSE);
2974 }
2975
2976/* Init directories */
2977 make_hole_for_dir("/var/log");
2978 make_hole_for_dir("/tmp/tmpfs"); /* just in case... */
2979 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2980 /*
2981 run_program_and_log_output("ln -sf /var/log/mondo-archive.log /tmp/mondorestore.log",
2982 FALSE);
2983 */
2984
2985 run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2986
2987/* Init GUI */
2988 malloc_libmondo_global_strings();
2989 setup_newt_stuff(); /* call newtInit and setup screen log */
2990 welcome_to_mondorestore();
2991 if (bkpinfo->disaster_recovery) {
2992 log_msg(1, "I am in disaster recovery mode");
2993 } else {
2994 log_msg(1, "I am in normal, live mode");
2995 }
2996
2997 iamhere("what time is it");
2998
2999/* Process command-line parameters */
3000 if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
3001#ifdef __FreeBSD__
3002 system("mv -f /tmp/raidconf.txt /etc/raidtab");
3003 if (!does_file_exist("/etc/raidtab"))
3004 system("vinum printconfig > /etc/raidtab");
3005#endif
3006 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3007 if (!does_file_exist(g_mountlist_fname)) {
3008 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3009 }
3010 res = let_user_edit_the_mountlist(mountlist, raidlist);
3011#ifdef __FreeBSD__
3012 system("mv -f /etc/raidtab /tmp/raidconf.txt");
3013#endif
3014 paranoid_MR_finish(res);
3015 }
3016
3017 g_loglevel = DEFAULT_MR_LOGLEVEL;
3018 if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
3019 fout = fopen("/tmp/out.txt", "w");
3020 fput_string_one_char_at_a_time(stderr, argv[2]);
3021 finish(0);
3022 }
3023
3024 if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
3025 make_grub_install_scriptlet(argv[2]);
3026 finish(0);
3027 }
3028
3029 if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
3030 if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
3031 system("mount " MNT_CDROM);
3032 }
3033 bkpinfo->compression_level = 1;
3034 g_current_media_number = 2;
3035 strcpy(bkpinfo->restore_path, "/tmp/TESTING");
3036 bkpinfo->backup_media_type = dvd;
3037 open_progress_form("Reassembling /dev/hda1",
3038 "Shark is a bit of a silly person.",
3039 "Please wait. This may take some time.",
3040 "", 1999);
3041 system("rm -Rf /tmp/*pih*");
3042
3043 restore_a_biggiefile_from_CD(42, NULL, tmp);
3044 }
3045
3046 if (argc == 5 && strcmp(argv[1], "--common") == 0) {
3047 g_loglevel = 6;
3048 filelist = load_filelist(argv[2]);
3049 if (!filelist) {
3050 fatal_error("Failed to load filelist");
3051 }
3052 toggle_node_selection(filelist, FALSE);
3053 toggle_all_root_dirs_on(filelist);
3054 // BERLIOS: /usr/lib ???
3055 toggle_path_selection(filelist, "/usr/share", TRUE);
3056// show_filelist(filelist);
3057 save_filelist(filelist, "/tmp/out.txt");
3058// finish(0);
3059// toggle_path_selection (filelist, "/root/stuff", TRUE);
3060 strcpy(a, argv[3]);
3061 strcpy(b, argv[4]);
3062
3063 res = save_filelist_entries_in_common(a, filelist, b, FALSE);
3064 free_filelist(filelist);
3065 printf("res = %d", res);
3066 finish(0);
3067 }
3068
3069 if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
3070 popup_changelist_from_file(argv[2]);
3071 paranoid_MR_finish(0);
3072 }
3073
3074 if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
3075 log_msg(1, "SCORE");
3076 g_loglevel = 10;
3077 if (strstr(argv[2], "save")) {
3078 log_msg(1, "Saving from %s to %s", argv[3], argv[4]);
3079 fin = fopen(argv[3], "r");
3080 fout = fopen(argv[4], "w");
3081 copy_from_src_to_dest(fin, fout, 'w');
3082 fclose(fin);
3083 fin = fopen(argv[3], "r");
3084 copy_from_src_to_dest(fin, fout, 'w');
3085 fclose(fout);
3086 fclose(fin);
3087 } else if (strstr(argv[2], "restore")) {
3088 fout = fopen(argv[3], "w");
3089 fin = fopen(argv[4], "r");
3090 copy_from_src_to_dest(fout, fin, 'r');
3091 fclose(fin);
3092 fin = fopen(argv[4], "r");
3093 copy_from_src_to_dest(fout, fin, 'r');
3094 fclose(fout);
3095 fclose(fin);
3096 } else {
3097 fatal_error("Unknown additional param");
3098 }
3099 finish(0);
3100 }
3101
3102 if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
3103 wait_until_software_raids_are_prepped(argv[2], 100);
3104 finish(0);
3105 }
3106
3107 if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
3108 finish(create_raidtab_from_mdstat(argv[2]));
3109 }
3110
3111 if (argc == 3 && strcmp(argv[1], "-p") == 0) {
3112 strcpy(bkpinfo->prefix,argv[2]);
3113 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
3114 }
3115
3116 if (argc == 3 && strcmp(argv[1], "-K") == 0) {
3117 g_loglevel = atoi(argv[2]);
3118 log_msg(1,"Loglevel forced to %s",g_loglevel);
3119 }
3120
3121 if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
3122 retval = run_grub(FALSE, "/dev/hda");
3123 if (retval) {
3124 log_to_screen("Failed to write Master Boot Record");
3125 }
3126 paranoid_MR_finish(0);
3127 }
3128 if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
3129 g_current_media_number = atoi(argv[2]);
3130 pause_and_ask_for_cdr(5, NULL);
3131 paranoid_MR_finish(0);
3132 } else if (!bkpinfo->disaster_recovery) { // live!
3133 if (argc != 1) {
3134 popup_and_OK
3135 ("Live mode doesn't support command-line parameters yet.");
3136 paranoid_MR_finish(1);
3137// return(1);
3138 }
3139 log_msg(1, "I am in normal, live mode.");
3140 log_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
3141 mount_boot_if_necessary(); /* for Gentoo users */
3142 log_msg(2, "Still here.");
3143 if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
3144 g_restoring_live_from_cd = TRUE;
3145 }
3146 if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
3147 retval =
3148 restore_live_from_monitas_server(argv[2],
3149 argv[3], argv[4]);
3150 } else {
3151 log_msg(2, "Calling restore_to_live_filesystem()");
3152 retval = restore_to_live_filesystem();
3153 }
3154 log_msg(2, "Still here. Yay.");
3155 if (strlen(bkpinfo->tmpdir) > 0) {
3156 sprintf(tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3157 run_program_and_log_output(tmp, FALSE);
3158 }
3159 unmount_boot_if_necessary(); /* for Gentoo users */
3160 paranoid_MR_finish(retval);
3161 } else {
3162 /* Disaster recovery mode (must be) */
3163 log_msg(1, "I must be in disaster recovery mode.");
3164 log_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3165 if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
3166 log_to_screen("Uh, that hasn't been implemented yet.");
3167 paranoid_MR_finish(1);
3168 }
3169
3170 iamhere("About to call load_mountlist and load_raidtab");
3171 strcpy(bkpinfo->restore_path, MNT_RESTORING);
3172 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
3173 retval = load_mountlist(mountlist, g_mountlist_fname);
3174 retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3175 iamhere
3176 ("Returned from calling load_mountlist and load_raidtab successfully");
3177
3178 if (argc > 1
3179 && (strcmp(argv[1], "--compare") == 0
3180 || strcmp(argv[1], "--nuke") == 0)) {
3181 if (bkpinfo->backup_media_type == nfs
3182 && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3183 log_msg(1, "Mounting nfs dir");
3184 sprintf(bkpinfo->isodir, "/tmp/isodir");
3185 run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3186 sprintf(tmp, "mount %s -t nfs -o nolock /tmp/isodir",
3187 bkpinfo->nfs_mount);
3188 run_program_and_log_output(tmp, 1);
3189 }
3190 }
3191
3192
3193 if (retval) {
3194 log_to_screen
3195 ("Warning - load_raidtab_into_raidlist returned an error");
3196 }
3197
3198
3199 log_msg(1, "Send in the clowns.");
3200
3201 if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
3202 log_msg(0, "Partitioning only.");
3203 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3204 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3205 load_mountlist(mountlist, g_mountlist_fname);
3206 res = partition_everything(mountlist);
3207 finish(res);
3208 }
3209
3210 if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3211 log_msg(0, "Formatting only.");
3212 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3213 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3214 load_mountlist(mountlist, g_mountlist_fname);
3215 res = format_everything(mountlist, FALSE, raidlist);
3216 finish(res);
3217 }
3218
3219 if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3220 log_msg(0, "Stopping LVM and RAID");
3221 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3222 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3223 load_mountlist(mountlist, g_mountlist_fname);
3224 res = do_my_funky_lvm_stuff(TRUE, FALSE);
3225 res += stop_all_raid_devices(mountlist);
3226 finish(res);
3227 }
3228
3229 if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3230 iamhere("nuking");
3231 retval += nuke_mode(mountlist, raidlist);
3232 } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3233 iamhere("catchall");
3234 retval += catchall_mode(mountlist, raidlist);
3235 } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3236 iamhere("compare");
3237 retval += compare_mode(mountlist, raidlist);
3238 } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3239 iamhere("iso");
3240 retval = iso_mode(mountlist, raidlist, FALSE);
3241 } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3242 iamhere("mbr");
3243 retval = mount_all_devices(mountlist, TRUE);
3244 if (!retval) {
3245 retval += run_boot_loader(FALSE);
3246 retval += unmount_all_devices(mountlist);
3247 }
3248 if (retval) {
3249 log_to_screen("Failed to write Master Boot Record");
3250 }
3251 } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3252 iamhere("isonuke");
3253 retval = iso_mode(mountlist, raidlist, TRUE);
3254 } else if (argc != 1) {
3255 log_to_screen("Invalid paremeters");
3256 paranoid_MR_finish(1);
3257 } else {
3258 iamhere("catchall (no mode specified in command-line call");
3259 retval += catchall_mode(mountlist, raidlist);
3260 }
3261 }
3262
3263 /* clean up at the end */
3264 if (retval) {
3265 if (does_file_exist(MONDO_CACHE"/changed.files")) {
3266 log_to_screen
3267 ("See "MONDO_CACHE"/changed.files for list of files that have changed.");
3268 }
3269 mvaddstr_and_log_it(g_currentY++,
3270 0,
3271 "Run complete. Errors were reported. Please review the logfile.");
3272 } else {
3273 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3274 mvaddstr_and_log_it(g_currentY++,
3275 0,
3276 "Run complete. Please remove floppy/CD/media and reboot.");
3277 } else {
3278 run_program_and_log_output("sync", FALSE);
3279 if (is_this_device_mounted(MNT_CDROM)) {
3280 res =
3281 run_program_and_log_output("umount " MNT_CDROM, FALSE);
3282 } else {
3283 res = 0;
3284 }
3285
3286 if (!bkpinfo->please_dont_eject) {
3287 res = eject_device("/dev/cdrom");
3288/*
3289 if (res)
3290 {
3291 log_to_screen( "WARNING - failed to eject CD-ROM disk" );
3292 }
3293*/
3294 }
3295 mvaddstr_and_log_it(g_currentY++,
3296 0,
3297 "Run complete. Please remove media and reboot.");
3298 }
3299 }
3300
3301// g_I_have_just_nuked is set true by nuke_mode() just before it returns
3302 if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3303 log_msg(1, "post-nuke found; find out whether we should run it...");
3304 if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3305 run_postnuke = TRUE;
3306 log_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3307 } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3308 run_postnuke = TRUE;
3309 log_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3310 } else {
3311 run_postnuke = FALSE;
3312 log_msg(1, "No, will not run post-nuke.");
3313 }
3314 } else {
3315 log_msg(1, "No post-nuke found.");
3316 }
3317 if (run_postnuke) {
3318 log_to_screen("Running post-nuke...");
3319 if (mount_all_devices(mountlist, TRUE)) {
3320 log_to_screen
3321 ("Unable to re-mount partitions for post-nuke stuff");
3322 } else {
3323 log_msg(1, "Re-mounted partitions for post-nuke stuff");
3324 sprintf(tmp, "post-nuke %s %d", bkpinfo->restore_path,
3325 retval);
3326 log_msg(2, "Calling '%s'", tmp);
3327 if ((res = run_program_and_log_output(tmp, 0))) {
3328 log_OS_error(tmp);
3329 }
3330 log_msg(1, "post-nuke returned w/ res=%d", res);
3331 }
3332 unmount_all_devices(mountlist);
3333 log_to_screen("I've finished post-nuking.");
3334 }
3335
3336/*
3337 log_to_screen("If you are REALLY in a hurry, hit Ctrl-Alt-Del now.");
3338 log_to_screen("Otherwise, please wait until the RAID disks are done.");
3339 wait_until_software_raids_are_prepped("/proc/mdstat", 100);
3340 log_to_screen("Thank you.");
3341*/
3342 unlink("/tmp/mondo-run-prog.tmp");
3343 set_signals(FALSE);
3344 log_to_screen("Restore log (%s) copied to /var/log on your hard disk", MONDO_LOGFILE);
3345 sprintf(tmp,
3346 "Mondo-restore is exiting (retval=%d) ",
3347 retval);
3348 log_to_screen(tmp);
3349 sprintf(tmp, "umount %s", bkpinfo->isodir);
3350 run_program_and_log_output(tmp, 5);
3351 paranoid_free(mountlist);
3352 paranoid_free(raidlist);
3353 if (am_I_in_disaster_recovery_mode()) {
3354 run_program_and_log_output("mount / -o remount,rw", 2);
3355 } // for b0rken distros
3356 sprintf(tmp, "rm -Rf %s", bkpinfo->tmpdir);
3357 system(tmp);
3358 paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3359 free_libmondo_global_strings(); // it's fine to have this here :) really :)
3360 paranoid_free(a);
3361 paranoid_free(b);
3362 paranoid_free(tmp);
3363
3364 unlink("/tmp/filelist.full");
3365 unlink("/tmp/filelist.full.gz");
3366
3367 exit(retval);
3368}
3369
3370/**************************************************************************
3371 *END_MAIN *
3372 **************************************************************************/
3373
3374
3375
3376
3377
3378/**************************************************************************
3379 *END_MONDO-RESTORE.C *
3380 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.