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

Last change on this file since 3544 was 3544, checked in by Bruno Cornec, 8 years ago

i- The cal to unmount_all_devices copies the log file on to the disk, so after all new log info such as labelling are not copied and thus should be considered on the restored system directly.

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