source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondorestore.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


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