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

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