source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondorestore.c@ 3193

Last change on this file since 3193 was 3193, checked in by Bruno Cornec, 11 years ago
  • Finish with backports from 3.1 for now. Still some work to do, but we will now make that version compile and work again and serve as a base

so the gettext patch can be added

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