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

Last change on this file since 1213 was 1213, checked in by Bruno Cornec, 17 years ago

Removal of g_mondo_home useless and used MONDO_SHARE instead

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