source: MondoRescue/branches/2.2.2/mondo/src/mondorestore/mondo-restore.c@ 1315

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

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

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