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

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

ps (busybox) and ps (system) do not give PID in the same column. Adapted with a global variable.

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