source: MondoRescue/trunk/mondo/src/mondorestore/mondo-restore.c@ 900

Last change on this file since 900 was 900, checked in by Bruno Cornec, 18 years ago

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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