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

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

so the gettext patch can be added

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