source: MondoRescue/branches/3.3/mondo/src/mondorestore/mondorestore.c@ 3790

Last change on this file since 3790 was 3790, checked in by Bruno Cornec, 21 months ago

Backport link fixes made for 3.2.2 to allow build on recent gcc versions

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