source: branches/2.2.10/mondo/src/mondorestore/mondo-rstr-tools.c @ 2816

Last change on this file since 2816 was 2816, checked in by Bruno Cornec, 9 years ago

svn merge (in svk) -r 2714:2773 2.2.9 in 2.2.10

r4207@localhost (orig r2716): bruno | 2011-02-03 01:29:51 +0100

  • Increase boot size again to support better fedora 13/14


r4208@localhost (orig r2717): bruno | 2011-02-12 15:43:36 +0100

  • Excluding vmhgfs FS for VMWare guests mounting areas of the host.


r4209@localhost (orig r2718): bruno | 2011-02-18 00:30:35 +0100
-Extend EXTRA-SIZE for Debian 6.0 (at least)


r4210@localhost (orig r2719): bruno | 2011-02-18 00:45:40 +0100

  • Fix #462 (removes temp dir if analyze-my-lvm launched in stand alonae mode)


r4213@localhost (orig r2722): bruno | 2011-02-25 18:44:47 +0100

  • Fixes for RHEL6 support at least around dm extensions, bnx2x and cp210x dependencies


r4214@localhost (orig r2723): bruno | 2011-02-25 19:00:17 +0100

  • Adds a restore quiet option


r4215@localhost (orig r2724): bruno | 2011-02-25 19:43:50 +0100

  • Adds support for dm-log used on RHEL6 as well.


r4216@localhost (orig r2725): bruno | 2011-02-25 21:26:54 +0100

  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3


r4217@localhost (orig r2726): bruno | 2011-02-26 11:38:29 +0100

  • Fix error introduced in previous patch in the if/then/else case without member in the then


r4218@localhost (orig r2727): bruno | 2011-02-26 12:05:33 +0100

  • With mindi-busybox 1.18.3 the syntax of openvt changed. This patch keeps a compatible init script for both previous and current version.


r4219@localhost (orig r2728): bruno | 2011-02-26 15:27:40 +0100

  • Latest lvdisplay print MiB instead of MB. Impact on analyze-my-lvm fixed.


r4220@localhost (orig r2729): bruno | 2011-02-26 16:39:32 +0100

  • Adds feature rpc to mindi-busybox in case of need



r4221@localhost (orig r2730): bruno | 2011-02-26 16:42:43 +0100

  • Adds the rebot command to the list of mandatory ones at restore time


r4222@localhost (orig r2731): bruno | 2011-02-26 17:37:13 +0100

  • Adds functions and /bin/loadkeys (new location) to minimal set of commands to have
  • provides a makemessage option to mindi and this function now works with pbdistrocheck
  • Do not create an error when a phys device has 0 size and is a /dev/dm-* device


r4223@localhost (orig r2732): bruno | 2011-02-26 19:07:43 +0100

  • Syntax fix


r4224@localhost (orig r2733): bruno | 2011-02-26 19:51:16 +0100

  • Fix test on dm which was made in wrong sense
  • Adds a driver to allow raid456 to work


r4225@localhost (orig r2734): bruno | 2011-02-26 20:55:00 +0100

  • Fix 2 redirections issues


r4317@localhost (orig r2737): bruno | 2011-03-13 13:12:57 +0100

  • Add support for libahci driver, mandatory for debian 6.


r4318@localhost (orig r2738): bruno | 2011-03-13 14:46:37 +0100

  • Update from Lester Wade (lester.wade_at_hp.com) incorporating latest ML feedbacks


r4319@localhost (orig r2739): bruno | 2011-03-13 17:49:15 +0100

  • Updated Lab for TES 2011


r4323@localhost (orig r2743): bruno | 2011-03-20 01:37:40 +0100

  • Fix a seg fault bug when using the GUI in case exclude_paths was NULL (mc_at_carreira.com.pt)


r4324@localhost (orig r2744): bruno | 2011-03-20 19:38:14 +0100

  • Adds Arch Linux Keyboard support (mc_at_carreira.com.pt)


r4325@localhost (orig r2745): bruno | 2011-03-20 19:48:01 +0100

  • Avoids coredump again when exclude_path is NULL with mr_make_devlist_from_pathlist (feedback from mc_at_carreira.com.pt)


r4326@localhost (orig r2746): bruno | 2011-03-20 19:39:47 +0100

  • Remove blkid from busybox to solve #435


r4327@localhost (orig r2747): bruno | 2011-03-20 19:43:22 +0100

  • Adds reboot to fix #435


r4328@localhost (orig r2748): bruno | 2011-03-22 00:58:07 +0100

  • Fix Arch Linux kbd printed in log file now instead of screen.


r4329@localhost (orig r2749): bruno | 2011-03-22 00:59:58 +0100

  • Again increase size for boot env to support better fedora 14 and other latest distros


r4356@localhost (orig r2750): bruno | 2011-03-25 19:30:01 +0100

  • Improve Arch Linux support for mindi tools (mc_at_carreira.com.pt)


r4357@localhost (orig r2751): bruno | 2011-03-25 19:48:33 +0100

  • Accept to work with either wodim or cdreord and genisoimage or mkisofs


r4358@localhost (orig r2752): bruno | 2011-03-25 20:20:49 +0100

  • Documents option -v of mondoarchive


r4359@localhost (orig r2753): bruno | 2011-03-29 01:34:30 +0200

  • Use modprobe instead of insmod to load loop, cd, ... modules (in order to force them at rstore time). Also drop very old aes support for mdk 9.2


r4360@localhost (orig r2754): bruno | 2011-03-29 01:38:49 +0200

  • Arch Linux support for boot message of mindi (mc_at_carreira.com.pt) using /etc/arch-release and pacman.log


r4383@localhost (orig r2755): bruno | 2011-04-07 09:49:38 +0200

  • Adds a UdevadmTrigger? function at restore time to deal with the various syntax formats changes ddepending on version (mc_at_carreira.com.pt)


r4384@localhost (orig r2756): bruno | 2011-04-07 10:05:24 +0200

  • Increase again sizes for Debian 6 support (victor.gattegno_at_hp.com)


r4385@localhost (orig r2757): bruno | 2011-04-07 10:13:00 +0200
Conform to the report of size really !


r4386@localhost (orig r2758): bruno | 2011-04-07 11:31:12 +0200

  • Improved message for Arch Linux for rebuilding the initrd (mc_at_carreira.com.pt)


r4390@localhost (orig r2759): bruno | 2011-04-12 01:15:00 +0200

  • Typo in Web site


r4392@localhost (orig r2761): bruno | 2011-04-14 00:23:38 +0200

  • Adds download references for latest versions.


r4394@localhost (orig r2763): bruno | 2011-04-16 00:35:08 +0200

  • Adds support for MT back mandatory for OBDR.


r4395@localhost (orig r2764): bruno | 2011-04-20 12:18:46 +0200
Function resize_drive_proportionately_to_suit_new_drives

  • Integrate some mr_asprintf
  • Use systematically long long data types in all computation to match the struct mountlist_reference size member and have correct precision
  • Apply JB general_at_itpsg.com patch to make the partition resizing work properly according to the drive size (keeping all calculation in KB and converting only for display)


r4396@localhost (orig r2765): bruno | 2011-04-21 11:20:58 +0200

  • Remove very old code creating confusing symlinks pico to nano in init (patch from MC). Fix #477


r4397@localhost (orig r2766): bruno | 2011-04-21 11:57:44 +0200

  • text's are properly centered in open_and_list_dir (Patch from Chucky). Fix #404.


r4398@localhost (orig r2767): bruno | 2011-04-21 12:49:40 +0200

  • Attempt to fix #432 with a better message at a start.


r4399@localhost (orig r2768): bruno | 2011-04-21 13:00:37 +0200

Log content of mondo-restore.cfg


r4400@localhost (orig r2769): bruno | 2011-04-21 13:48:52 +0200

  • Introduce a new bkpinfo member (subdir) to support storing the subdir under which ISO images are stored on an external HDD. Should fix mostly #433.


r4401@localhost (orig r2770): bruno | 2011-04-21 14:14:52 +0200

  • Fix compilation issues due to level of visibility of functions


r4402@localhost (orig r2771): bruno | 2011-04-22 01:49:03 +0200

  • Adds GUI support for compresion type. Fix half of #468.


r4403@localhost (orig r2772): bruno | 2011-04-22 02:00:07 +0200

  • Adds support of ext attr through the GUI. Fix second part of #468


r4404@localhost (orig r2773): bruno | 2011-04-22 02:22:24 +0200

  • Propose more variables in the mindi.conf example
  • More explicit messages when size unsufficient in mindi for kernel + initrd as per #471
  • Better loging of labeling in mondo when in nuke mode


  • Property svn:keywords set to Id
File size: 62.2 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 2816 2011-04-29 13:42:55Z bruno $
3***************************************************************************/
4
5#include <pthread.h>
6#include <linux/fd.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "mr_str.h"
10#include "../common/mondostructures.h"
11#include "../common/libmondo.h"
12#include "mr-externs.h"
13#include "mondo-rstr-tools.h"
14
15extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
16extern bool g_I_have_just_nuked;
17/*
18extern char *g_tmpfs_mountpt;
19*/
20extern char *g_isodir_device;
21extern long g_current_progress, g_maximum_progress;
22extern char *g_biggielist_pot;  // list of big files which _could_ be restored, if the
23                  // user chooses them
24extern char *g_filelist_imagedevs;  // list of devices (e.g. /dev/hda1, /dev/sda5) which
25                     // were archived as images, not just /dev entries
26                     // ... e.g. NTFS, BeOS partitions
27extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
28                      // restore only these
29extern char *g_mondo_home;      // homedir of Mondo; usually /usr/local/share/mondo
30
31extern t_bkptype g_backup_media_type;
32
33extern int g_partition_table_locked_up;
34extern char *MONDO_LOGFILE;
35
36/* Reference to global bkpinfo */
37extern struct s_bkpinfo *bkpinfo;
38
39/* Should we use or not extended attributes and acl when restoring */
40char *g_getfattr = NULL;
41char *g_getfacl = NULL;
42
43extern void kill_anything_like_this(char *str);
44extern int skip_obdr(void);
45extern int mount_media();
46extern int set_tape_block_size_with_mt(long internal_tape_block_size);
47
48/**
49* @addtogroup restoreUtilityGroup
50* @{
51*/
52/**
53* Free the malloc()s for the filename variables.
54*/
55void free_MR_global_filenames(void)
56{
57paranoid_free(g_filelist_imagedevs);
58paranoid_free(g_imagedevs_restthese);
59paranoid_free(g_mondo_home);
60/*
61paranoid_free(g_tmpfs_mountpt);
62*/
63mr_free(g_isodir_device);
64
65}
66
67
68
69/**
70* Ask the user which imagedevs from the list contained in @p infname should
71* actually be restored.
72* @param infname The file containing a list of all imagedevs.
73* @param outfname The location of the output file containing the imagedevs the user wanted to restore.
74* @ingroup restoreUtilityGroup
75*/
76void ask_about_these_imagedevs(char *infname, char *outfname) {
77
78FILE *fin;
79FILE *fout;
80char *incoming = NULL;
81char *question = NULL;
82
83assert_string_is_neither_NULL_nor_zerolength(infname);
84assert_string_is_neither_NULL_nor_zerolength(outfname);
85
86if (!(fin = fopen(infname, "r"))) {
87    fatal_error("Cannot openin infname");
88}
89if (!(fout = fopen(outfname, "w"))) {
90    fatal_error("Cannot openin outfname");
91}
92for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
93    mr_strip_spaces(incoming);
94
95    if (incoming[0] == '\0') {
96        mr_free(incoming);
97        continue;
98    }
99
100    mr_asprintf(question, "Should I restore the image of %s ?", incoming);
101   
102    if (ask_me_yes_or_no(question)) {
103        fprintf(fout, "%s\n", incoming);
104    }
105    mr_free(incoming);
106}
107mr_free(incoming);
108mr_free(question);
109paranoid_fclose(fout);
110paranoid_fclose(fin);
111}
112
113/**************************************************************************
114*ASK_ABOUT_THESE_IMAGEDEVS                                               *
115**************************************************************************/
116
117/**
118* Determine whether @p list_fname contains a line containing @p f.
119* @param f The line to search for.
120* @param list_fname The file to search in.
121* @param preamble Ignore this beginning part of @p f ("" to disable).
122* @return TRUE if it's in the list, FALSE if it's not.
123*/
124bool is_file_in_list(char *f, char *list_fname, char *preamble)
125{
126
127char *command = NULL;
128char *file = NULL;
129char *tmp = NULL;
130int res;
131
132assert_string_is_neither_NULL_nor_zerolength(f);
133assert_string_is_neither_NULL_nor_zerolength(list_fname);
134assert(preamble != NULL);
135
136if (strncmp(preamble, f, strlen(preamble)) == 0) {
137    mr_asprintf(file, "%s", f + strlen(preamble));
138} else {
139    mr_asprintf(file, "%s", f);
140}
141if (file[0] == '/' && file[1] == '/') {
142    mr_asprintf(tmp, "%s", file);
143    mr_free(file);
144
145    mr_asprintf(file, "%s", tmp + 1);
146    mr_free(tmp);
147}
148log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
149mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
150mr_free(file);
151
152res = run_program_and_log_output(command, FALSE);
153mr_free(command);
154if (res) {
155    return (FALSE);
156} else {
157    return (TRUE);
158}
159}
160
161/**************************************************************************
162*END_IS_FILE_IN_LIST                                                     *
163**************************************************************************/
164
165
166
167/**
168* Set up an ISO backup.
169* @param bkpinfo The backup information structure. Fields used:
170* - @c bkpinfo->backup_media_type
171* - @c bkpinfo->disaster_recovery
172* - @c bkpinfo->isodir
173* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
174* @return 0 for success, nonzero for failure.
175*/
176int iso_fiddly_bits(bool nuke_me_please)
177{
178    char *mount_isodir_command = NULL;
179    char *command = NULL;
180    char *mds = NULL;
181    int retval = 0, i;
182    bool already_mounted = FALSE;
183    char *isodir_format = NULL;
184
185g_ISO_restore_mode = TRUE;
186mr_free(g_isodir_device);
187g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
188if (bkpinfo->disaster_recovery) {
189    /* Patch Conor Daly 26-june-2004
190    * Don't let this clobber an existing bkpinfo->isodir */
191    if (!bkpinfo->isodir[0]) {
192        mr_free(bkpinfo->isodir);
193        mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
194    }
195    /* End patch */
196    mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
197    run_program_and_log_output(command, 5);
198    mr_free(command);
199    log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
200}
201
202/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
203if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
204    mr_free(isodir_format);
205    return (1);
206}
207paranoid_system("umount "MNT_CDROM" 2> /dev/null"); /* just in case */
208
209if (is_this_device_mounted(g_isodir_device)) {
210    log_to_screen("WARNING - isodir is already mounted");
211    already_mounted = TRUE;
212} else {
213    mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
214    if (isodir_format) {
215        mr_strcat(mount_isodir_command, " -t %s", isodir_format);
216    }
217
218    mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
219    run_program_and_log_output("df -m -P", FALSE);
220    log_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command);
221    if (run_program_and_log_output(mount_isodir_command, FALSE)) {
222        popup_and_OK
223            ("Cannot mount the device where the ISO files are stored.");
224        return (1);
225    }
226    paranoid_free(mount_isodir_command);
227    log_to_screen
228    ("I have mounted the device where the ISO files are stored.");
229}
230mr_free(isodir_format);
231
232if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
233    mount_media();
234}
235i = what_number_cd_is_this();   /* has the side-effect of calling mount_media() */
236mds = media_descriptor_string(bkpinfo->backup_media_type);
237mr_free(mds);
238
239log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
240if (i < 0) {
241    popup_and_OK("Cannot find ISO images in the directory you specified.");
242    retval = 1;
243}
244log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
245return (retval);
246}
247
248
249
250
251/**
252* Kill all Petris processes.
253*/
254void kill_petris(void) {
255    kill_anything_like_this("petris");
256}
257
258/**************************************************************************
259*END_KILL_PETRIS                                                         *
260**************************************************************************/
261
262
263/**
264 * Mount @p device at @p mpt as @p format.
265 * @param device The device (/dev entry) to mount.
266 * @param mpt The directory to mount it on.
267 * @param format The filesystem type of @p device.
268 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
269 * @return 0 for success, nonzero for failure.
270 */
271int mount_device(char *device, char *mpt, char *format, bool writeable)
272{
273int res = 0;
274
275/** malloc **/
276char *tmp = NULL;
277char *command = NULL;
278char *mountdir = NULL;
279char *mountpoint = NULL;
280char *additional_parameters = NULL;
281
282assert_string_is_neither_NULL_nor_zerolength(device);
283assert_string_is_neither_NULL_nor_zerolength(mpt);
284assert(format != NULL);
285
286    if (!strcmp(mpt, "/1")) {
287        mr_asprintf(mountpoint, "/");
288        log_msg(3, "Mommm! SME is being a dildo!");
289    } else {
290        mr_asprintf(mountpoint, "%s", mpt);
291    }
292
293    if (!strcmp(mountpoint, "lvm")) {
294        return (0);
295    }
296    if (!strcmp(mountpoint, "image")) {
297        return (0);
298    }
299    mr_asprintf(tmp, "Mounting device %s   ", device);
300    log_msg(1, tmp);
301    /* Deal with additional params only if not /proc or /sys */
302    mr_asprintf(additional_parameters, "");
303    if (strcmp(format, "proc") && strcmp(format, "sys")) {
304        if (writeable) {
305            mr_strcat(additional_parameters, "-o rw");
306        } else {
307            mr_strcat(additional_parameters, "-o ro");
308        }
309        tmp = find_home_of_exe("setfattr");
310        if (tmp) {
311            mr_strcat(additional_parameters, ",user_xattr");
312        }
313        mr_free(tmp);
314
315        tmp = find_home_of_exe("setfacl");
316        if (tmp) {
317            mr_strcat(additional_parameters, ",acl");
318        }
319        mr_free(tmp);
320    }
321
322    if (!strcmp(mountpoint, "swap")) {
323        mr_asprintf(command, "swapon %s", device);
324        mr_asprintf(mountdir, "swap");
325    } else {
326        if (!strcmp(mountpoint, "/")) {
327            mr_asprintf(mountdir, "%s", MNT_RESTORING);
328        } else {
329            mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
330        }
331        mr_asprintf(command, "mkdir -p %s", mountdir);
332        run_program_and_log_output(command, FALSE);
333        mr_free(command);
334
335        mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
336        log_msg(2, "command='%s'", command);
337    }
338    mr_free(additional_parameters);
339
340    res = run_program_and_log_output(command, TRUE);
341    if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
342        log_msg(1, "Re-trying without the fancy extra parameters");
343        mr_free(command);
344        mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
345        res = run_program_and_log_output(command, TRUE);
346    }
347    if (res) {
348        log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
349        log_msg(1, "command was '%s'", command);
350        if (!strcmp(mountpoint, "swap")) {
351            log_to_screen(tmp);
352        } else {
353            log_msg(2, "Retrying w/o the '-t' switch");
354            mr_free(command);
355            mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
356            log_msg(2, "2nd command = '%s'", command);
357            res = run_program_and_log_output(command, TRUE);
358            if (res == 0) {
359                log_msg(1,
360                    "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
361            } else {
362                log_to_screen(tmp);
363            }
364        }
365    }
366
367    if (res && !strcmp(mountpoint, "swap")) {
368        log_msg(2, "That's ok. It's just a swap partition.");
369        log_msg(2, "Non-fatal error. Returning 0.");
370        res = 0;
371    }
372
373mr_free(tmp);
374mr_free(command);
375mr_free(mountdir);
376mr_free(mountpoint);
377
378    return (res);
379}
380/**************************************************************************
381 *END_MOUNT_DEVICE                                                        *
382**************************************************************************/
383
384
385/**
386 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
387 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
388 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
389 * @return The number of errors encountered (0 for success).
390 */
391int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
392{
393int retval = 0, lino, res;
394char *tmp = NULL;
395char *these_failed = NULL;
396struct mountlist_itself *mountlist = NULL;
397
398assert(p_external_copy_of_mountlist != NULL);
399mountlist = malloc(sizeof(struct mountlist_itself));
400memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
401   sizeof(struct mountlist_itself));
402    sort_mountlist_by_mountpoint(mountlist, 0);
403
404
405    mvaddstr_and_log_it(g_currentY, 0, "Mounting devices         ");
406    open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
407
408    mr_asprintf(these_failed, "");
409    for (lino = 0; lino < mountlist->entries; lino++) {
410        if (!strcmp(mountlist->el[lino].device, "/proc")) {
411            log_msg(1, "Again with the /proc - why is this in your mountlist?");
412        } else if (is_this_device_mounted(mountlist->el[lino].device)) {
413            log_to_screen("%s is already mounted", mountlist->el[lino].device);
414        } else if (strcmp(mountlist->el[lino].mountpoint, "none")
415           && strcmp(mountlist->el[lino].mountpoint, "lvm")
416           && strcmp(mountlist->el[lino].mountpoint, "raid")
417           && strcmp(mountlist->el[lino].mountpoint, "image")) {
418            mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
419            update_progress_form(tmp);
420            mr_free(tmp);
421            res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
422
423            retval += res;
424            if (res) {
425                mr_strcat(these_failed, "%s ",mountlist->el[lino].device);
426            }
427        }
428        g_current_progress++;
429    }
430    close_progress_form();
431    if (retval) {
432        if (g_partition_table_locked_up > 0) {
433            log_to_screen("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to");
434            log_to_screen("lock up the partition table. You might have to reboot and use Interactive Mode to");
435            log_to_screen("format and restore *without* partitioning first. Sorry for the inconvenience.");
436        }
437        mr_asprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed);
438
439        if (!ask_me_yes_or_no(tmp)) {
440            retval = 0;
441            log_to_screen("Continuing, although some device(s) failed to be mounted");
442            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
443        } else {
444            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
445            log_to_screen("Unable to mount some or all of your partitions.");
446        }
447        mr_free(tmp);
448    } else {
449        log_to_screen("All partitions were mounted OK.");
450        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
451    }
452    paranoid_free(these_failed);
453
454    /* Also mounting under MNT_RESTORING  special FS */
455    (void)mount_device("/proc","/proc","proc",TRUE);
456    (void)mount_device("/sys","/sys","sysfs",TRUE);
457    run_program_and_log_output("df -m -P", 3);
458    paranoid_free(mountlist);
459    return (retval);
460}
461/**************************************************************************
462*END_MOUNT_ALL_DEVICES                                                   *
463**************************************************************************/
464
465
466/**
467* Fix some miscellaneous things in the filesystem so the system will come
468* up correctly on the first boot.
469*/
470void protect_against_braindead_sysadmins()
471{
472run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
473                       FALSE);
474run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
475                       FALSE);
476if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
477run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
478                           FALSE);
479}
480run_program_and_log_output("mkdir -p " MNT_RESTORING
481                       "/var/run/console", FALSE);
482run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
483                       FALSE);
484run_program_and_log_output("cd " MNT_RESTORING
485                       "; for i in `ls home/`; do echo \"Moving $i's spurious files to $i/.disabled\"; mkdir \"$i\"/.disabled ; mv -f \"$i\"/.DCOP* \"$i\"/.MCOP* \"$i\"/.*authority \"$i\"/.kde/tmp* \"$i\"/.kde/socket* \"$i\"/.disabled/ ; done",
486                       TRUE);
487run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
488                       TRUE);
489run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
490                       TRUE);
491}
492
493/**************************************************************************
494*END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS                                 *
495**************************************************************************/
496
497
498/**
499 * Extract mondorestore.cfg and the mountlist from the tape inserted
500 * to the ./tmp/ directory.
501 * @param dev The tape device to read from.
502 * @return 0 for success, nonzero for failure.
503 */
504int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
505{
506    char *command = NULL;
507    int res = 0;
508
509    if (bkpinfo->use_obdr) {
510        skip_obdr();
511    } else {
512        // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
513        set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
514    }
515
516    mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size);
517    log_msg(2, "command = '%s'", command);
518    res = run_program_and_log_output(command, -1);
519    mr_free(command);
520
521    return (res);
522}
523
524
525
526/**
527 * Get the configuration file from the initrd of the backup media
528 * case when calling mondorestore live
529 * @param bkpinfo The backup information structure. Fields used:
530 * - @c bkpinfo->backup_media_type
531 * - @c bkpinfo->media_device
532 * - @c bkpinfo->tmpdir
533 * @return 0 for success, nonzero for failure.
534 */
535void get_cfg_file_from_initrd()
536{
537   /** malloc *****/
538    char *command = NULL;
539    char *cfg_file = NULL;
540    char *tmp = NULL;
541    char *mountpt = NULL;
542
543    bool try_plan_B;
544
545    assert(bkpinfo != NULL);
546    log_msg(2, "gcffa --- starting");
547    log_to_screen("I'm thinking...");
548    mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
549    mr_asprintf(command, "mkdir -p %s", mountpt);
550    run_program_and_log_output(command, FALSE);
551    log_msg(2, "mountpt = %s; ", mountpt);
552    mr_free(command);
553
554    chdir(bkpinfo->tmpdir);
555
556    mr_free(mountpt);
557
558    if (!does_file_exist(cfg_file)) {
559        log_msg(2, "gcffa --- we don't have cfg file yet.");
560        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
561            try_plan_B = TRUE;
562        } else {
563            log_msg(2, "gcffa --- calling mount_media now :)");
564            if (!mount_media()) {
565                log_msg(2,
566                        "gcffa --- managed to mount CD; so, no need for Plan B");
567                try_plan_B = FALSE;
568            } else {
569                try_plan_B = TRUE;
570            }
571            if (what_number_cd_is_this() > 1) {
572                insist_on_this_cd_number((g_current_media_number = 1));
573            }
574        }
575        if (try_plan_B) {
576            log_msg(2, "gcffa --- OK, switching to Plan B");
577            chdir(bkpinfo->tmpdir);
578            run_program_and_log_output("mkdir -p tmp", FALSE);
579
580            if (! bkpinfo->media_device) {
581                mr_asprintf(bkpinfo->media_device, "/dev/st0");
582                log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device);
583            }
584            mr_asprintf(tmp, "%s", bkpinfo->media_device);
585            if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
586                mr_free(bkpinfo->media_device);
587                mr_asprintf(bkpinfo->media_device, "/dev/st0");
588                if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
589                    mr_free(bkpinfo->media_device);
590                    mr_asprintf(bkpinfo->media_device, "/dev/osst0");
591                    if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
592                        mr_free(bkpinfo->media_device);
593                        mr_asprintf(bkpinfo->media_device, "/dev/ht0");
594                        if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
595                            log_msg(3, "I tried lots of devices but none worked.");
596                            mr_free(bkpinfo->media_device);
597                            mr_asprintf(bkpinfo->media_device, "%s", tmp);
598                        }
599                    }
600                }
601            }
602            mr_free(tmp);
603
604            if (!does_file_exist(MINDI_CACHE_REL"/mondorestore.cfg")) {
605                log_to_screen("Cannot find config info on media");
606            }
607        } else {
608            log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
609            mr_asprintf(command, "tar -zxvf "MNT_CDROM"/images/all.tar.gz ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm"); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
610            run_program_and_log_output(command, TRUE);
611            mr_free(command);
612        }
613    }
614    run_program_and_log_output("umount "MNT_CDROM, FALSE);
615    if (!does_file_exist(cfg_file)) {
616        log_it("%s",cfg_file);
617        log_msg(1, "%s not found", cfg_file);
618        log_to_screen("Oh dear. Unable to recover configuration file from boot disk");
619    }
620
621    log_to_screen("Recovered mondorestore.cfg");
622
623    run_program_and_log_output(command, FALSE);
624    mr_free(command);
625
626    mr_asprintf(command, "cp -f etc/raidtab /etc/");
627    run_program_and_log_output(command, FALSE);
628    mr_free(command);
629
630    g_backup_media_type = bkpinfo->backup_media_type;
631}
632
633
634
635/**
636* Fill out @p bkpinfo based on @p cfg_file.
637* @param cfg_file The mondorestore.cfg file to read into @p bkpinfo.
638* @param bkpinfo The backup information structure to fill out with information
639* from @p cfg_file.
640* @return 0 for success, nonzero for failure.
641*/
642int read_cfg_file_into_bkpinfo(char *cfgf)
643{
644/** add mallocs **/
645char *value = NULL;
646char *tmp = NULL;
647char *tmp1 = NULL;
648char *envtmp1 = NULL;
649char *envtmp2 = NULL;
650char *command = NULL;
651char *iso_mnt = NULL;
652char *iso_path = NULL;
653char *old_isodir = NULL;
654char *cfg_file = NULL;
655t_bkptype media_specified_by_user;
656
657//  assert_string_is_neither_NULL_nor_zerolength(cfg_file);
658assert(bkpinfo != NULL);
659assert(cfgf != NULL);
660
661media_specified_by_user = bkpinfo->backup_media_type;   // or 'none', if not specified
662
663if ((value = read_cfg_var(cfg_file, "backup-media-type")) != NULL) {
664    if (!strcmp(value, "cdstream")) {
665        bkpinfo->backup_media_type = cdstream;
666    } else if (!strcmp(value, "cdr")) {
667        bkpinfo->backup_media_type = cdr;
668    } else if (!strcmp(value, "cdrw")) {
669        bkpinfo->backup_media_type = cdrw;
670    } else if (!strcmp(value, "dvd")) {
671        bkpinfo->backup_media_type = dvd;
672    } else if (!strcmp(value, "usb")) {
673        bkpinfo->backup_media_type = usb;
674        bkpinfo->please_dont_eject = TRUE;
675    } else if (!strcmp(value, "iso")) {
676        // Patch by Conor Daly - 2004/07/12
677        bkpinfo->backup_media_type = iso;
678        if (am_I_in_disaster_recovery_mode()) {
679            /* Check to see if CD is already mounted before mounting it... */
680            if (!is_this_device_mounted("/dev/cdrom")) {
681                log_msg(2, "NB: CDROM device not mounted, mounting...");
682                run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
683            }
684            if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
685                bkpinfo->backup_media_type = cdr;
686                run_program_and_log_output("umount "MNT_CDROM, 1);
687                log_it
688                    ("Re-jigging configuration AGAIN. CD-R, not ISO.");
689            }
690        }
691        mr_free(bkpinfo->prefix);
692        mr_free(value);
693        if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
694            mr_asprintf(bkpinfo->prefix, "%s", value);
695        } else {
696            mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
697        }
698    } else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
699        /* Stay compatible with previous versions by allowing nfs as an entry here */
700        bkpinfo->backup_media_type = netfs;
701        bkpinfo->please_dont_eject = TRUE;
702        mr_free(value);
703
704        mr_free(bkpinfo->netfs_proto);
705        if ((value = read_cfg_var(cfg_file, "netfs-proto")) == 0) {
706            mr_asprintf(bkpinfo->netfs_proto, "%s", value);
707        } else {
708            /* For compatibility, force protocol in old nfs case to be transparent */
709            mr_asprintf(bkpinfo->netfs_proto, "nfs");
710        }
711        mr_free(value);
712
713        mr_free(bkpinfo->prefix);
714        if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
715            mr_asprintf(bkpinfo->prefix, "%s", value);
716        } else {
717            mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
718        }
719        mr_free(value);
720   
721        tmp = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
722        if (strstr(tmp, "pxe")) {
723            /* We need to override prefix value in PXE mode as it's
724            * already done in start-netfs */
725            envtmp1 = getenv("imgname");
726            if (envtmp1 == NULL) {
727                fatal_error("no imgname variable in environment");
728            }
729            mr_free(bkpinfo->prefix);
730            mr_asprintf(bkpinfo->prefix, "%s", envtmp1);
731        }
732        mr_free(tmp);
733
734    } else if (!strcmp(value, "tape")) {
735        bkpinfo->backup_media_type = tape;
736    } else if (!strcmp(value, "udev")) {
737        bkpinfo->backup_media_type = udev;
738    } else {
739        fatal_error("UNKNOWN bkp-media-type");
740    }
741} else {
742    fatal_error("backup-media-type not specified!");
743}
744mr_free(value);
745
746if (bkpinfo->disaster_recovery) {
747    if (bkpinfo->backup_media_type == cdstream) {
748        mr_free(bkpinfo->media_device);
749        mr_asprintf(bkpinfo->media_device, "/dev/cdrom");
750        bkpinfo->media_size[0] = 1999 * 1024;
751        bkpinfo->media_size[1] = 650;   /* good guess */
752    } else if (bkpinfo->backup_media_type == usb) {
753        envtmp1 = getenv("MRUSBDEV");
754        if (envtmp1 == NULL) {
755            if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
756                fatal_error("Cannot get USB device name from cfg file");
757            }
758        } else {
759            mr_asprintf(value,"%s", envtmp1);
760        }
761        mr_free(bkpinfo->media_device);
762        mr_asprintf(bkpinfo->media_device, "%s1", value);
763        mr_free(value);
764        log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
765    } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
766        if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
767            fatal_error("Cannot get tape device name from cfg file");
768        }
769        mr_free(bkpinfo->media_device);
770        bkpinfo->media_device = value;
771
772        value = read_cfg_var(cfg_file, "media-size");
773        if (value != NULL) {
774            bkpinfo->media_size[1] = atol(value);
775            mr_free(value);
776        } else {
777            bkpinfo->media_size[1] = 0L;
778        }
779        log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
780    } else {
781        mr_free(bkpinfo->media_device);
782        mr_asprintf(bkpinfo->media_device, "/dev/cdrom");   /* we don't really need this var */
783        bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
784        bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
785        log_msg(2, "Backup medium is CD-R[W]");
786    }
787} else {
788    log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
789}
790
791value = read_cfg_var(cfg_file, "use-star");
792if (value && strstr(value, "yes")) {
793    bkpinfo->use_star = TRUE;
794    log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
795}
796mr_free(value);
797
798value = read_cfg_var(cfg_file, "obdr");
799if (value && strstr(value, "TRUE")) {
800    bkpinfo->use_obdr = TRUE;
801    log_msg(1, "OBDR mode activated");
802}
803mr_free(value);
804
805value = read_cfg_var(cfg_file, "acl");
806if (value && strstr(value, "TRUE")) {
807    mr_asprintf(g_getfacl,"setfacl");
808    log_msg(1, "We will restore ACLs");
809    tmp = find_home_of_exe("setfacl");
810    if (!tmp) {
811        log_msg(1, "Unable to restore ACLs as no setfacl found");
812    }
813    mr_free(tmp);
814}
815mr_free(value);
816
817value = read_cfg_var(cfg_file, "xattr");
818if (value && strstr(value, "TRUE")) {
819    mr_asprintf(g_getfattr,"setfattr");
820    log_msg(1, "We will restore XATTRs");
821    tmp = find_home_of_exe("setfattr");
822    if (!tmp) {
823        log_msg(1, "Unable to restore XATTRs as no setfattr found");
824    }
825    mr_free(tmp);
826}
827mr_free(value);
828
829value = read_cfg_var(cfg_file, "internal-tape-block-size");
830if (value != NULL) {
831    bkpinfo->internal_tape_block_size = atol(value);
832} else {
833    bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
834}
835log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
836mr_free(value);
837
838value = read_cfg_var(cfg_file, "use-lzma");
839if (value && strstr(value, "yes")) {
840    bkpinfo->use_lzma = TRUE;
841    bkpinfo->use_lzo = FALSE;
842    bkpinfo->use_gzip = FALSE;
843    mr_free(bkpinfo->zip_exe);
844    mr_asprintf(bkpinfo->zip_exe, "lzma");
845    mr_free(bkpinfo->zip_suffix);
846    mr_asprintf(bkpinfo->zip_suffix, "lzma");
847}
848mr_free(value);
849
850value = read_cfg_var(cfg_file, "use-lzo");
851if (value && strstr(value, "yes")) {
852    bkpinfo->use_lzma = FALSE;
853    bkpinfo->use_lzo = TRUE;
854    bkpinfo->use_gzip = FALSE;
855    mr_free(bkpinfo->zip_exe);
856    mr_asprintf(bkpinfo->zip_exe, "lzop");
857    mr_free(bkpinfo->zip_suffix);
858    mr_asprintf(bkpinfo->zip_suffix, "lzo");
859}
860mr_free(value);
861
862value = read_cfg_var(cfg_file, "use-gzip");
863if (value && strstr(value, "yes")) {
864    bkpinfo->use_lzma = FALSE;
865    bkpinfo->use_lzo = FALSE;
866    bkpinfo->use_gzip = TRUE;
867    mr_free(bkpinfo->zip_exe);
868    mr_asprintf(bkpinfo->zip_exe, "gzip");
869    mr_free(bkpinfo->zip_suffix);
870    mr_asprintf(bkpinfo->zip_suffix, "gz");
871}
872mr_free(value);
873
874value = read_cfg_var(cfg_file, "use-comp");
875if (value && strstr(value, "yes")) {
876    bkpinfo->use_lzma = FALSE;
877    bkpinfo->use_lzo = FALSE;
878    bkpinfo->use_gzip = FALSE;
879    mr_free(bkpinfo->zip_exe);
880    mr_asprintf(bkpinfo->zip_exe, "bzip2");
881    mr_free(bkpinfo->zip_suffix);
882    mr_asprintf(bkpinfo->zip_suffix, "bz2");
883}
884mr_free(value);
885
886if (bkpinfo->zip_exe == NULL) {
887    mr_asprintf(bkpinfo->zip_exe, "none");
888}
889if (bkpinfo->zip_suffix == NULL) {
890    mr_asprintf(bkpinfo->zip_suffix, "");
891}
892
893value = read_cfg_var(cfg_file, "differential");
894if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
895    bkpinfo->differential = TRUE;
896}
897log_msg(2, "differential var = '%s'", value);
898mr_free(value);
899if (bkpinfo->differential) {
900    log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
901} else {
902    log_msg(2, "This is a regular (full) backup");
903}
904
905tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
906tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
907if (tmp || strstr(tmp1, "donteject")) {
908    bkpinfo->please_dont_eject = TRUE;
909    log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
910}
911mr_free(tmp);
912mr_free(tmp1);
913
914if (bkpinfo->backup_media_type == netfs) {
915    if (!cfgf) {
916        if (bkpinfo->netfs_mount) {
917            log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
918        }
919        if (bkpinfo->netfs_remote_dir) {
920            log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
921        }
922        log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
923    } else {
924        mr_free(bkpinfo->netfs_mount);
925        bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
926
927        mr_free(bkpinfo->netfs_remote_dir);
928        bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
929
930        if (bkpinfo->netfs_mount != NULL) {
931            log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
932        }
933        if (bkpinfo->netfs_remote_dir != NULL) {
934            log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
935        }
936        if (bkpinfo->netfs_proto != NULL) {
937            log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
938        }
939    }
940    tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
941    if (strstr(tmp1, "pxe")) {
942        mr_free(tmp1);
943        /* We need to override values in PXE mode as it's
944        * already done in start-netfs */
945        envtmp1 = getenv("netfsmount");
946        if (envtmp1 == NULL) {
947            fatal_error("no netfsmount variable in environment");
948        }
949        envtmp2 = getenv("dirimg");
950        if (envtmp2 == NULL) {
951            fatal_error("no dirimg variable in environment");
952        }
953        mr_free(bkpinfo->netfs_mount);
954        mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
955
956        mr_free(bkpinfo->netfs_remote_dir);
957        mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
958    } else {
959        mr_free(tmp1);
960    }
961
962} else if (bkpinfo->backup_media_type == iso) {
963    /* Patch by Conor Daly 23-june-2004
964    * to correctly mount iso-dev and set a sensible
965    * isodir in disaster recovery mode
966    */
967    mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
968    iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
969    iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
970    mr_free(bkpinfo->isodir);
971    mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
972    mr_free(iso_mnt);
973
974    if (!bkpinfo->isodir[0]) {
975        mr_free(bkpinfo->isodir);
976        bkpinfo->isodir = old_isodir;
977    } else {
978        mr_free(old_isodir);
979    }
980    if (!bkpinfo->disaster_recovery) {
981        if (strcmp(old_isodir, bkpinfo->isodir)) {
982            log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
983            mr_free(bkpinfo->isodir);
984            bkpinfo->isodir = old_isodir;
985        } else {
986            mr_free(old_isodir);
987        }
988    }
989    mr_free(g_isodir_device);
990    g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
991    log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
992
993    if (bkpinfo->disaster_recovery) {
994        if (is_this_device_mounted(g_isodir_device)) {
995            log_msg(2, "NB: isodir is already mounted");
996            /* Find out where it's mounted */
997            mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
998            log_it("command = %s", command);
999            iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
1000            log_it("res of it = %s", iso_mnt);
1001            mr_free(command);
1002        } else {
1003            mr_asprintf(iso_mnt, "/tmp/isodir");
1004            mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
1005            run_program_and_log_output(tmp1, 5);
1006            mr_free(tmp1);
1007
1008            mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
1009            if (run_program_and_log_output(tmp1, 3)) {
1010                log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
1011                bkpinfo->backup_media_type = cdr;
1012                mr_free(bkpinfo->media_device);
1013                mr_asprintf(bkpinfo->media_device, "/dev/cdrom");   /* superfluous */
1014                if (mount_media()) {
1015                    mr_free(tmp1);
1016                    fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
1017                } else {
1018                    log_msg(1, "You backed up to disk, then burned some CDs.");
1019                }
1020            }
1021            mr_free(tmp1);
1022        }
1023        /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1024        if (bkpinfo->backup_media_type == iso) {
1025            mr_free(bkpinfo->isodir);
1026            mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1027            bkpinfo->isodir = tmp1;
1028        }
1029        mr_free(iso_mnt);
1030    }
1031    mr_free(iso_path);
1032}
1033
1034if (media_specified_by_user != none) {
1035    if (! bkpinfo->disaster_recovery) {
1036        if (bkpinfo->backup_media_type != media_specified_by_user) {
1037            log_msg(2,
1038                    "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1039            interactively_obtain_media_parameters_from_user(FALSE);
1040            media_specified_by_user = bkpinfo->backup_media_type;
1041            get_cfg_file_from_initrd();
1042        }
1043    }
1044    bkpinfo->backup_media_type = media_specified_by_user;
1045}
1046g_backup_media_type = bkpinfo->backup_media_type;
1047paranoid_free(value);
1048return (0);
1049
1050}
1051
1052/**************************************************************************
1053*END_READ_CFG_FILE_INTO_BKPINFO                                          *
1054**************************************************************************/
1055
1056
1057
1058
1059/**
1060 * Allow the user to edit the filelist and biggielist.
1061 * The filelist is unlinked after it is read.
1062 * @param bkpinfo The backup information structure. Fields used:
1063 * - @c bkpinfo->backup_media_type
1064 * - @c bkpinfo->isodir
1065 * - @c bkpinfo->media_device
1066 * - @c bkpinfo->tmpdir
1067 * @return The filelist structure containing the information read from disk.
1068 */
1069struct
1070s_node *process_filelist_and_biggielist()
1071{
1072struct s_node *filelist;
1073
1074char *command = NULL;
1075char *tmp;
1076char *tmp1 = NULL;
1077int res = 0;
1078pid_t pid;
1079
1080assert(bkpinfo != NULL);
1081malloc_string(tmp);
1082
1083    getcwd(tmp, MAX_STR_LEN);
1084    chdir(bkpinfo->tmpdir);
1085    log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1086    log_to_screen("Extracting filelist and biggielist from media...");
1087    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1088        mr_asprintf(command, "tar -b %ld -zxf %s ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm", bkpinfo->internal_tape_block_size, bkpinfo->media_device);
1089        log_msg(1, "tarcommand = %s", command);
1090        run_program_and_log_output(command, 1);
1091        mr_free(command);
1092
1093    } else {
1094        log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1095        insist_on_this_cd_number(1);
1096        log_msg(2, "Back from iotcn");
1097        run_program_and_log_output("mount", 1);
1098        mr_asprintf(command, "tar -zxf "MNT_CDROM"/images/all.tar.gz ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm");
1099
1100        log_msg(1, "tarcommand = %s", command);
1101        run_program_and_log_output(command, 1);
1102        mr_free(command);
1103
1104        if (!does_file_exist(MINDI_CACHE"/biggielist.txt")) {
1105            fatal_error("all.tar.gz did not include "MINDI_CACHE"/biggielist.txt");
1106        }
1107        if (!does_file_exist(MINDI_CACHE"/filelist.full.gz")) {
1108            fatal_error("all.tar.gz did not include "MINDI_CACHE"/filelist.full.gz");
1109        }
1110    }
1111    chdir(tmp);
1112
1113    log_msg(2, "Forking");
1114    pid = fork();
1115    switch (pid) {
1116    case -1:
1117        fatal_error("Forking error");
1118        break;
1119
1120    case 0:
1121        log_to_screen("Pre-processing filelist");
1122        mr_asprintf(command, "grep -E '^/dev/.*' "MINDI_CACHE"/biggielist.txt > %s 2> /dev/null", g_filelist_imagedevs);
1123        paranoid_system(command);
1124        mr_free(command);
1125        exit(0);
1126        break;
1127
1128    default:
1129        open_evalcall_form("Pre-processing filelist");
1130        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1131            usleep(100000);
1132            update_evalcall_form(0);
1133        }
1134    }
1135    close_evalcall_form();
1136
1137    log_msg(3, "loading filelist");
1138    filelist = load_filelist(MINDI_CACHE"/filelist.full.gz");
1139    log_msg(3, "deleting original filelist");
1140    unlink(MINDI_CACHE"/filelist.full.gz");
1141    if (g_text_mode) {
1142        printf("Restore which directory? --> ");
1143        mr_getline(tmp1, stdin);
1144        toggle_path_selection(filelist, tmp1, TRUE);
1145        if (strlen(tmp1) == 0) {
1146            res = 1;
1147        } else {
1148            res = 0;
1149        }
1150        mr_free(tmp1);
1151    } else {
1152        res = edit_filelist(filelist);
1153    }
1154    if (res) {
1155        log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1156        free_filelist(filelist);
1157        return (NULL);
1158    }
1159    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1160    close_evalcall_form();
1161
1162    // NB: It's not necessary to add biggielist.txt to the filelist.full
1163    // file. The filelist.full file already contains the filename of EVERY
1164    // file backed up - regular and biggie files.
1165
1166    // However, we do want to make sure the imagedevs selected by the user
1167    // are flagged for restoring.
1168    if (length_of_file(g_imagedevs_restthese) > 2) {
1169        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1170                                      TRUE);
1171    }
1172
1173    paranoid_free(tmp);
1174    return (filelist);
1175}
1176
1177/**************************************************************************
1178 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1179 **************************************************************************/
1180
1181
1182
1183
1184/**
1185 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1186 * The backup filename is the filename of the original with ".pristine" added.
1187 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1188 * @param filename The filename (absolute path) within @p path_root.
1189 * @return 0 for success, nonzero for failure.
1190 */
1191int backup_crucial_file(char *path_root, char *filename)
1192{
1193    char *tmp = NULL;
1194    char *command = NULL;
1195    int res;
1196
1197    assert(path_root != NULL);
1198    assert_string_is_neither_NULL_nor_zerolength(filename);
1199
1200    mr_asprintf(tmp, "%s/%s", path_root, filename);
1201    mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1202    mr_free(tmp);
1203
1204    res = run_program_and_log_output(command, 5);
1205    mr_free(command);
1206    return (res);
1207}
1208
1209void offer_to_make_initrd() {
1210
1211if (bkpinfo->restore_mode != nuke) {
1212    if (ask_me_yes_or_no
1213        ("You will now be able to re-generate your initrd.\nThis is especially useful if you changed of hardware configuration, cloned, made P2V, used multipath...\nDo you need to do it ?")) {
1214        log_msg(1,"Launching shell for manual initrd recreation");
1215        if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1216            popup_and_OK("You'll now be chrooted under your future / partition.\nEdit /etc/mkinitcpio.conf if needed and rebuild your initrd with the kernel preset name e.g.\nmkinitcpio -p kernel26\nThen type exit to finish.\n");
1217        } else {
1218            popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your initrd with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nThen type exit to finish.");
1219        }
1220        mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1221        if (!g_text_mode) {
1222            newtSuspend();
1223        }
1224        (void)system("chroot " MNT_RESTORING);
1225        if (!g_text_mode) {
1226            newtResume();
1227        }
1228        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1229    } else {
1230        return;
1231    }
1232} else {
1233    log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1234    log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1235}
1236}
1237
1238
1239/**
1240 * Install the user's boot loader in the MBR.
1241 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1242 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1243 * @return 0 for success, nonzero for failure.
1244 */
1245int run_boot_loader(bool offer_to_hack_scripts)
1246{
1247    int res;
1248    int retval = 0;
1249
1250  /** malloc *******/
1251    char *device = NULL;
1252    char *name = NULL;
1253    char *cmd = NULL;
1254
1255    /* In order to have a working bootloader, we need to have all devices
1256     * ready in the chroot. If they are not there (udev) then copy them from
1257     * the current /dev location
1258     */
1259    mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1260    run_program_and_log_output(cmd, 3);
1261    paranoid_free(cmd);
1262
1263    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1264    backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1265    backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1266    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1267    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1268    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1269    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1270    device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.device");
1271    name = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.name");
1272    log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1273    sync();
1274
1275    offer_to_make_initrd();
1276    if (!strcmp(name, "LILO")) {
1277        res = run_lilo(offer_to_hack_scripts);
1278    } else if (!strcmp(name, "ELILO")) {
1279        res = run_elilo(offer_to_hack_scripts);
1280    } else if (!strcmp(name, "GRUB")) {
1281        res = run_grub(offer_to_hack_scripts, device);
1282    } else if (!strcmp(name, "RAW")) {
1283        res = run_raw_mbr(offer_to_hack_scripts, device);
1284    }
1285#ifdef __FreeBSD__
1286    else if (!strcmp(name, "BOOT0")) {
1287        mr_asprintf(tmp, "boot0cfg -B %s", device);
1288        res = run_program_and_log_output(tmp, FALSE);
1289        paranoid_free(tmp);
1290    } else {
1291        mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1292        if (!system(tmp)) {
1293            mr_free(tmp);
1294            mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1295            res = run_program_and_log_output(tmp, 3);
1296        } else {
1297            log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1298        }
1299        mr_free(tmp);
1300    }
1301#else
1302    else {
1303        log_to_screen
1304            ("Unable to determine type of boot loader. Defaulting to LILO.");
1305        res = run_lilo(offer_to_hack_scripts);
1306    }
1307#endif
1308    mr_free(device);
1309    mr_free(name);
1310
1311    retval += res;
1312    if (res) {
1313        log_to_screen("Your boot loader returned an error");
1314    } else {
1315        log_to_screen("Your boot loader ran OK");
1316    }
1317    return (retval);
1318}
1319
1320/**************************************************************************
1321 *END_ RUN_BOOT_LOADER                                                    *
1322 **************************************************************************/
1323
1324
1325
1326/**
1327 * Attempt to find the user's editor.
1328 * @return The editor found ("vi" if none could be found).
1329 * @note The returned string points to static storage that will be overwritten with each call.
1330 */
1331char *find_my_editor(void) {
1332   
1333    char *tmp = NULL;
1334    static char output[MAX_STR_LEN];
1335
1336    tmp = find_home_of_exe("pico");
1337    if (tmp) {
1338        strcpy(output, "pico");
1339    } else { 
1340        mr_free(tmp);
1341        tmp = find_home_of_exe("nano");
1342        if (tmp) {
1343            strcpy(output, "nano");
1344        } else {
1345            mr_free(tmp);
1346            tmp = find_home_of_exe("joe");
1347            if (tmp) {
1348                strcpy(output, "joe");
1349            } else {
1350                strcpy(output, "vi");
1351            }
1352        }
1353    }
1354    mr_free(tmp);
1355
1356    tmp = find_home_of_exe(output);
1357    if (!tmp) {
1358        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1359    }
1360    mr_free(tmp);
1361    return (output);
1362}
1363
1364
1365/**
1366 * Install GRUB on @p bd.
1367 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1368 * @param bd The boot device where GRUB is installed.
1369 * @return 0 for success, nonzero for failure.
1370 */
1371int run_grub(bool offer_to_run_stabgrub, char *bd)
1372{
1373  /** malloc **/
1374    char *command = NULL;
1375    char *boot_device = NULL;
1376    char *tmp = NULL;
1377    char *editor = NULL;
1378    char *p = NULL;
1379
1380    int res = 0;
1381    bool done;
1382
1383    assert_string_is_neither_NULL_nor_zerolength(bd);
1384    mr_asprintf(boot_device, "%s", bd);
1385
1386    if (offer_to_run_stabgrub
1387        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1388        /* interactive mode */
1389        mvaddstr_and_log_it(g_currentY,
1390                            0,
1391                            "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB...                             ");
1392        for (done = FALSE; !done;) {
1393            p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1394            if (p == NULL) {
1395                done = TRUE;
1396                mr_free(p);
1397                /* we want some warnings later on */
1398                res = 1;
1399                continue;
1400            }
1401            mr_asprintf(command, "stabgrub-me %s", p);
1402            mr_free(p);
1403
1404            res = run_program_and_log_output(command, 1);
1405            mr_free(command);
1406
1407            if (res) {
1408                popup_and_OK
1409                    ("GRUB installation failed. Please install manually using 'grub-install' or similar command. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1410                newtSuspend();
1411                system("chroot " MNT_RESTORING);
1412                newtResume();
1413                popup_and_OK("Thank you.");
1414            } else {
1415                done = TRUE;
1416            }
1417            popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
1418            if (!g_text_mode) {
1419                newtSuspend();
1420            }
1421            mr_asprintf(editor, "%s", find_my_editor());
1422
1423            mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1424            paranoid_system(tmp);
1425            mr_free(tmp);
1426
1427            mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1428            paranoid_system(tmp);
1429            mr_free(tmp);
1430
1431            if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1432                mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1433            } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1434                mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1435            }
1436            paranoid_system(tmp);
1437            mr_free(tmp);
1438
1439            mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1440            paranoid_system(tmp);
1441            mr_free(tmp);
1442            mr_free(editor);
1443
1444            if (!g_text_mode) {
1445                newtResume();
1446            }
1447        }
1448    } else {
1449        /* nuke mode */
1450        if (!run_program_and_log_output("which grub-MR", FALSE)) {
1451            log_msg(1, "Yay! grub-MR found...");
1452            mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1453            log_msg(1, "command = %s", command);
1454        } else {
1455            mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
1456            log_msg(1, "WARNING - grub-MR not found; using grub-install");
1457        }
1458        mvaddstr_and_log_it(g_currentY,
1459                            0,
1460                            "Running GRUB...                                                 ");
1461        log_it("%s",command);
1462        res = run_program_and_log_output(command, 1);
1463        mr_free(command);
1464
1465        if (res) {
1466            popup_and_OK
1467                ("Because of bugs in GRUB's own installer, GRUB was not installed properly. Please install the boot loader manually now, using this chroot()'ed shell prompt. Type 'exit' when you have finished.");
1468            newtSuspend();
1469            system("chroot " MNT_RESTORING);
1470            newtResume();
1471            popup_and_OK("Thank you.");
1472        }
1473    }
1474    mr_free(boot_device);
1475
1476    if (res) {
1477        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1478        log_to_screen
1479            ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1480        log_msg(1, "Type:-");
1481        log_msg(1, "    mount-me");
1482        log_msg(1, "    chroot " MNT_RESTORING);
1483        log_msg(1, "    mount /boot");
1484        log_msg(1, "    grub-install '(hd0)'");
1485        log_msg(1, "    exit");
1486        log_msg(1, "    unmount-me");
1487        log_msg(1,
1488                "If you're really stuck, please e-mail the mailing list.");
1489    } else {
1490        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1491    }
1492
1493    return (res);
1494}
1495
1496/**************************************************************************
1497 *END_RUN_GRUB                                                            *
1498 **************************************************************************/
1499
1500
1501/**
1502 * Install ELILO on the user's boot drive (determined by elilo.conf).
1503 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1504 * @return 0 for success, nonzero for failure.
1505 */
1506int run_elilo(bool offer_to_run_stabelilo)
1507{
1508  /** malloc **/
1509    char *command = NULL;
1510    char *tmp = NULL;
1511    char *editor = NULL;
1512
1513    int res;
1514    int done;
1515
1516    if (offer_to_run_stabelilo
1517        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1518
1519        /* interactive mode */
1520    {
1521        mvaddstr_and_log_it(g_currentY,
1522                            0,
1523                            "Modifying fstab and elilo.conf...                             ");
1524        mr_asprintf(command, "stabelilo-me");
1525        res = run_program_and_log_output(command, 3);
1526        mr_free(command);
1527
1528        if (res) {
1529            popup_and_OK
1530                ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1531            for (done = FALSE; !done;) {
1532                if (!g_text_mode) {
1533                    newtSuspend();
1534                }
1535                mr_asprintf(editor, "%s", find_my_editor());
1536
1537                mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1538                paranoid_system(tmp);
1539                mr_free(tmp);
1540
1541                mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1542                paranoid_system(tmp);
1543                mr_free(tmp);
1544
1545                mr_free(editor);
1546
1547                if (!g_text_mode) {
1548                    newtResume();
1549                }
1550//              newtCls();
1551                if (ask_me_yes_or_no("Edit them again?")) {
1552                    continue;
1553                }
1554                done = TRUE;
1555            }
1556        } else {
1557            log_to_screen("elilo.conf and fstab were modified OK");
1558        }
1559    } else
1560        /* nuke mode */
1561    {
1562        res = TRUE;
1563    }
1564    return (res);
1565}
1566
1567/**************************************************************************
1568 *END_RUN_ELILO                                                            *
1569 **************************************************************************/
1570
1571
1572/**
1573 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1574 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1575 * @return 0 for success, nonzero for failure.
1576 */
1577int run_lilo(bool offer_to_run_stablilo)
1578{
1579  /** malloc **/
1580    char *command = NULL;
1581    char *tmp = NULL;
1582    char *editor = NULL;
1583
1584    int res;
1585    int done;
1586    bool run_lilo_M = FALSE;
1587
1588    if (!run_program_and_log_output
1589        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1590        run_lilo_M = TRUE;
1591    }
1592
1593    if (offer_to_run_stablilo
1594        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1595
1596        /* interactive mode */
1597    {
1598        mvaddstr_and_log_it(g_currentY,
1599                            0,
1600                            "Modifying fstab and lilo.conf, and running LILO...                             ");
1601        mr_asprintf(command, "stablilo-me");
1602        res = run_program_and_log_output(command, 3);
1603        mr_free(command);
1604
1605        if (res) {
1606            popup_and_OK
1607                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1608            for (done = FALSE; !done;) {
1609                if (!g_text_mode) {
1610                    newtSuspend();
1611                }
1612                mr_asprintf(editor, "%s", find_my_editor());
1613
1614                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1615                paranoid_system(tmp);
1616                mr_free(tmp);
1617
1618                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1619                paranoid_system(tmp);
1620                mr_free(tmp);
1621
1622                mr_free(editor);
1623
1624                if (!g_text_mode) {
1625                    newtResume();
1626                }
1627//              newtCls();
1628                if (ask_me_yes_or_no("Edit them again?")) {
1629                    continue;
1630                }
1631                res =
1632                    run_program_and_log_output("chroot " MNT_RESTORING
1633                                               " lilo -L", 3);
1634                if (res) {
1635                    res =
1636                        run_program_and_log_output("chroot " MNT_RESTORING
1637                                                   " lilo", 3);
1638                }
1639                if (res) {
1640                    done =
1641                        ask_me_yes_or_no
1642                        ("LILO failed. Re-edit system files?");
1643                } else {
1644                    done = TRUE;
1645                }
1646            }
1647        } else {
1648            log_to_screen("lilo.conf and fstab were modified OK");
1649        }
1650    } else
1651        /* nuke mode */
1652    {
1653        mvaddstr_and_log_it(g_currentY,
1654                            0,
1655                            "Running LILO...                                                 ");
1656        res =
1657            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1658                                       3);
1659        if (res) {
1660            res =
1661                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1662                                           3);
1663        }
1664        if (res) {
1665            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1666            log_to_screen
1667                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1668        } else {
1669            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1670        }
1671    }
1672    if (run_lilo_M) {
1673        run_program_and_log_output("chroot " MNT_RESTORING
1674                                   " lilo -M /dev/hda", 3);
1675        run_program_and_log_output("chroot " MNT_RESTORING
1676                                   " lilo -M /dev/sda", 3);
1677    }
1678    return (res);
1679}
1680
1681/**************************************************************************
1682 *END_RUN_LILO                                                            *
1683 **************************************************************************/
1684
1685
1686/**
1687 * Install a raw MBR onto @p bd.
1688 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1689 * @param bd The device to copy the stored MBR to.
1690 * @return 0 for success, nonzero for failure.
1691 */
1692int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1693{
1694  /** malloc **/
1695    char *command = NULL;
1696    char *boot_device = NULL;
1697    char *tmp = NULL;
1698    char *editor;
1699    char *p = NULL;
1700    int res;
1701    int done;
1702
1703    assert_string_is_neither_NULL_nor_zerolength(bd);
1704
1705    mr_asprintf(boot_device, "%s", bd);
1706
1707    if (offer_to_hack_scripts
1708        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1709        /* interactive mode */
1710        mvaddstr_and_log_it(g_currentY, 0,
1711                            "Modifying fstab and restoring MBR...                           ");
1712        for (done = FALSE; !done;) {
1713            if (!run_program_and_log_output("which vi", FALSE)) {
1714                popup_and_OK("You will now edit fstab");
1715                if (!g_text_mode) {
1716                    newtSuspend();
1717                }
1718                mr_asprintf(editor, "%s", find_my_editor());
1719                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1720                mr_free(editor);
1721
1722                paranoid_system(tmp);
1723                mr_free(tmp);
1724                if (!g_text_mode) {
1725                    newtResume();
1726                }
1727            }
1728            p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1729            if (p == NULL) {
1730                done = TRUE;
1731                mr_free(p);
1732                /* we want some warnings later on */
1733                res = 1;
1734                continue;
1735            }
1736            mr_asprintf(command, "stabraw-me %s", p);
1737            mr_free(p);
1738
1739            res = run_program_and_log_output(command, 3);
1740            mr_free(command);
1741
1742            if (res) {
1743                done = ask_me_yes_or_no("Modifications failed. Re-try?");
1744            } else {
1745                done = TRUE;
1746            }
1747        }
1748    } else {
1749        /* nuke mode */
1750        mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1751        log_msg(2, "run_raw_mbr() --- command='%s'", command);
1752
1753        mvaddstr_and_log_it(g_currentY, 0,
1754                            "Restoring MBR...                                               ");
1755        res = run_program_and_log_output(command, 3);
1756        mr_free(command);
1757    }
1758    mr_free(boot_device);
1759
1760    if (res) {
1761        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1762        log_to_screen
1763            ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1764    } else {
1765        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1766    }
1767    return (res);
1768}
1769
1770/**************************************************************************
1771 *END_RUN_RAW_MBR                                                         *
1772 **************************************************************************/
1773
1774
1775
1776/**
1777 * malloc() and set sensible defaults for the mondorestore filename variables.
1778 * @param bkpinfo The backup information structure. Fields used:
1779 * - @c bkpinfo->tmpdir
1780 * - @c bkpinfo->disaster_recovery
1781 */
1782void setup_MR_global_filenames()
1783{
1784    assert(bkpinfo != NULL);
1785
1786    malloc_string(g_filelist_imagedevs);
1787    malloc_string(g_imagedevs_restthese);
1788    malloc_string(g_mondo_home);
1789
1790    sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1791    sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
1792    if (! bkpinfo->disaster_recovery) {
1793        /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
1794        get_cfg_file_from_initrd();
1795    }
1796}
1797
1798/**************************************************************************
1799 *END_SET_GLOBAL_FILENAME                                                 *
1800 **************************************************************************/
1801
1802
1803/**
1804 * Copy @p input_file (containing the result of a compare) to @p output_file,
1805 * deleting spurious "changes" along the way.
1806 * @param output_file The output file to write with spurious changes removed.
1807 * @param input_file The input file, a list of changed files created by a compare.
1808 */
1809void streamline_changes_file(char *output_file, char *input_file)
1810{
1811    FILE *fin;
1812    FILE *fout;
1813    char *incoming = NULL;
1814
1815    assert_string_is_neither_NULL_nor_zerolength(output_file);
1816    assert_string_is_neither_NULL_nor_zerolength(input_file);
1817
1818    if (!(fin = fopen(input_file, "r"))) {
1819        log_OS_error(input_file);
1820        return;
1821    }
1822    if (!(fout = fopen(output_file, "w"))) {
1823        fatal_error("cannot open output_file");
1824    }
1825    for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1826        if (strncmp(incoming, "etc/adjtime", 11)
1827            && strncmp(incoming, "etc/mtab", 8)
1828            && strncmp(incoming, "tmp/", 4)
1829            && strncmp(incoming, "boot/map", 8)
1830            && !strstr(incoming, "incheckentry")
1831            && strncmp(incoming, "etc/mail/statistics", 19)
1832            && strncmp(incoming, "var/", 4))
1833            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
1834        mr_free(incoming);
1835    }
1836    mr_free(incoming);
1837    paranoid_fclose(fout);
1838    paranoid_fclose(fin);
1839}
1840
1841/**************************************************************************
1842 *END_STREAMLINE_CHANGES_FILE                                             *
1843 **************************************************************************/
1844
1845
1846/**
1847 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1848 */
1849void twenty_seconds_til_yikes()
1850{
1851    int i;
1852    /* MALLOC * */
1853    char *tmp = NULL;
1854
1855    if (does_file_exist("/tmp/NOPAUSE")) {
1856        return;
1857    }
1858    open_progress_form("CAUTION",
1859                       "Be advised: I am about to ERASE your hard disk(s)!",
1860                       "You may press Ctrl+Alt+Del to abort safely.",
1861                       "", 20);
1862    for (i = 0; i < 20; i++) {
1863        g_current_progress = i;
1864        mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1865        update_progress_form(tmp);
1866        mr_free(tmp);
1867        sleep(1);
1868    }
1869    close_progress_form();
1870}
1871
1872/**************************************************************************
1873 *END_TWENTY_SECONDS_TIL_YIKES                                            *
1874 **************************************************************************/
1875
1876
1877/**
1878 * Unmount all devices in @p p_external_copy_of_mountlist.
1879 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1880 * @return 0 for success, nonzero for failure.
1881 */
1882int unmount_all_devices(struct mountlist_itself
1883                        *p_external_copy_of_mountlist)
1884{
1885    struct mountlist_itself *mountlist;
1886    int retval = 0, lino, res = 0, i;
1887    char *command = NULL;
1888    char *tmp = NULL;
1889
1890    assert(p_external_copy_of_mountlist != NULL);
1891
1892    mountlist = malloc(sizeof(struct mountlist_itself));
1893    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1894           sizeof(struct mountlist_itself));
1895    sort_mountlist_by_mountpoint(mountlist, 0);
1896
1897    run_program_and_log_output("df -m -P", 3);
1898    mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices      ");
1899    open_progress_form("Unmounting devices",
1900                       "Unmounting all devices that were mounted,",
1901                       "in preparation for the post-restoration reboot.",
1902                       "", mountlist->entries);
1903    chdir("/");
1904    for (i = 0;
1905         i < 10
1906         &&
1907         run_program_and_log_output
1908         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1909         i++) {
1910        sleep(1);
1911        log_msg(2, "Waiting for buffer() to finish");
1912    }
1913
1914    sync();
1915
1916    mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1917    if (run_program_and_log_output(tmp, FALSE)) {
1918        log_msg(1,
1919                "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1920    }
1921    paranoid_free(tmp);
1922    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1923        run_program_and_log_output("mkdir -p " MNT_RESTORING
1924                                   "/mnt/.boot.d", 5);
1925    }
1926
1927    /* Unmounting the local /proc and /sys first */
1928    run_program_and_log_output("umount " MNT_RESTORING "/proc",3);
1929    run_program_and_log_output("umount " MNT_RESTORING "/sys",3);
1930
1931    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1932        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1933            continue;
1934        }
1935        mr_asprintf(tmp, "Unmounting device %s  ", mountlist->el[lino].device);
1936        update_progress_form(tmp);
1937
1938        if (is_this_device_mounted(mountlist->el[lino].device)) {
1939            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
1940                mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
1941            } else {
1942                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
1943                    mr_asprintf(command, "umount %s/", MNT_RESTORING);
1944                    log_msg(3,
1945                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1946                } else {
1947                    mr_asprintf(command, "umount " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
1948
1949                    /* To support latest Ubuntu where /var is a separate FS
1950                     * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
1951                     * we need to create some dirs under the real / before unmounting it */
1952                    if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
1953                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
1954                        run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
1955                    }
1956                }
1957            }
1958            log_msg(10, "The 'umount' command is '%s'", command);
1959            res = run_program_and_log_output(command, 3);
1960            mr_free(command);
1961        } else {
1962            mr_strcat(tmp, "...not mounted anyway :-) OK");
1963            res = 0;
1964        }
1965        g_current_progress++;
1966        if (res) {
1967            mr_strcat(tmp, "...Failed");
1968            retval++;
1969            log_to_screen(tmp);
1970        } else {
1971            log_msg(2, tmp);
1972        }
1973        paranoid_free(tmp);
1974    }
1975    close_progress_form();
1976    if (retval) {
1977        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1978    } else {
1979        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1980    }
1981    if (retval) {
1982        log_to_screen("Unable to unmount some of your partitions.");
1983    } else {
1984        log_to_screen("All partitions were unmounted OK.");
1985    }
1986    free(mountlist);
1987    return (retval);
1988}
1989
1990/**************************************************************************
1991 *END_UNMOUNT_ALL_DEVICES                                                 *
1992 **************************************************************************/
1993
1994
1995
1996/**************************************************************************
1997 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
1998 **************************************************************************/
1999
2000/* @} - end restoreUtilityGroup */
2001
2002void wait_until_software_raids_are_prepped(char *mdstat_file,
2003                                           int wait_for_percentage)
2004{
2005    struct raidlist_itself *raidlist;
2006    int unfinished_mdstat_devices = 9999, i;
2007    char *screen_message = NULL;
2008
2009    raidlist = malloc(sizeof(struct raidlist_itself));
2010
2011    assert(wait_for_percentage <= 100);
2012    log_it("wait_until_software_raids_are_prepped");
2013    while (unfinished_mdstat_devices > 0) {
2014            // FIXME: Prefix '/dev/' should really be dynamic!
2015        if (parse_mdstat(raidlist, "/dev/")) {
2016            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2017            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2018            return;
2019        }
2020        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2021            if (raidlist->el[i].progress < wait_for_percentage) {
2022                unfinished_mdstat_devices++;
2023                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2024                {
2025                    continue;
2026                }
2027                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2028                mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2029                open_evalcall_form(screen_message);
2030                mr_free(screen_message);
2031
2032                while (raidlist->el[i].progress < wait_for_percentage) {
2033                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2034                    update_evalcall_form(raidlist->el[i].progress);
2035                    sleep(2);
2036                    // FIXME: Prefix '/dev/' should really be dynamic!
2037                    if (parse_mdstat(raidlist, "/dev/")) {
2038                        break;
2039                    }
2040                }
2041                close_evalcall_form();
2042            }
2043        }
2044    }
2045    paranoid_free(raidlist);
2046}
2047
2048
Note: See TracBrowser for help on using the repository browser.