source: MondoRescue/branches/2.2.6/mondo/src/mondorestore/mondorestore.c@ 1930

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

Renaming of files to be in conformity with stable and ease aplication of patches between branches.

  • Property svn:keywords set to Id
File size: 100.6 KB
Line 
1/***************************************************************************
2$Id: mondorestore.c 1930 2008-04-22 12:05:49Z 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 "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: mondorestore.c 1930 2008-04-22 12:05:49Z 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 media 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 && !g_restoring_live_from_nfs) {
929 popup_and_OK
930 ("Please insert tape/CD/USB Key, then hit 'OK' to continue.");
931 sleep(1);
932 }
933 if (!g_restoring_live_from_nfs) {
934 interactively_obtain_media_parameters_from_user(FALSE);
935 }
936 log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
937 if (!bkpinfo->media_device[0]) {
938 log_msg(2, "Warning - failed to find media dev");
939 }
940
941
942 log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
943
944 open_evalcall_form("Thinking...");
945
946 get_cfg_file_from_archive_or_bust();
947 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
948 load_mountlist(mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo
949
950 close_evalcall_form();
951 retval = load_mountlist(mountlist, g_mountlist_fname);
952 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
953
954 if (!g_restoring_live_from_nfs && (filelist = process_filelist_and_biggielist())) {
955 save_filelist(filelist, "/tmp/selected-files.txt");
956 strcpy(old_restpath, bkpinfo->restore_path);
957 if (popup_and_get_string("Restore path",
958 "Restore files to where? )",
959 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
960 iamhere("Restoring everything");
961 retval += restore_everything(filelist);
962 free_filelist(filelist);
963 strcpy(bkpinfo->restore_path, old_restpath);
964 } else {
965 free_filelist(filelist);
966 }
967 strcpy(bkpinfo->restore_path, old_restpath);
968 } else {
969 retval += restore_everything(NULL);
970 }
971 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
972 log_msg(2,
973 "Tape : I don't need to unmount or eject the CD-ROM.");
974 } else {
975 run_program_and_log_output("umount " MNT_CDROM, FALSE);
976 if (!bkpinfo->please_dont_eject) {
977 eject_device(bkpinfo->media_device);
978 }
979 }
980 run_program_and_log_output("umount " MNT_CDROM, FALSE);
981 if (!bkpinfo->please_dont_eject) {
982 eject_device(bkpinfo->media_device);
983 }
984 paranoid_free(old_restpath);
985 free(mountlist);
986 free(raidlist);
987 return (retval);
988}
989
990/**************************************************************************
991 *END_RESTORE_TO_LIVE_FILESYSTEM *
992 **************************************************************************/
993
994/* @} - end of restoreGroup */
995
996
997#include <utime.h>
998/**
999 * @addtogroup LLrestoreGroup
1000 * @{
1001 */
1002/**
1003 * Restore biggiefile @p bigfileno from the currently mounted CD.
1004 * @param bkpinfo The backup information structure. Fields used:
1005 * - @c bkpinfo->backup_media_type
1006 * - @c bkpinfo->restore_path
1007 * @param bigfileno The biggiefile number (starting from 0) to restore.
1008 * @param filelist The node structure containing the list of files to restore.
1009 * If the biggiefile is not in this list, it will be skipped (return value will
1010 * still indicate success).
1011 * @return 0 for success (or skip), nonzero for failure.
1012 */
1013int
1014restore_a_biggiefile_from_CD(long bigfileno,
1015 struct s_node *filelist,
1016 char *pathname_of_last_file_restored)
1017{
1018 FILE *fin;
1019 FILE *fout;
1020 FILE *fbzip2;
1021
1022 /** malloc ***/
1023 char *checksum, *outfile_fname, *tmp, *bzip2_command,
1024 *ntfsprog_command, *suffix, *sz_devfile;
1025 char *bigblk;
1026 char *p;
1027 int retval = 0;
1028 int finished = FALSE;
1029 long sliceno;
1030 long siz;
1031 char ntfsprog_fifo[MAX_STR_LEN];
1032 char *file_to_openout = NULL;
1033 struct s_filename_and_lstat_info biggiestruct;
1034 struct utimbuf the_utime_buf, *ubuf;
1035 bool use_ntfsprog_hack = FALSE;
1036 pid_t pid;
1037 int res = 0;
1038 int old_loglevel;
1039 char sz_msg[MAX_STR_LEN];
1040 struct s_node *node;
1041
1042 old_loglevel = g_loglevel;
1043 ubuf = &the_utime_buf;
1044 assert(bkpinfo != NULL);
1045
1046 malloc_string(checksum);
1047 malloc_string(outfile_fname);
1048 malloc_string(tmp);
1049 malloc_string(bzip2_command);
1050 malloc_string(ntfsprog_command);
1051 malloc_string(suffix);
1052 malloc_string(sz_devfile);
1053
1054 pathname_of_last_file_restored[0] = '\0';
1055 if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
1056 fatal_error("Cannot malloc bigblk");
1057 }
1058
1059 if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1060 log_to_screen("Cannot even open bigfile's info file");
1061 return (1);
1062 }
1063
1064 memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1065 if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1066 sizeof(biggiestruct)) {
1067 log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1068 bigfileno + 1);
1069 }
1070 paranoid_fclose(fin);
1071
1072 strcpy(checksum, biggiestruct.checksum);
1073
1074 if (!checksum[0]) {
1075 sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
1076 bigfileno + 1);
1077 log_msg(3, tmp);
1078 p = checksum;
1079 }
1080
1081 if (!strncmp(biggiestruct.filename, "/dev/", 5)) // Whether NTFS or not :)
1082 {
1083 strcpy(outfile_fname, biggiestruct.filename);
1084 } else {
1085 sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1086 biggiestruct.filename);
1087 }
1088
1089 /* skip file if we have a selective restore subset & it doesn't match */
1090 if (filelist != NULL) {
1091 node = find_string_at_node(filelist, biggiestruct.filename);
1092 if (!node) {
1093 log_msg(0, "Skipping %s (name isn't in filelist)",
1094 biggiestruct.filename);
1095 pathname_of_last_file_restored[0] = '\0';
1096 return (0);
1097 } else if (!(node->selected)) {
1098 log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1099 biggiestruct.filename);
1100 pathname_of_last_file_restored[0] = '\0';
1101 return (0);
1102 }
1103 }
1104 /* otherwise, continue */
1105
1106 log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1107 if (biggiestruct.use_ntfsprog) {
1108 if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1109 log_msg(1,
1110 "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1111 log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1112 biggiestruct.use_ntfsprog = FALSE;
1113 }
1114 }
1115
1116 if (biggiestruct.use_ntfsprog) // if it's an NTFS device
1117// if (!strncmp ( biggiestruct.filename, "/dev/", 5))
1118 {
1119 g_loglevel = 4;
1120 use_ntfsprog_hack = TRUE;
1121 log_msg(2,
1122 "Calling ntfsclone in background because %s is an NTFS /dev entry",
1123 outfile_fname);
1124 sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
1125 (int) (random() % 32768));
1126 mkfifo(sz_devfile, 0x770);
1127 strcpy(ntfsprog_fifo, sz_devfile);
1128 file_to_openout = ntfsprog_fifo;
1129 switch (pid = fork()) {
1130 case -1:
1131 fatal_error("Fork failure");
1132 case 0:
1133 log_msg(3,
1134 "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1135 biggiestruct.filename, ntfsprog_fifo);
1136 res =
1137 feed_outfrom_ntfsprog(biggiestruct.filename,
1138 ntfsprog_fifo);
1139// log_msg(3, "CHILD - fip - exiting");
1140 exit(res);
1141 break;
1142 default:
1143 log_msg(3,
1144 "feed_into_ntfsprog() called in background --- pid=%ld",
1145 (long int) (pid));
1146 }
1147 } else {
1148 use_ntfsprog_hack = FALSE;
1149 ntfsprog_fifo[0] = '\0';
1150 file_to_openout = outfile_fname;
1151 if (!does_file_exist(outfile_fname)) // yes, it looks weird with the '!' but it's correct that way
1152 {
1153 make_hole_for_file(outfile_fname);
1154 }
1155 }
1156
1157 sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
1158 outfile_fname);
1159 log_msg(2, tmp);
1160
1161 /*
1162 last slice is zero-length and uncompressed; when we find it, we stop.
1163 We DON'T wait until there are no more slices; if we did that,
1164 We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1165 */
1166
1167 strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1168 MAX_STR_LEN - 1);
1169 pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1170
1171 log_msg(3, "file_to_openout = %s", file_to_openout);
1172 if (!(fout = fopen(file_to_openout, "w"))) {
1173 log_to_screen("Cannot openout outfile_fname - hard disk full?");
1174 return (1);
1175 }
1176 log_msg(3, "Opened out to %s", outfile_fname); // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1177
1178 for (sliceno = 1, finished = FALSE; !finished;) {
1179 if (!does_file_exist
1180 (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1181 &&
1182 !does_file_exist(slice_fname
1183 (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1184 &&
1185 !does_file_exist(slice_fname
1186 (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1187 &&
1188 !does_file_exist(slice_fname
1189 (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1190 log_msg(3,
1191 "Cannot find a data slice or terminator slice on CD %d",
1192 g_current_media_number);
1193 g_current_media_number++;
1194 sprintf(tmp,
1195 "Asking for %s #%d so that I may read slice #%ld\n",
1196 media_descriptor_string(bkpinfo->backup_media_type),
1197 g_current_media_number, sliceno);
1198 log_msg(2, tmp);
1199 sprintf(tmp, "Restoring from %s #%d",
1200 media_descriptor_string(bkpinfo->backup_media_type),
1201 g_current_media_number);
1202 log_to_screen(tmp);
1203 insist_on_this_cd_number(g_current_media_number);
1204 log_to_screen("Continuing to restore.");
1205 } else {
1206 strcpy(tmp,
1207 slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1208 if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1209 log_msg(2,
1210 "End of bigfile # %ld (slice %ld is the terminator)",
1211 bigfileno + 1, sliceno);
1212 finished = TRUE;
1213 continue;
1214 } else {
1215 if (does_file_exist
1216 (slice_fname
1217 (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1218 strcpy(bzip2_command, "lzop");
1219 strcpy(suffix, "lzo");
1220 } else
1221 if (does_file_exist
1222 (slice_fname
1223 (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1224 strcpy(bzip2_command, "gzip");
1225 strcpy(suffix, "gz");
1226 } else
1227 if (does_file_exist
1228 (slice_fname
1229 (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1230 strcpy(bzip2_command, "bzip2");
1231 strcpy(suffix, "bz2");
1232 } else
1233 if (does_file_exist
1234 (slice_fname
1235 (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1236 strcpy(bzip2_command, "");
1237 strcpy(suffix, "");
1238 } else {
1239 log_to_screen("OK, that's pretty fsck0red...");
1240 return (1);
1241 }
1242 }
1243 if (bzip2_command[0] != '\0') {
1244 sprintf(bzip2_command + strlen(bzip2_command),
1245 " -dc %s 2>> %s",
1246 slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1247 suffix), MONDO_LOGFILE);
1248 } else {
1249 sprintf(bzip2_command, "cat %s 2>> %s",
1250 slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1251 suffix), MONDO_LOGFILE);
1252 }
1253 sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld ",
1254 media_descriptor_string(bkpinfo->backup_media_type),
1255 g_current_media_number, bigfileno + 1, sliceno);
1256 log_msg(2, tmp);
1257
1258 if (!g_text_mode) {
1259 newtDrawRootText(0, g_noof_rows - 2, tmp);
1260 newtRefresh();
1261 strip_spaces(tmp);
1262 update_progress_form(tmp);
1263 }
1264 if (!(fbzip2 = popen(bzip2_command, "r"))) {
1265 fatal_error("Can't run popen command");
1266 }
1267 while (!feof(fbzip2)) {
1268 siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1269 if (siz > 0) {
1270 sprintf(sz_msg, "Read %ld from fbzip2", siz);
1271 siz = fwrite(bigblk, 1, siz, fout);
1272 sprintf(sz_msg + strlen(sz_msg),
1273 "; written %ld to fout", siz);
1274// log_msg(2. sz_msg);
1275 }
1276 }
1277 paranoid_pclose(fbzip2);
1278
1279
1280 sliceno++;
1281 g_current_progress++;
1282 }
1283 }
1284/*
1285 memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
1286 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1287 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1288 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1289 fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1290*/
1291 paranoid_fclose(fout);
1292 g_loglevel = old_loglevel;
1293
1294 if (use_ntfsprog_hack) {
1295 log_msg(3, "Waiting for ntfsclone to finish");
1296 sprintf(tmp,
1297 " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1298 while (system(tmp) == 0) {
1299 sleep(1);
1300 }
1301 log_it("OK, ntfsclone has really finished");
1302 }
1303
1304 if (strcmp(outfile_fname, "/dev/null")) {
1305 chown(outfile_fname, biggiestruct.properties.st_uid,
1306 biggiestruct.properties.st_gid);
1307 chmod(outfile_fname, biggiestruct.properties.st_mode);
1308 ubuf->actime = biggiestruct.properties.st_atime;
1309 ubuf->modtime = biggiestruct.properties.st_mtime;
1310 utime(outfile_fname, ubuf);
1311 }
1312 paranoid_free(bigblk);
1313 paranoid_free(checksum);
1314 paranoid_free(outfile_fname);
1315 paranoid_free(tmp);
1316 paranoid_free(bzip2_command);
1317 paranoid_free(ntfsprog_command);
1318 paranoid_free(suffix);
1319 paranoid_free(sz_devfile);
1320
1321 return (retval);
1322}
1323
1324/**************************************************************************
1325 *END_ RESTORE_A_BIGGIEFILE_FROM_CD *
1326 **************************************************************************/
1327
1328
1329
1330/**
1331 * Restore a biggiefile from the currently opened stream.
1332 * @param bkpinfo The backup information structure. Fields used:
1333 * - @c bkpinfo->restore_path
1334 * - @c bkpinfo->zip_exe
1335 * @param orig_bf_fname The original filename of the biggiefile.
1336 * @param biggiefile_number The number of the biggiefile (starting from 0).
1337 * @param orig_checksum Unused.
1338 * @param biggiefile_size Unused.
1339 * @param filelist The node structure containing the list of files to be restored.
1340 * If @p orig_bf_fname is not in the list, it will be ignored.
1341 * @return 0 for success (or skip), nonzero for failure.
1342 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
1343 */
1344int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum, //UNUSED
1345 long long biggiefile_size, //UNUSED
1346 struct s_node *filelist,
1347 int use_ntfsprog,
1348 char *pathname_of_last_file_restored)
1349{
1350 FILE *pout;
1351 FILE *fin;
1352
1353 /** mallocs ********/
1354 char *tmp;
1355 char *command;
1356 char *outfile_fname;
1357 char *ntfsprog_command;
1358 char *sz_devfile;
1359 char *ntfsprog_fifo;
1360 char *file_to_openout = NULL;
1361
1362 struct s_node *node;
1363
1364 int old_loglevel;
1365 long current_slice_number = 0;
1366 int retval = 0;
1367 int res = 0;
1368 int ctrl_chr = '\0';
1369 long long slice_siz;
1370 bool dummy_restore = FALSE;
1371 bool use_ntfsprog_hack = FALSE;
1372 pid_t pid;
1373 struct s_filename_and_lstat_info biggiestruct;
1374 struct utimbuf the_utime_buf, *ubuf;
1375 ubuf = &the_utime_buf;
1376
1377 malloc_string(tmp);
1378 malloc_string(ntfsprog_fifo);
1379 malloc_string(outfile_fname);
1380 malloc_string(command);
1381 malloc_string(sz_devfile);
1382 malloc_string(ntfsprog_command);
1383 old_loglevel = g_loglevel;
1384 assert(bkpinfo != NULL);
1385 assert(orig_bf_fname != NULL);
1386 assert(orig_checksum != NULL);
1387
1388 pathname_of_last_file_restored[0] = '\0';
1389 if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1390 use_ntfsprog = 1;
1391 log_msg(1, "%s --- pih=YES", orig_bf_fname);
1392 } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1393 use_ntfsprog = 0;
1394 log_msg(1, "%s --- pih=NO", orig_bf_fname);
1395 } else {
1396 use_ntfsprog = 0;
1397 log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1398 }
1399
1400 strncpy(pathname_of_last_file_restored, orig_bf_fname,
1401 MAX_STR_LEN - 1);
1402 pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1403
1404 /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1405
1406 if (filelist != NULL) {
1407 node = find_string_at_node(filelist, orig_bf_fname);
1408 if (!node) {
1409 dummy_restore = TRUE;
1410 log_msg(1,
1411 "Skipping big file %ld (%s) - not in biggielist subset",
1412 biggiefile_number + 1, orig_bf_fname);
1413 pathname_of_last_file_restored[0] = '\0';
1414 } else if (!(node->selected)) {
1415 dummy_restore = TRUE;
1416 log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1417 orig_bf_fname);
1418 pathname_of_last_file_restored[0] = '\0';
1419 }
1420 }
1421
1422 if (use_ntfsprog) {
1423 if (strncmp(orig_bf_fname, "/dev/", 5)) {
1424 log_msg(1,
1425 "I was in error when I set use_ntfsprog to TRUE.");
1426 log_msg(1, "%s isn't even in /dev", orig_bf_fname);
1427 use_ntfsprog = FALSE;
1428 }
1429 }
1430
1431 if (use_ntfsprog) {
1432 g_loglevel = 4;
1433 strcpy(outfile_fname, orig_bf_fname);
1434 use_ntfsprog_hack = TRUE;
1435 log_msg(2,
1436 "Calling ntfsclone in background because %s is a /dev entry",
1437 outfile_fname);
1438 sprintf(sz_devfile, "%s/%d.%d.000",
1439 bkpinfo->tmpdir,
1440 (int) (random() % 32768),
1441 (int) (random() % 32768));
1442 mkfifo(sz_devfile, 0x770);
1443 strcpy(ntfsprog_fifo, sz_devfile);
1444 file_to_openout = ntfsprog_fifo;
1445 switch (pid = fork()) {
1446 case -1:
1447 fatal_error("Fork failure");
1448 case 0:
1449 log_msg(3,
1450 "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1451 outfile_fname, ntfsprog_fifo);
1452 res =
1453 feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1454// log_msg(3, "CHILD - fip - exiting");
1455 exit(res);
1456 break;
1457 default:
1458 log_msg(3,
1459 "feed_into_ntfsprog() called in background --- pid=%ld",
1460 (long int) (pid));
1461 }
1462 } else {
1463 if (!strncmp(orig_bf_fname, "/dev/", 5)) // non-NTFS partition
1464 {
1465 strcpy(outfile_fname, orig_bf_fname);
1466 } else // biggiefile
1467 {
1468 sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1469 orig_bf_fname);
1470 }
1471 use_ntfsprog_hack = FALSE;
1472 ntfsprog_fifo[0] = '\0';
1473 file_to_openout = outfile_fname;
1474 if (!does_file_exist(outfile_fname)) // yes, it looks weird with the '!' but it's correct that way
1475 {
1476 make_hole_for_file(outfile_fname);
1477 }
1478 sprintf(tmp, "Reassembling big file %ld (%s)",
1479 biggiefile_number + 1, orig_bf_fname);
1480 log_msg(2, tmp);
1481 }
1482
1483 if (dummy_restore) {
1484 sprintf(outfile_fname, "/dev/null");
1485 }
1486
1487 if (!bkpinfo->zip_exe[0]) {
1488 sprintf(command, "cat > \"%s\"", file_to_openout);
1489 } else {
1490 sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1491 file_to_openout, MONDO_LOGFILE);
1492 }
1493 sprintf(tmp, "Pipe command = '%s'", command);
1494 log_msg(3, tmp);
1495
1496 /* restore biggiefile, one slice at a time */
1497 if (!(pout = popen(command, "w"))) {
1498 fatal_error("Cannot pipe out");
1499 }
1500 for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1501 ctrl_chr != BLK_STOP_A_BIGGIE;
1502 res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
1503 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1504 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1505 }
1506 sprintf(tmp, "Working on file #%ld, slice #%ld ",
1507 biggiefile_number + 1, current_slice_number);
1508 log_msg(2, tmp);
1509 if (!g_text_mode) {
1510 newtDrawRootText(0, g_noof_rows - 2, tmp);
1511 newtRefresh();
1512 }
1513 strip_spaces(tmp);
1514 update_progress_form(tmp);
1515 if (current_slice_number == 0) {
1516 res =
1517 read_file_from_stream_to_file("/tmp/biggie-blah.txt",
1518 slice_siz);
1519 if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1520 log_OS_error("blah blah");
1521 } else {
1522 if (fread
1523 ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1524 fin) < sizeof(biggiestruct)) {
1525 log_msg(2,
1526 "Warning - unable to get biggiestruct of bigfile #%d",
1527 biggiefile_number + 1);
1528 }
1529 paranoid_fclose(fin);
1530 }
1531 } else {
1532 res =
1533 read_file_from_stream_to_stream(pout, slice_siz);
1534 }
1535 retval += res;
1536 res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1537 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1538 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1539 }
1540 current_slice_number++;
1541 g_current_progress++;
1542 }
1543 paranoid_pclose(pout);
1544
1545 log_msg(1, "pathname_of_last_file_restored is now %s",
1546 pathname_of_last_file_restored);
1547
1548 if (use_ntfsprog_hack) {
1549 log_msg(3, "Waiting for ntfsclone to finish");
1550 sprintf(tmp,
1551 " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1552 while (system(tmp) == 0) {
1553 sleep(1);
1554 }
1555 log_msg(3, "OK, ntfsclone has really finished");
1556 }
1557
1558 log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1559 log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1560 if (strcmp(outfile_fname, "/dev/null")) {
1561 chmod(outfile_fname, biggiestruct.properties.st_mode);
1562 chown(outfile_fname, biggiestruct.properties.st_uid,
1563 biggiestruct.properties.st_gid);
1564 ubuf->actime = biggiestruct.properties.st_atime;
1565 ubuf->modtime = biggiestruct.properties.st_mtime;
1566 utime(outfile_fname, ubuf);
1567 }
1568
1569 paranoid_free(tmp);
1570 paranoid_free(outfile_fname);
1571 paranoid_free(command);
1572 paranoid_free(ntfsprog_command);
1573 paranoid_free(sz_devfile);
1574 paranoid_free(ntfsprog_fifo);
1575 g_loglevel = old_loglevel;
1576 return (retval);
1577}
1578
1579/**************************************************************************
1580 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM *
1581 **************************************************************************/
1582
1583
1584
1585/**
1586 * Restore @p tarball_fname from CD.
1587 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1588 * This will be used unmodified.
1589 * @param current_tarball_number The number (starting from 0) of the fileset
1590 * we're restoring now.
1591 * @param filelist The node structure containing the list of files to be
1592 * restored. If no file in the afioball is in this list, afio will still be
1593 * called, but nothing will be written.
1594 * @return 0 for success, nonzero for failure.
1595 */
1596int
1597restore_a_tarball_from_CD(char *tarball_fname,
1598 long current_tarball_number,
1599 struct s_node *filelist)
1600{
1601 int retval = 0;
1602 int res;
1603 char *p;
1604
1605 /** malloc **/
1606 char *command;
1607 char *tmp;
1608 char *filelist_name;
1609 char *filelist_subset_fname;
1610 char *executable;
1611 char *temp_log;
1612 char screen_message[100];
1613 long matches = 0;
1614 bool use_star;
1615 char *xattr_fname;
1616 char *acl_fname;
1617// char files_to_restore_this_time_fname[MAX_STR_LEN];
1618
1619 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1620 malloc_string(command);
1621 malloc_string(tmp);
1622 malloc_string(filelist_name);
1623 malloc_string(filelist_subset_fname);
1624 malloc_string(executable);
1625 malloc_string(temp_log);
1626 malloc_string(xattr_fname);
1627 malloc_string(acl_fname);
1628
1629 log_msg(5, "Entering");
1630 filelist_subset_fname[0] = '\0';
1631 use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1632// sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
1633 sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
1634 run_program_and_log_output(command, 9);
1635 sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1636 (int) (random() % 32768));
1637
1638 sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
1639 current_tarball_number);
1640 if (length_of_file(filelist_name) <= 2) {
1641 log_msg(2, "There are _zero_ files in filelist '%s'",
1642 filelist_name);
1643 log_msg(2,
1644 "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1645 log_msg(2,
1646 "but it's non-critical. It's cosmetic. Don't worry about it.");
1647 retval = 0;
1648 goto leave_sub;
1649 }
1650 if (count_lines_in_file(filelist_name) <= 0
1651 || length_of_file(tarball_fname) <= 0) {
1652 log_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1653 length_of_file(tarball_fname));
1654 sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
1655 current_tarball_number);
1656 log_to_screen(tmp);
1657 retval = 1;
1658 goto leave_sub;
1659 }
1660
1661 if (filelist) {
1662 sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1663 current_tarball_number);
1664 if ((matches =
1665 save_filelist_entries_in_common(filelist_name, filelist,
1666 filelist_subset_fname,
1667 use_star))
1668 <= 0) {
1669 sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1670 log_msg(1, tmp);
1671 } else {
1672 log_msg(3, "Saved fileset %ld's subset to %s",
1673 current_tarball_number, filelist_subset_fname);
1674 }
1675 sprintf(screen_message, "Tarball #%ld --- %ld matches",
1676 current_tarball_number, matches);
1677 log_to_screen(screen_message);
1678 } else {
1679 filelist_subset_fname[0] = '\0';
1680 }
1681
1682 if (filelist == NULL || matches > 0) {
1683 if (g_getfattr) {
1684 sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1685 MNT_CDROM "/archives", current_tarball_number);
1686 }
1687 if (g_getfacl) {
1688 sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1689 current_tarball_number);
1690 }
1691 if (strstr(tarball_fname, ".bz2")) {
1692 strcpy(executable, "bzip2");
1693 } else if (strstr(tarball_fname, ".gz")) {
1694 strcpy(executable, "gzip");
1695 } else if (strstr(tarball_fname, ".lzo")) {
1696 strcpy(executable, "lzop");
1697 } else {
1698 executable[0] = '\0';
1699 }
1700 if (executable[0]) {
1701 sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
1702 if (run_program_and_log_output(tmp, FALSE)) {
1703 log_to_screen
1704 ("(compare_a_tarball) Compression program not found - oh no!");
1705 paranoid_MR_finish(1);
1706 }
1707 strcpy(tmp, executable);
1708 sprintf(executable, "-P %s -Z", tmp);
1709 }
1710#ifdef __FreeBSD__
1711#define BUFSIZE 512
1712#else
1713#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1714#endif
1715
1716// if (strstr(tarball_fname, ".star."))
1717 if (use_star) {
1718 sprintf(command,
1719 "star -x -force-remove -U " STAR_ACL_SZ
1720 " errctl= file=%s", tarball_fname);
1721 if (strstr(tarball_fname, ".bz2")) {
1722 strcat(command, " -bz");
1723 }
1724 } else {
1725 if (filelist_subset_fname[0] != '\0') {
1726 sprintf(command,
1727 "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1728 TAPE_BLOCK_SIZE,
1729 BUFSIZE, executable, filelist_subset_fname,
1730// files_to_restore_this_time_fname,
1731 tarball_fname);
1732 } else {
1733 sprintf(command,
1734 "afio -i -b %ld -c %ld -M 8m %s %s",
1735 TAPE_BLOCK_SIZE,
1736 BUFSIZE, executable, tarball_fname);
1737 }
1738 }
1739#undef BUFSIZE
1740 sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
1741 temp_log);
1742 log_msg(1, "command = '%s'", command);
1743 unlink(temp_log);
1744 res = system(command);
1745 if (res) {
1746 p = strstr(command, "-acl ");
1747 if (p) {
1748 p[0] = p[1] = p[2] = p[3] = ' ';
1749 log_msg(1, "new command = '%s'", command);
1750 res = system(command);
1751 }
1752 }
1753 if (res && length_of_file(temp_log) < 5) {
1754 res = 0;
1755 }
1756
1757 if (g_getfattr) {
1758 log_msg(1, "Setting fattr list %s", xattr_fname);
1759 if (length_of_file(xattr_fname) > 0) {
1760 res = set_fattr_list(filelist_subset_fname, xattr_fname);
1761 if (res) {
1762 log_to_screen
1763 ("Errors occurred while setting extended attributes");
1764 } else {
1765 log_msg(1, "I set xattr OK");
1766 }
1767 retval += res;
1768 }
1769 }
1770 if (g_getfacl) {
1771 log_msg(1, "Setting acl list %s", acl_fname);
1772 if (length_of_file(acl_fname) > 0) {
1773 res = set_acl_list(filelist_subset_fname, acl_fname);
1774 if (res) {
1775 log_to_screen
1776 ("Errors occurred while setting access control lists");
1777 } else {
1778 log_msg(1, "I set ACL OK");
1779 }
1780 retval += res;
1781 }
1782 }
1783 if (retval) {
1784 sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1785 system(command);
1786 log_msg(2, "Errors occurred while processing fileset #%d",
1787 current_tarball_number);
1788 } else {
1789 log_msg(2, "Fileset #%d processed OK", current_tarball_number);
1790 }
1791 }
1792 if (does_file_exist("/PAUSE")) {
1793 popup_and_OK
1794 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
1795 }
1796 unlink(filelist_subset_fname);
1797 unlink(xattr_fname);
1798 unlink(acl_fname);
1799 unlink(temp_log);
1800
1801 leave_sub:
1802 paranoid_free(command);
1803 paranoid_free(tmp);
1804 paranoid_free(filelist_name);
1805 paranoid_free(filelist_subset_fname);
1806 paranoid_free(executable);
1807 paranoid_free(temp_log);
1808 paranoid_free(xattr_fname);
1809 paranoid_free(acl_fname);
1810 log_msg(5, "Leaving");
1811 return (retval);
1812}
1813
1814/**************************************************************************
1815 *END_RESTORE_A_TARBALL_FROM_CD *
1816 **************************************************************************/
1817
1818
1819/**
1820 * Restore a tarball from the currently opened stream.
1821 * @param bkpinfo The backup information structure. Fields used:
1822 * - @c bkpinfo->backup_media_type
1823 * - @c bkpinfo->media_device
1824 * - @c bkpinfo->zip_exe
1825 * @param tarball_fname The filename of the afioball to restore.
1826 * @param current_tarball_number The number (starting from 0) of the fileset
1827 * we're restoring now.
1828 * @param filelist The node structure containing the list of files to be
1829 * restored. If no file in the afioball is in this list, afio will still be
1830 * called, but nothing will be written.
1831 * @param size The size (in @b bytes) of the afioball.
1832 * @return 0 for success, nonzero for failure.
1833 */
1834int
1835restore_a_tarball_from_stream(char *tarball_fname,
1836 long current_tarball_number,
1837 struct s_node *filelist,
1838 long long size, char *xattr_fname,
1839 char *acl_fname)
1840{
1841 int retval = 0;
1842 int res = 0;
1843
1844 /** malloc add ***/
1845 char *tmp;
1846 char *command;
1847 char *afio_fname;
1848 char *filelist_fname;
1849 char *filelist_subset_fname;
1850 char *executable;
1851 long matches = 0;
1852 bool restore_this_fileset = FALSE;
1853 bool use_star;
1854
1855 assert(bkpinfo != NULL);
1856 assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1857 malloc_string(filelist_subset_fname);
1858 malloc_string(filelist_fname);
1859 malloc_string(afio_fname);
1860 malloc_string(executable);
1861 malloc_string(command);
1862 malloc_string(tmp);
1863 filelist_subset_fname[0] = '\0';
1864 /* to do it with a file... */
1865 use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1866 sprintf(tmp,
1867 "Restoring from fileset #%ld (%ld KB) on %s #%d",
1868 current_tarball_number, (long) size >> 10,
1869 media_descriptor_string(bkpinfo->backup_media_type),
1870 g_current_media_number);
1871 log_msg(2, tmp);
1872 run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1873
1874 /****************************************************************************
1875 * Use RAMDISK's /tmp; saves time; oh wait, it's too small *
1876 * Well, pipe from tape to afio, then; oh wait, can't do that either: bug *
1877 * in afio or someting; oh darn.. OK, use tmpfs :-) *
1878 ****************************************************************************/
1879 filelist_fname[0] = filelist_subset_fname[0] = '\0';
1880 sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1881 current_tarball_number);
1882 sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1883 current_tarball_number);
1884 sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1885 bkpinfo->tmpdir, current_tarball_number);
1886// sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
1887 res = read_file_from_stream_to_file(afio_fname, size);
1888 if (strstr(tarball_fname, ".star")) {
1889 bkpinfo->use_star = TRUE;
1890 }
1891 if (res) {
1892 log_msg(1, "Warning - error reading afioball from tape");
1893 }
1894 if (bkpinfo->compression_level == 0) {
1895 executable[0] = '\0';
1896 } else {
1897 if (bkpinfo->use_star) {
1898 strcpy(executable, " -bz");
1899 } else {
1900 sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
1901 }
1902 }
1903
1904 if (!filelist) // if unconditional restore then restore entire fileset
1905 {
1906 restore_this_fileset = TRUE;
1907 } else // If restoring selectively then get TOC from tarball
1908 {
1909 if (strstr(tarball_fname, ".star.")) {
1910 use_star = TRUE;
1911 sprintf(command, "star -t file=%s %s", afio_fname, executable);
1912 } else {
1913 use_star = FALSE;
1914 sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1915 executable, afio_fname);
1916 }
1917 sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
1918 MONDO_LOGFILE);
1919 log_msg(1, "command = %s", command);
1920 if (system(command)) {
1921 log_msg(4, "Warning - error occurred while retrieving TOC");
1922 }
1923 if ((matches =
1924 save_filelist_entries_in_common(filelist_fname, filelist,
1925 filelist_subset_fname,
1926 use_star))
1927 <= 0 || length_of_file(filelist_subset_fname) < 2) {
1928 if (length_of_file(filelist_subset_fname) < 2) {
1929 log_msg(1, "No matches found in fileset %ld",
1930 current_tarball_number);
1931 }
1932 sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1933 log_msg(2, tmp);
1934 restore_this_fileset = FALSE;
1935 } else {
1936 log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1937 matches, current_tarball_number,
1938 filelist_subset_fname);
1939 restore_this_fileset = TRUE;
1940 }
1941 }
1942
1943// Concoct the call to star/afio to restore files
1944 if (strstr(tarball_fname, ".star.")) // star
1945 {
1946 sprintf(command, "star -x file=%s %s", afio_fname, executable);
1947 if (filelist) {
1948 sprintf(command + strlen(command), " list=%s",
1949 filelist_subset_fname);
1950 }
1951 } else // afio
1952 {
1953 sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
1954 executable);
1955 if (filelist) {
1956 sprintf(command + strlen(command), " -w %s",
1957 filelist_subset_fname);
1958 }
1959 sprintf(command + strlen(command), " %s", afio_fname);
1960 }
1961 sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
1962
1963// Call if IF there are files to restore (selectively/unconditionally)
1964 if (restore_this_fileset) {
1965 log_msg(1, "Calling command='%s'", command);
1966 paranoid_system(command);
1967
1968 if (g_getfattr) {
1969 iamhere("Restoring xattr stuff");
1970 res = set_fattr_list(filelist_subset_fname, xattr_fname);
1971 if (res) {
1972 log_msg(1, "Errors occurred while setting xattr");
1973 } else {
1974 log_msg(1, "I set xattr OK");
1975 }
1976 retval += res;
1977 }
1978
1979 if (g_getfacl) {
1980 iamhere("Restoring acl stuff");
1981 res = set_acl_list(filelist_subset_fname, acl_fname);
1982 if (res) {
1983 log_msg(1, "Errors occurred while setting ACL");
1984 } else {
1985 log_msg(1, "I set ACL OK");
1986 }
1987 retval += res;
1988 }
1989
1990 } else {
1991 log_msg(1, "NOT CALLING '%s'", command);
1992 }
1993
1994 if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1995 log_to_screen("Paused after set %ld", current_tarball_number);
1996 popup_and_OK("Pausing. Press ENTER to continue.");
1997 }
1998
1999 unlink(filelist_subset_fname);
2000 unlink(filelist_fname);
2001 unlink(afio_fname);
2002
2003 paranoid_free(filelist_subset_fname);
2004 paranoid_free(filelist_fname);
2005 paranoid_free(afio_fname);
2006 paranoid_free(command);
2007 paranoid_free(tmp);
2008 return (retval);
2009}
2010
2011/**************************************************************************
2012 *END_RESTORE_A_TARBALL_FROM_STREAM *
2013 **************************************************************************/
2014
2015
2016
2017
2018/**
2019 * Restore all biggiefiles from all media in this CD backup.
2020 * The CD with the last afioball should be currently mounted.
2021 * @param bkpinfo The backup information structure. @c backup_media_type is the
2022 * only field used in this function.
2023 * @param filelist The node structure containing the list of files to be
2024 * restored. If a prospective biggiefile is not in this list, it will be ignored.
2025 * @return 0 for success, nonzero for failure.
2026 */
2027int
2028restore_all_biggiefiles_from_CD(struct s_node *filelist)
2029{
2030 int retval = 0;
2031 int res = 0;
2032 long noof_biggiefiles, bigfileno = 0, total_slices;
2033 /** malloc **/
2034 char *tmp;
2035 bool just_changed_cds = FALSE;
2036 char *xattr_fname;
2037 char *acl_fname;
2038 char *biggies_whose_EXATs_we_should_set; // EXtended ATtributes
2039 char *pathname_of_last_biggie_restored;
2040 FILE *fbw = NULL;
2041
2042 malloc_string(xattr_fname);
2043 malloc_string(acl_fname);
2044 malloc_string(tmp);
2045 malloc_string(biggies_whose_EXATs_we_should_set);
2046 malloc_string(pathname_of_last_biggie_restored);
2047 assert(bkpinfo != NULL);
2048
2049 sprintf(biggies_whose_EXATs_we_should_set,
2050 "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2051 if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2052 log_msg(1, "Warning - cannot openout %s",
2053 biggies_whose_EXATs_we_should_set);
2054 }
2055
2056 read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2057 total_slices = atol(tmp);
2058 sprintf(tmp, "Reassembling large files ");
2059 mvaddstr_and_log_it(g_currentY, 0, tmp);
2060 if (length_of_file(BIGGIELIST) < 6) {
2061 log_msg(1, "OK, no biggielist; not restoring biggiefiles");
2062 return (0);
2063 }
2064 noof_biggiefiles = count_lines_in_file(BIGGIELIST);
2065 if (noof_biggiefiles <= 0) {
2066 log_msg(2,
2067 "OK, no biggiefiles in biggielist; not restoring biggiefiles");
2068 return (0);
2069 }
2070 sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2071 noof_biggiefiles);
2072 log_msg(2, tmp);
2073
2074 open_progress_form("Reassembling large files",
2075 "I am now reassembling all the large files.",
2076 "Please wait. This may take some time.",
2077 "", total_slices);
2078 for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
2079 log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
2080 if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
2081 log_msg(3,
2082 "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
2083 log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
2084 bigfileno + 1,
2085 media_descriptor_string(bkpinfo->backup_media_type),
2086 g_current_media_number);
2087 log_msg(3, "Slicename would have been %s",
2088 slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
2089 // I'm not positive 'just_changed_cds' is even necessary...
2090 if (just_changed_cds) {
2091 just_changed_cds = FALSE;
2092 log_msg(3,
2093 "I'll continue to scan this CD for bigfiles to be restored.");
2094 } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2095 insist_on_this_cd_number(++g_current_media_number);
2096 sprintf(tmp, "Restoring from %s #%d",
2097 media_descriptor_string(bkpinfo->backup_media_type),
2098 g_current_media_number);
2099 log_to_screen(tmp);
2100 just_changed_cds = TRUE;
2101 } else {
2102 /* That big file doesn't exist, but the followings may */
2103 /* So we need to continue looping */
2104 log_msg(2, "There was no bigfile #%ld. That's OK.",
2105 bigfileno + 1);
2106 log_msg(2, "I'm going to stop restoring bigfiles now.");
2107 retval++;
2108 bigfileno++;
2109 }
2110 } else {
2111 just_changed_cds = FALSE;
2112 sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
2113 update_progress_form(tmp);
2114 res =
2115 restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
2116 iamhere(pathname_of_last_biggie_restored);
2117 if (fbw && pathname_of_last_biggie_restored[0]) {
2118 fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2119 }
2120 retval += res;
2121 bigfileno++;
2122
2123 }
2124 }
2125
2126 if (fbw) {
2127 fclose(fbw);
2128 if (g_getfattr) {
2129 sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2130 if (length_of_file(xattr_fname) > 0) {
2131 set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2132 }
2133 }
2134 if (g_getfacl) {
2135 sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2136 if (length_of_file(acl_fname) > 0) {
2137 set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2138 }
2139 }
2140 }
2141 if (does_file_exist("/PAUSE")) {
2142 popup_and_OK
2143 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2144 }
2145 close_progress_form();
2146 if (retval) {
2147 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2148 } else {
2149 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2150 }
2151 paranoid_free(xattr_fname);
2152 paranoid_free(acl_fname);
2153 paranoid_free(tmp);
2154 paranoid_free(biggies_whose_EXATs_we_should_set);
2155 paranoid_free(pathname_of_last_biggie_restored);
2156 return (retval);
2157}
2158
2159/**************************************************************************
2160 *END_RESTORE_ALL_BIGGIFILES_FROM_CD *
2161 **************************************************************************/
2162
2163
2164
2165/**
2166 * Restore all afioballs from all CDs in the backup.
2167 * The first CD should be inserted (if not, it will be asked for).
2168 * @param bkpinfo The backup information structure. @c backup_media_type is the
2169 * only field used in @e this function.
2170 * @param filelist The node structure containing the list of files to be
2171 * restored. If no file in some particular afioball is in this list, afio will
2172 * still be called for that fileset, but nothing will be written.
2173 * @return 0 for success, or the number of filesets that failed.
2174 */
2175int
2176restore_all_tarballs_from_CD(struct s_node *filelist)
2177{
2178 int retval = 0;
2179 int res;
2180 int attempts;
2181 long current_tarball_number = 0;
2182 long max_val;
2183 /**malloc ***/
2184 char *tmp;
2185 char *tarball_fname;
2186 char *progress_str;
2187 char *comment;
2188
2189 malloc_string(tmp);
2190 malloc_string(tarball_fname);
2191 malloc_string(progress_str);
2192 malloc_string(comment);
2193
2194 assert(bkpinfo != NULL);
2195
2196 mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2197 log_msg(2,
2198 "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2199 if (g_current_media_number != 1) {
2200 log_msg(3, "OK, that's jacked up.");
2201 g_current_media_number = 1;
2202 }
2203 insist_on_this_cd_number(g_current_media_number);
2204 read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2205 max_val = atol(tmp) + 1;
2206 sprintf(progress_str, "Restoring from %s #%d",
2207 media_descriptor_string(bkpinfo->backup_media_type),
2208 g_current_media_number);
2209 log_to_screen(progress_str);
2210 open_progress_form("Restoring from archives",
2211 "Restoring data from the archives.",
2212 "Please wait. This may take some time.",
2213 progress_str, max_val);
2214 for (;;) {
2215 insist_on_this_cd_number(g_current_media_number);
2216 update_progress_form(progress_str);
2217 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2218 current_tarball_number);
2219 if (!does_file_exist(tarball_fname)) {
2220 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2221 current_tarball_number);
2222 }
2223 if (!does_file_exist(tarball_fname)) {
2224 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2225 current_tarball_number);
2226 }
2227 if (!does_file_exist(tarball_fname)) {
2228 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2229 current_tarball_number);
2230 }
2231 if (!does_file_exist(tarball_fname)) {
2232 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2233 current_tarball_number);
2234 }
2235 if (!does_file_exist(tarball_fname)) {
2236 sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
2237 current_tarball_number);
2238 }
2239 if (!does_file_exist(tarball_fname)) {
2240 if (current_tarball_number == 0) {
2241 log_to_screen
2242 ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
2243 return (0);
2244 }
2245 if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2246 || system("find " MNT_CDROM
2247 "/archives/slice* > /dev/null 2> /dev/null") ==
2248 0) {
2249 break;
2250 }
2251 g_current_media_number++;
2252 sprintf(progress_str, "Restoring from %s #%d",
2253 media_descriptor_string(bkpinfo->backup_media_type),
2254 g_current_media_number);
2255 log_to_screen(progress_str);
2256 } else {
2257 sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2258 current_tarball_number,
2259 media_descriptor_string(bkpinfo->backup_media_type),
2260 g_current_media_number);
2261// log_msg(3, "progress_str = %s", progress_str);
2262 for (res = 999, attempts = 0; attempts < 3 && res != 0;
2263 attempts++) {
2264 res =
2265 restore_a_tarball_from_CD(tarball_fname,
2266 current_tarball_number,
2267 filelist);
2268 }
2269 sprintf(tmp, "%s #%d, fileset #%ld - restore ",
2270 media_descriptor_string(bkpinfo->backup_media_type),
2271 g_current_media_number, current_tarball_number);
2272 if (res) {
2273 strcat(tmp, "reported errors");
2274 } else if (attempts > 1) {
2275 strcat(tmp, "succeeded");
2276 } else {
2277 strcat(tmp, "succeeded");
2278 }
2279 if (attempts > 1) {
2280 sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
2281 attempts);
2282 }
2283 strcpy(comment, tmp);
2284 if (attempts > 1) {
2285 log_to_screen(comment);
2286 }
2287
2288 retval += res;
2289 current_tarball_number++;
2290 g_current_progress++;
2291 }
2292 }
2293 close_progress_form();
2294 if (retval) {
2295 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2296 } else {
2297 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2298 }
2299 paranoid_free(tmp);
2300 paranoid_free(tarball_fname);
2301 paranoid_free(progress_str);
2302 paranoid_free(comment);
2303
2304 return (retval);
2305}
2306
2307/**************************************************************************
2308 *END_RESTORE_ALL_TARBALLS_FROM_CD *
2309 **************************************************************************/
2310
2311
2312
2313/**
2314 * Restore all biggiefiles from the currently opened stream.
2315 * @param bkpinfo The backup information structure. Passed to other functions.
2316 * @param filelist The node structure containing the list of files to be
2317 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2318 * @return 0 for success, or the number of biggiefiles that failed.
2319 */
2320int
2321restore_all_biggiefiles_from_stream(struct s_node *filelist)
2322{
2323 long noof_biggiefiles;
2324 long current_bigfile_number = 0;
2325 long total_slices;
2326
2327 int retval = 0;
2328 int res = 0;
2329 int ctrl_chr;
2330
2331 /** malloc add ****/
2332 char *tmp;
2333 char *biggie_fname;
2334 char *biggie_cksum;
2335 char *xattr_fname;
2336 char *acl_fname;
2337 char *p;
2338 char *pathname_of_last_biggie_restored;
2339 char *biggies_whose_EXATs_we_should_set; // EXtended ATtributes
2340 long long biggie_size;
2341 FILE *fbw = NULL;
2342
2343 malloc_string(tmp);
2344 malloc_string(biggie_fname);
2345 malloc_string(biggie_cksum);
2346 malloc_string(xattr_fname);
2347 malloc_string(acl_fname);
2348 malloc_string(biggies_whose_EXATs_we_should_set);
2349 malloc_string(pathname_of_last_biggie_restored);
2350 assert(bkpinfo != NULL);
2351
2352 read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2353
2354 total_slices = atol(tmp);
2355 sprintf(tmp, "Reassembling large files ");
2356 if (g_getfattr) {
2357 sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2358 }
2359 if (g_getfacl) {
2360 sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2361 }
2362 mvaddstr_and_log_it(g_currentY, 0, tmp);
2363 sprintf(biggies_whose_EXATs_we_should_set,
2364 "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2365 if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2366 log_msg(1, "Warning - cannot openout %s",
2367 biggies_whose_EXATs_we_should_set);
2368 }
2369// get xattr and acl files if they're there
2370 res =
2371 read_header_block_from_stream(&biggie_size, biggie_fname,
2372 &ctrl_chr);
2373 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2374 res =
2375 read_EXAT_files_from_tape(&biggie_size, biggie_fname,
2376 &ctrl_chr, xattr_fname, acl_fname);
2377 }
2378
2379 noof_biggiefiles = atol(biggie_fname);
2380 sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2381 noof_biggiefiles);
2382 log_msg(2, tmp);
2383 open_progress_form("Reassembling large files",
2384 "I am now reassembling all the large files.",
2385 "Please wait. This may take some time.",
2386 "", total_slices);
2387
2388 for (res =
2389 read_header_block_from_stream(&biggie_size, biggie_fname,
2390 &ctrl_chr);
2391 ctrl_chr != BLK_STOP_BIGGIEFILES;
2392 res =
2393 read_header_block_from_stream(&biggie_size, biggie_fname,
2394 &ctrl_chr)) {
2395 if (ctrl_chr != BLK_START_A_NORMBIGGIE
2396 && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2397 wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2398 }
2399 p = strrchr(biggie_fname, '/');
2400 if (!p) {
2401 p = biggie_fname;
2402 } else {
2403 p++;
2404 }
2405 sprintf(tmp, "Restoring big file %ld (%lld K)",
2406 current_bigfile_number + 1, biggie_size / 1024);
2407 update_progress_form(tmp);
2408 res = restore_a_biggiefile_from_stream(biggie_fname,
2409 current_bigfile_number,
2410 biggie_cksum,
2411 biggie_size,
2412 filelist, ctrl_chr,
2413 pathname_of_last_biggie_restored);
2414 log_msg(1, "I believe I have restored %s",
2415 pathname_of_last_biggie_restored);
2416 if (fbw && pathname_of_last_biggie_restored[0]) {
2417 fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2418 }
2419 retval += res;
2420 current_bigfile_number++;
2421
2422 }
2423 if (current_bigfile_number != noof_biggiefiles
2424 && noof_biggiefiles != 0) {
2425 sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2426 current_bigfile_number, noof_biggiefiles);
2427 } else {
2428 sprintf(tmp,
2429 "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2430 noof_biggiefiles, current_bigfile_number);
2431 }
2432 log_msg(1, tmp);
2433
2434 if (fbw) {
2435 fclose(fbw);
2436 if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2437 iamhere("Setting biggie-EXATs");
2438 if (g_getfattr) {
2439 if (length_of_file(xattr_fname) > 0) {
2440 log_msg(1, "set_fattr_List(%s,%s)",
2441 biggies_whose_EXATs_we_should_set, xattr_fname);
2442 set_fattr_list(biggies_whose_EXATs_we_should_set,
2443 xattr_fname);
2444 }
2445 }
2446 if (g_getfacl) {
2447 if (length_of_file(acl_fname) > 0) {
2448 log_msg(1, "set_acl_list(%s,%s)",
2449 biggies_whose_EXATs_we_should_set, acl_fname);
2450 set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2451 }
2452 }
2453 } else {
2454 iamhere
2455 ("No biggiefiles selected. So, no biggie-EXATs to set.");
2456 }
2457 }
2458 if (does_file_exist("/PAUSE")) {
2459 popup_and_OK
2460 ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2461 }
2462
2463 close_progress_form();
2464 if (retval) {
2465 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2466 } else {
2467 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2468 }
2469 paranoid_free(biggies_whose_EXATs_we_should_set);
2470 paranoid_free(pathname_of_last_biggie_restored);
2471 paranoid_free(biggie_fname);
2472 paranoid_free(biggie_cksum);
2473 paranoid_free(xattr_fname);
2474 paranoid_free(acl_fname);
2475 paranoid_free(tmp);
2476 return (retval);
2477}
2478
2479/**************************************************************************
2480 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM *
2481 **************************************************************************/
2482
2483
2484
2485
2486
2487
2488/**
2489 * Restore all afioballs from the currently opened tape stream.
2490 * @param bkpinfo The backup information structure. Fields used:
2491 * - @c bkpinfo->backup_media_type
2492 * - @c bkpinfo->restore_path
2493 * @param filelist The node structure containing the list of files to be
2494 * restored. If no file in an afioball is in this list, afio will still be
2495 * called for that fileset, but nothing will be written.
2496 * @return 0 for success, or the number of filesets that failed.
2497 */
2498int
2499restore_all_tarballs_from_stream(struct s_node *filelist)
2500{
2501 int retval = 0;
2502 int res;
2503 long current_afioball_number = 0;
2504 int ctrl_chr;
2505 long max_val /*, total_noof_files */ ;
2506
2507 /** malloc **/
2508 char *tmp;
2509 char *progress_str;
2510 char *tmp_fname;
2511 char *xattr_fname;
2512 char *acl_fname;
2513
2514 long long tmp_size;
2515
2516 malloc_string(tmp);
2517 malloc_string(progress_str);
2518 malloc_string(tmp_fname);
2519 assert(bkpinfo != NULL);
2520 malloc_string(xattr_fname);
2521 malloc_string(acl_fname);
2522 mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2523 read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2524 max_val = atol(tmp) + 1;
2525
2526 chdir(bkpinfo->restore_path); /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2527
2528 run_program_and_log_output("pwd", 5);
2529
2530 sprintf(progress_str, "Restoring from media #%d",
2531 g_current_media_number);
2532 log_to_screen(progress_str);
2533 open_progress_form("Restoring from archives",
2534 "Restoring data from the archives.",
2535 "Please wait. This may take some time.",
2536 progress_str, max_val);
2537
2538 log_msg(3, "hey");
2539
2540 res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2541 if (res) {
2542 log_msg(2, "Warning - error reading afioball from tape");
2543 }
2544 retval += res;
2545 if (ctrl_chr != BLK_START_AFIOBALLS) {
2546 wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2547 }
2548 log_msg(2, "ho");
2549 res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2550 while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2551 update_progress_form(progress_str);
2552 if (g_getfattr) {
2553 sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2554 current_afioball_number);
2555 unlink(xattr_fname);
2556 }
2557 if (g_getfacl) {
2558 sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2559 current_afioball_number);
2560 unlink(acl_fname);
2561 }
2562 if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2563 iamhere("Reading EXAT files from tape");
2564 res =
2565 read_EXAT_files_from_tape(&tmp_size, tmp_fname,
2566 &ctrl_chr, xattr_fname,
2567 acl_fname);
2568 }
2569 if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2570 wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2571 }
2572 sprintf(tmp,
2573 "Restoring from fileset #%ld (name=%s, size=%ld K)",
2574 current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2575 res =
2576 restore_a_tarball_from_stream(tmp_fname,
2577 current_afioball_number,
2578 filelist, tmp_size, xattr_fname,
2579 acl_fname);
2580 retval += res;
2581 if (res) {
2582 sprintf(tmp, "Fileset %ld - errors occurred",
2583 current_afioball_number);
2584 log_to_screen(tmp);
2585 }
2586 res =
2587 read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2588 if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2589 wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2590 }
2591
2592 current_afioball_number++;
2593 g_current_progress++;
2594 sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2595 current_afioball_number,
2596 media_descriptor_string(bkpinfo->backup_media_type),
2597 g_current_media_number);
2598 res =
2599 read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2600 if (g_getfattr) {
2601 unlink(xattr_fname);
2602 }
2603 if (g_getfacl) {
2604 unlink(acl_fname);
2605 }
2606 } // next
2607 log_msg(1, "All done with afioballs");
2608 close_progress_form();
2609 if (retval) {
2610 mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2611 } else {
2612 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2613 }
2614 paranoid_free(tmp);
2615 paranoid_free(progress_str);
2616 paranoid_free(tmp_fname);
2617 paranoid_free(xattr_fname);
2618 paranoid_free(acl_fname);
2619 return (retval);
2620}
2621
2622/**************************************************************************
2623 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM *
2624 **************************************************************************/
2625
2626/* @} - end of LLrestoreGroup */
2627
2628
2629/**
2630 * Restore all files in @p filelist.
2631 * @param bkpinfo The backup information structure. Most fields are used.
2632 * @param filelist The node structure containing the list of files to be
2633 * restored.
2634 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2635 * @ingroup restoreGroup
2636 */
2637int restore_everything(struct s_node *filelist)
2638{
2639 int resA;
2640 int resB;
2641
2642 /** mallco ***/
2643 char *cwd;
2644 char *newpath;
2645 char *tmp;
2646 assert(bkpinfo != NULL);
2647
2648 malloc_string(cwd);
2649 malloc_string(newpath);
2650 malloc_string(tmp);
2651 log_msg(2, "restore_everything() --- starting");
2652 g_current_media_number = 1;
2653 getcwd(cwd, MAX_STR_LEN - 1);
2654 sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
2655 run_program_and_log_output(tmp, FALSE);
2656 log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2657 chdir(bkpinfo->restore_path);
2658 getcwd(newpath, MAX_STR_LEN - 1);
2659 log_msg(1, "path is now %s", newpath);
2660 log_msg(1, "restoring everything");
2661 if (!find_home_of_exe("petris") && !g_text_mode) {
2662 newtDrawRootText(0, g_noof_rows - 2,
2663 "Press ALT-<left cursor> twice to play Petris :-) ");
2664 newtRefresh();
2665 }
2666 mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
2667 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2668 mount_media();
2669 mvaddstr_and_log_it(g_currentY++, 0,
2670 "Restoring OS and data from streaming media");
2671 if (bkpinfo->backup_media_type == cdstream) {
2672 openin_cdstream();
2673 } else {
2674 assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
2675 openin_tape();
2676 }
2677 resA = restore_all_tarballs_from_stream(filelist);
2678 resB = restore_all_biggiefiles_from_stream(filelist);
2679 if (bkpinfo->backup_media_type == cdstream) {
2680 closein_cdstream();
2681 } else {
2682 closein_tape();
2683 }
2684 } else {
2685 mvaddstr_and_log_it(g_currentY++, 0,
2686 "Restoring OS and data from CD/USB ");
2687 mount_media();
2688 resA = restore_all_tarballs_from_CD(filelist);
2689 resB = restore_all_biggiefiles_from_CD(filelist);
2690 }
2691 chdir(cwd);
2692 if (resA + resB) {
2693 log_to_screen("Errors occurred while data was being restored.");
2694 }
2695 if (length_of_file("/etc/raidtab") > 0) {
2696 log_msg(2, "Copying local raidtab to restored filesystem");
2697 run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2698 "/etc/raidtab", FALSE);
2699 }
2700 kill_petris();
2701 log_msg(2, "restore_everything() --- leaving");
2702 paranoid_free(cwd);
2703 paranoid_free(newpath);
2704 paranoid_free(tmp);
2705 return (resA + resB);
2706}
2707
2708/**************************************************************************
2709 *END_RESTORE_EVERYTHING *
2710 **************************************************************************/
2711
2712
2713
2714/**
2715 * @brief Haha. You wish! (This function is not implemented :-)
2716 */
2717int
2718restore_live_from_monitas_server(char *monitas_device,
2719 char *restore_this_directory,
2720 char *restore_here)
2721 /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2722{
2723 FILE *fout;
2724 int retval = 0;
2725 int i;
2726 int j;
2727 struct mountlist_itself the_mountlist;
2728 static struct raidlist_itself the_raidlist;
2729 /** malloc **/
2730 char tmp[MAX_STR_LEN + 1];
2731 char command[MAX_STR_LEN + 1];
2732 char datablock[256 * 1024];
2733 char datadisks_fname[MAX_STR_LEN + 1];
2734 long k;
2735 long length;
2736 long long llt;
2737 struct s_node *filelist = NULL;
2738 assert(bkpinfo != NULL);
2739 assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2740 assert(restore_this_directory != NULL);
2741 assert(restore_here != NULL);
2742
2743 sprintf(tmp, "restore_here = '%s'", restore_here);
2744
2745 log_msg(2, tmp);
2746
2747 log_msg(2, "restore_live_from_monitas_server() - starting");
2748 unlink("/tmp/mountlist.txt");
2749 unlink("/tmp/filelist.full");
2750 unlink("/tmp/biggielist.txt");
2751 if (restore_here[0] == '\0') {
2752 strcpy(bkpinfo->restore_path, MNT_RESTORING);
2753 } else {
2754 strcpy(bkpinfo->restore_path, restore_here);
2755 }
2756 log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2757 sprintf(tmp, "FYI - data will be restored to %s",
2758 bkpinfo->restore_path);
2759 log_msg(3, tmp);
2760 log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2761 sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2762 (int) (random() % 32768));
2763 chdir(bkpinfo->tmpdir);
2764
2765 sprintf(command, "cat %s", monitas_device);
2766 g_tape_stream = popen(command, "r"); // for compatibility with openin_tape()
2767 if (!(fout = fopen(datadisks_fname, "w"))) {
2768 log_OS_error(datadisks_fname);
2769 return (1);
2770 }
2771 for (i = 0; i < 32; i++) {
2772 for (j = 0; j < 4; j++) {
2773 for (length = k = 0; length < 256 * 1024; length += k) {
2774 k = fread(datablock + length, 1, 256 * 1024 - length,
2775 g_tape_stream);
2776 }
2777 fwrite(datablock, 1, length, fout);
2778 g_tape_posK += length;
2779 }
2780 }
2781 paranoid_fclose(fout);
2782 sprintf(command,
2783 "tar -zxvf %s ./tmp/mondo-restore.cfg ./tmp/mountlist.txt ./tmp/filelist.full ./tmp/biggielist.txt",
2784 datadisks_fname);
2785 run_program_and_log_output(command, 4);
2786 read_header_block_from_stream(&llt, tmp, &i);
2787 read_header_block_from_stream(&llt, tmp, &i);
2788
2789 unlink(datadisks_fname);
2790 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
2791 retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo strcpy(bkpinfo->media_device, monitas_device);
2792
2793
2794 load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2795 iamhere("FIXME");
2796 fatal_error("This will fail");
2797 sprintf(command,
2798 "grep -E '^%s.*$' %s > %s",
2799 restore_this_directory, g_filelist_full, g_filelist_full);
2800 if (system(command)) {
2801 retval++;
2802 log_to_screen
2803 ("Error(s) occurred while processing filelist and wildcard");
2804 }
2805 iamhere("FIXME");
2806 fatal_error("This will fail");
2807 sprintf(command,
2808 "grep -E '^%s.*$' %s > %s",
2809 restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2810 if (system(command)) {
2811 log_msg(1,
2812 "Error(s) occurred while processing biggielist and wildcard");
2813 }
2814 sprintf(command, "touch %s", g_biggielist_txt);
2815 run_program_and_log_output(command, FALSE);
2816// filelist = load_filelist(g_filelist_restthese); // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2817 retval += restore_everything(filelist);
2818 free_filelist(filelist);
2819 log_msg(2, "--------End of restore_live_from_monitas_server--------");
2820 return (retval);
2821}
2822
2823/**************************************************************************
2824 *END_RESTORE_LIVE_FROM_MONITAS_SERVER *
2825 **************************************************************************/
2826
2827
2828
2829
2830extern void wait_until_software_raids_are_prepped(char *, int);
2831
2832
2833char which_restore_mode(void);
2834
2835
2836/**
2837 * Log a "don't panic" message to the logfile.
2838 */
2839void welcome_to_mondorestore()
2840{
2841 log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2842 log_msg(0,
2843 "DON'T PANIC! Mondorestore logs almost everything, so please ");
2844 log_msg(0,
2845 "don't break out in a cold sweat just because you see a few ");
2846 log_msg(0,
2847 "error messages in the log. Read them; analyze them; see if ");
2848 log_msg(0,
2849 "they are significant; above all, verify your backups! Please");
2850 log_msg(0,
2851 "attach a compressed copy of this log to any e-mail you send ");
2852 log_msg(0,
2853 "to the Mondo mailing list when you are seeking technical ");
2854 log_msg(0,
2855 "support. Without it, we can't help you. - DevTeam");
2856 log_msg(0,
2857 "------------------------------------------------------------");
2858 log_msg(0,
2859 "BTW, despite (or perhaps because of) the wealth of messages,");
2860 log_msg(0,
2861 "some users are inclined to stop reading this log. If Mondo ");
2862 log_msg(0,
2863 "stopped for some reason, chances are it's detailed here. ");
2864 log_msg(0,
2865 "More than likely there's a message at the very end of this ");
2866 log_msg(0,
2867 "log that will tell you what is wrong. Please read it! ");
2868 log_msg(0,
2869 "------------------------------------------------------------");
2870}
2871
2872
2873
2874/**
2875 * Restore the user's data.
2876 * What did you think it did, anyway? :-)
2877 */
2878int main(int argc, char *argv[])
2879{
2880 FILE *fin;
2881 FILE *fout;
2882 int retval = 0;
2883 int res;
2884// int c;
2885 char *tmp;
2886
2887 struct mountlist_itself *mountlist;
2888 struct raidlist_itself *raidlist;
2889 struct s_node *filelist;
2890 char *a, *b;
2891 bool run_postnuke = FALSE;
2892
2893 /**************************************************************************
2894 * hugo- *
2895 * busy stuff here - it needs some comments -stan *
2896 * *
2897 **************************************************************************/
2898 if (getuid() != 0) {
2899 fprintf(stderr, "Please run as root.\r\n");
2900 exit(127);
2901 }
2902 if (!
2903 (bkpinfo = malloc(sizeof(struct s_bkpinfo)))) {
2904 fatal_error("Cannot malloc bkpinfo");
2905 }
2906 reset_bkpinfo();
2907
2908 g_loglevel = DEFAULT_MR_LOGLEVEL;
2909 malloc_string(tmp);
2910
2911/* Configure global variables */
2912#ifdef __FreeBSD__
2913 if (strstr
2914 (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2915 "textonly"))
2916#else
2917 if (strstr
2918 (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2919 "textonly"))
2920#endif
2921 {
2922 g_text_mode = TRUE;
2923 log_msg(1, "TEXTONLY MODE");
2924 } else {
2925 g_text_mode = FALSE;
2926 } // newt :-)
2927 if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
2928 fatal_error("Cannot malloc mountlist");
2929 }
2930 if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
2931 fatal_error("Cannot malloc raidlist");
2932 }
2933
2934 malloc_libmondo_global_strings();
2935
2936 strcpy(g_mondo_home,
2937 call_program_and_get_last_line_of_output("which mondorestore"));
2938 sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2939 make_hole_for_dir(g_tmpfs_mountpt);
2940 g_current_media_number = 1; // precaution
2941
2942 run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2943
2944 malloc_string(tmp);
2945 malloc_string(a);
2946 malloc_string(b);
2947 setup_MR_global_filenames(); // malloc() and set globals, using bkpinfo->tmpdir etc.
2948 bkpinfo->backup_media_type = none; // in case boot disk was made for one backup type but user wants to restore from another backup type
2949 bkpinfo->restore_data = TRUE; // Well, yeah :-)
2950 if (am_I_in_disaster_recovery_mode()) {
2951 run_program_and_log_output("mount / -o remount,rw", 2);
2952 } // for b0rken distros
2953 g_main_pid = getpid();
2954 srandom((int) (time(NULL)));
2955 register_pid(getpid(), "mondo");
2956 set_signals(TRUE);
2957 g_kernel_version = get_kernel_version();
2958
2959 log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2960 if (strlen(g_mountlist_fname) < 3) {
2961 fatal_error
2962 ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2963 }
2964 mkdir(MNT_CDROM, 0x770);
2965 make_hole_for_dir(MONDO_CACHE);
2966
2967 /* Backup original mountlist.txt */
2968 sprintf(tmp, "%s.orig", g_mountlist_fname);
2969 if (!does_file_exist(g_mountlist_fname)) {
2970 log_msg(2,
2971 "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2972 __LINE__, g_mountlist_fname);
2973 } else if (!does_file_exist(tmp)) {
2974 sprintf(tmp, "cp -f %s %s.orig", g_mountlist_fname,
2975 g_mountlist_fname);
2976 run_program_and_log_output(tmp, FALSE);
2977 }
2978
2979 /* Init directories */
2980 make_hole_for_dir("/var/log");
2981 make_hole_for_dir("/tmp/tmpfs"); /* just in case... */
2982 run_program_and_log_output("umount " MNT_CDROM, FALSE);
2983 /*
2984 run_program_and_log_output("ln -sf /var/log/mondo-archive.log /tmp/mondorestore.log",
2985 FALSE);
2986 */
2987
2988 run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2989
2990 /* Init GUI */
2991 malloc_libmondo_global_strings();
2992 setup_newt_stuff(); /* call newtInit and setup screen log */
2993 welcome_to_mondorestore();
2994 if (bkpinfo->disaster_recovery) {
2995 log_msg(1, "I am in disaster recovery mode");
2996 } else {
2997 log_msg(1, "I am in normal, live mode");
2998 }
2999
3000 iamhere("what time is it");
3001
3002 /* Process command-line parameters */
3003 if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
3004#ifdef __FreeBSD__
3005 system("mv -f /tmp/raidconf.txt /etc/raidtab");
3006 if (!does_file_exist("/etc/raidtab"))
3007 system("vinum printconfig > /etc/raidtab");
3008#endif
3009 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3010 if (!does_file_exist(g_mountlist_fname)) {
3011 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3012 }
3013 res = let_user_edit_the_mountlist(mountlist, raidlist);
3014#ifdef __FreeBSD__
3015 system("mv -f /etc/raidtab /tmp/raidconf.txt");
3016#endif
3017 paranoid_MR_finish(res);
3018 }
3019
3020 g_loglevel = DEFAULT_MR_LOGLEVEL;
3021 if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
3022 fout = fopen("/tmp/out.txt", "w");
3023 fput_string_one_char_at_a_time(stderr, argv[2]);
3024 finish(0);
3025 }
3026
3027 if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
3028 make_grub_install_scriptlet(argv[2]);
3029 finish(0);
3030 }
3031
3032 if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
3033 if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
3034 system("mount " MNT_CDROM);
3035 }
3036 bkpinfo->compression_level = 1;
3037 g_current_media_number = 2;
3038 strcpy(bkpinfo->restore_path, "/tmp/TESTING");
3039 bkpinfo->backup_media_type = dvd;
3040 open_progress_form("Reassembling /dev/hda1",
3041 "Shark is a bit of a silly person.",
3042 "Please wait. This may take some time.",
3043 "", 1999);
3044 system("rm -Rf /tmp/*pih*");
3045
3046 restore_a_biggiefile_from_CD(42, NULL, tmp);
3047 }
3048
3049 if (argc == 5 && strcmp(argv[1], "--common") == 0) {
3050 g_loglevel = 6;
3051 filelist = load_filelist(argv[2]);
3052 if (!filelist) {
3053 fatal_error("Failed to load filelist");
3054 }
3055 toggle_node_selection(filelist, FALSE);
3056 toggle_all_root_dirs_on(filelist);
3057 // BERLIOS: /usr/lib ???
3058 toggle_path_selection(filelist, "/usr/share", TRUE);
3059// show_filelist(filelist);
3060 save_filelist(filelist, "/tmp/out.txt");
3061// finish(0);
3062// toggle_path_selection (filelist, "/root/stuff", TRUE);
3063 strcpy(a, argv[3]);
3064 strcpy(b, argv[4]);
3065
3066 res = save_filelist_entries_in_common(a, filelist, b, FALSE);
3067 free_filelist(filelist);
3068 printf("res = %d", res);
3069 finish(0);
3070 }
3071
3072 if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
3073 popup_changelist_from_file(argv[2]);
3074 paranoid_MR_finish(0);
3075 }
3076
3077 if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
3078 log_msg(1, "SCORE");
3079 g_loglevel = 10;
3080 if (strstr(argv[2], "save")) {
3081 log_msg(1, "Saving from %s to %s", argv[3], argv[4]);
3082 fin = fopen(argv[3], "r");
3083 fout = fopen(argv[4], "w");
3084 copy_from_src_to_dest(fin, fout, 'w');
3085 fclose(fin);
3086 fin = fopen(argv[3], "r");
3087 copy_from_src_to_dest(fin, fout, 'w');
3088 fclose(fout);
3089 fclose(fin);
3090 } else if (strstr(argv[2], "restore")) {
3091 fout = fopen(argv[3], "w");
3092 fin = fopen(argv[4], "r");
3093 copy_from_src_to_dest(fout, fin, 'r');
3094 fclose(fin);
3095 fin = fopen(argv[4], "r");
3096 copy_from_src_to_dest(fout, fin, 'r');
3097 fclose(fout);
3098 fclose(fin);
3099 } else {
3100 fatal_error("Unknown additional param");
3101 }
3102 finish(0);
3103 }
3104
3105 if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
3106 wait_until_software_raids_are_prepped(argv[2], 100);
3107 finish(0);
3108 }
3109
3110 if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
3111 finish(create_raidtab_from_mdstat(argv[2]));
3112 }
3113
3114 if (argc == 3 && strcmp(argv[1], "-p") == 0) {
3115 strcpy(bkpinfo->prefix,argv[2]);
3116 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
3117 }
3118
3119 if (argc == 3 && strcmp(argv[1], "-K") == 0) {
3120 g_loglevel = atoi(argv[2]);
3121 log_msg(1,"Loglevel forced to %s",g_loglevel);
3122 }
3123
3124 if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
3125 retval = run_grub(FALSE, "/dev/hda");
3126 if (retval) {
3127 log_to_screen("Failed to write Master Boot Record");
3128 }
3129 paranoid_MR_finish(0);
3130 }
3131 if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
3132 g_current_media_number = atoi(argv[2]);
3133 pause_and_ask_for_cdr(5, NULL);
3134 paranoid_MR_finish(0);
3135 } else if (!bkpinfo->disaster_recovery) { // live!
3136 if (argc != 1) {
3137 popup_and_OK
3138 ("Live mode doesn't support command-line parameters yet.");
3139 paranoid_MR_finish(1);
3140// return(1);
3141 }
3142 log_msg(1, "I am in normal, live mode.");
3143 log_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
3144 mount_boot_if_necessary(); /* for Gentoo users */
3145 log_msg(2, "Still here.");
3146 if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
3147 g_restoring_live_from_cd = TRUE;
3148 }
3149 if (bkpinfo->backup_media_type == nfs) {
3150 g_restoring_live_from_nfs = TRUE;
3151 }
3152 if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
3153 retval =
3154 restore_live_from_monitas_server(argv[2],
3155 argv[3], argv[4]);
3156 } else {
3157 log_msg(2, "Calling restore_to_live_filesystem()");
3158 retval = restore_to_live_filesystem();
3159 }
3160 log_msg(2, "Still here. Yay.");
3161 if (strlen(bkpinfo->tmpdir) > 0) {
3162 sprintf(tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3163 run_program_and_log_output(tmp, FALSE);
3164 }
3165 unmount_boot_if_necessary(); /* for Gentoo users */
3166 paranoid_MR_finish(retval);
3167 } else {
3168 /* Disaster recovery mode (must be) */
3169 log_msg(1, "I must be in disaster recovery mode.");
3170 log_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3171 if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
3172 log_to_screen("Uh, that hasn't been implemented yet.");
3173 paranoid_MR_finish(1);
3174 }
3175
3176 iamhere("About to call load_mountlist and load_raidtab");
3177 strcpy(bkpinfo->restore_path, MNT_RESTORING);
3178 read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
3179 retval = load_mountlist(mountlist, g_mountlist_fname);
3180 retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3181 iamhere
3182 ("Returned from calling load_mountlist and load_raidtab successfully");
3183
3184 if (argc > 1
3185 && (strcmp(argv[1], "--compare") == 0
3186 || strcmp(argv[1], "--nuke") == 0)) {
3187 if (bkpinfo->backup_media_type == nfs
3188 && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3189 log_msg(1, "Mounting nfs dir");
3190 sprintf(bkpinfo->isodir, "/tmp/isodir");
3191 run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3192 sprintf(tmp, "mount %s -t nfs -o nolock /tmp/isodir",
3193 bkpinfo->nfs_mount);
3194 run_program_and_log_output(tmp, 1);
3195 }
3196 }
3197
3198
3199 if (retval) {
3200 log_to_screen
3201 ("Warning - load_raidtab_into_raidlist returned an error");
3202 }
3203
3204
3205 log_msg(1, "Send in the clowns.");
3206
3207 if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
3208 log_msg(0, "Partitioning only.");
3209 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3210 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3211 load_mountlist(mountlist, g_mountlist_fname);
3212 res = partition_everything(mountlist);
3213 finish(res);
3214 }
3215
3216 if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3217 log_msg(0, "Formatting only.");
3218 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3219 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3220 load_mountlist(mountlist, g_mountlist_fname);
3221 res = format_everything(mountlist, FALSE, raidlist);
3222 finish(res);
3223 }
3224
3225 if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3226 log_msg(0, "Stopping LVM and RAID");
3227 load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3228 strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3229 load_mountlist(mountlist, g_mountlist_fname);
3230 res = do_my_funky_lvm_stuff(TRUE, FALSE);
3231 res += stop_all_raid_devices(mountlist);
3232 finish(res);
3233 }
3234
3235 if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3236 iamhere("nuking");
3237 retval += nuke_mode(mountlist, raidlist);
3238 } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3239 iamhere("catchall");
3240 retval += catchall_mode(mountlist, raidlist);
3241 } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3242 iamhere("compare");
3243 retval += compare_mode(mountlist, raidlist);
3244 } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3245 iamhere("iso");
3246 retval = iso_mode(mountlist, raidlist, FALSE);
3247 } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3248 iamhere("mbr");
3249 retval = mount_all_devices(mountlist, TRUE);
3250 if (!retval) {
3251 retval += run_boot_loader(FALSE);
3252 retval += unmount_all_devices(mountlist);
3253 }
3254 if (retval) {
3255 log_to_screen("Failed to write Master Boot Record");
3256 }
3257 } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3258 iamhere("isonuke");
3259 retval = iso_mode(mountlist, raidlist, TRUE);
3260 } else if (argc != 1) {
3261 log_to_screen("Invalid paremeters");
3262 paranoid_MR_finish(1);
3263 } else {
3264 iamhere("catchall (no mode specified in command-line call");
3265 retval += catchall_mode(mountlist, raidlist);
3266 }
3267 }
3268
3269 /* clean up at the end */
3270 if (retval) {
3271 if (does_file_exist(MONDO_CACHE"/changed.files")) {
3272 log_to_screen
3273 ("See "MONDO_CACHE"/changed.files for list of files that have changed.");
3274 }
3275 mvaddstr_and_log_it(g_currentY++,
3276 0,
3277 "Run complete. Errors were reported. Please review the logfile.");
3278 } else {
3279 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3280 mvaddstr_and_log_it(g_currentY++,
3281 0,
3282 "Run complete. Please remove media and reboot.");
3283 } else {
3284 run_program_and_log_output("sync", FALSE);
3285 if (is_this_device_mounted(MNT_CDROM)) {
3286 res =
3287 run_program_and_log_output("umount " MNT_CDROM, FALSE);
3288 } else {
3289 res = 0;
3290 }
3291
3292 if (!bkpinfo->please_dont_eject) {
3293 res = eject_device("/dev/cdrom");
3294/*
3295 if (res)
3296 {
3297 log_to_screen( "WARNING - failed to eject CD-ROM disk" );
3298 }
3299*/
3300 }
3301 mvaddstr_and_log_it(g_currentY++,
3302 0,
3303 "Run complete. Please remove media and reboot.");
3304 }
3305 }
3306
3307// g_I_have_just_nuked is set true by nuke_mode() just before it returns
3308 if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3309 log_msg(1, "post-nuke found; find out whether we should run it...");
3310 if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3311 run_postnuke = TRUE;
3312 log_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3313 } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3314 run_postnuke = TRUE;
3315 log_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3316 } else {
3317 run_postnuke = FALSE;
3318 log_msg(1, "No, will not run post-nuke.");
3319 }
3320 } else {
3321 log_msg(1, "No post-nuke found.");
3322 }
3323 if (run_postnuke) {
3324 log_to_screen("Running post-nuke...");
3325 if (mount_all_devices(mountlist, TRUE)) {
3326 log_to_screen
3327 ("Unable to re-mount partitions for post-nuke stuff");
3328 } else {
3329 log_msg(1, "Re-mounted partitions for post-nuke stuff");
3330 sprintf(tmp, "post-nuke %s %d", bkpinfo->restore_path,
3331 retval);
3332 log_msg(2, "Calling '%s'", tmp);
3333 if ((res = run_program_and_log_output(tmp, 0))) {
3334 log_OS_error(tmp);
3335 }
3336 log_msg(1, "post-nuke returned w/ res=%d", res);
3337 }
3338 unmount_all_devices(mountlist);
3339 log_to_screen("I've finished post-nuking.");
3340 }
3341
3342/*
3343 log_to_screen("If you are REALLY in a hurry, hit Ctrl-Alt-Del now.");
3344 log_to_screen("Otherwise, please wait until the RAID disks are done.");
3345 wait_until_software_raids_are_prepped("/proc/mdstat", 100);
3346 log_to_screen("Thank you.");
3347*/
3348 unlink("/tmp/mondo-run-prog.tmp");
3349 set_signals(FALSE);
3350 log_to_screen("Restore log (%s) copied to /var/log on your hard disk", MONDO_LOGFILE);
3351 sprintf(tmp,
3352 "Mondo-restore is exiting (retval=%d) ",
3353 retval);
3354 log_to_screen(tmp);
3355 sprintf(tmp, "umount %s", bkpinfo->isodir);
3356 run_program_and_log_output(tmp, 5);
3357 paranoid_free(mountlist);
3358 paranoid_free(raidlist);
3359 if (am_I_in_disaster_recovery_mode()) {
3360 run_program_and_log_output("mount / -o remount,rw", 2);
3361 } // for b0rken distros
3362 sprintf(tmp, "rm -Rf %s", bkpinfo->tmpdir);
3363 system(tmp);
3364 paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3365 free_libmondo_global_strings(); // it's fine to have this here :) really :)
3366 paranoid_free(a);
3367 paranoid_free(b);
3368 paranoid_free(tmp);
3369
3370 unlink("/tmp/filelist.full");
3371 unlink("/tmp/filelist.full.gz");
3372
3373 exit(retval);
3374}
3375
3376/**************************************************************************
3377 *END_MAIN *
3378 **************************************************************************/
3379
3380
3381
3382
3383
3384/**************************************************************************
3385 *END_MONDO-RESTORE.C *
3386 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.