source: MondoRescue/branches/stable/mondo/src/mondorestore/mondorestore.c@ 1297

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