source: MondoRescue/branches/2.06/mondo/mondo/mondorestore/mondo-restore.c

Last change on this file was 296, checked in by andree, 18 years ago

Replaced partimagehack with ntfsclone from ntfsprogs package. Replaced
all occurrences of strings 'partimagehack' and 'partimage' with 'ntfsprog'.

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