source: MondoRescue/branches/stable/mondo/mondo/mondorestore/mondo-restore.c@ 541

Last change on this file since 541 was 541, checked in by bcornec, 18 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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