source: MondoRescue/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, 13 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
RevLine 
[1]1/***************************************************************************
[2029]2$Id: mondo-rstr-tools.c 2816 2011-04-29 13:42:55Z bruno $
[1242]3***************************************************************************/
[1]4
5#include <pthread.h>
[1846]6#include <linux/fd.h>
[1930]7#include "my-stuff.h"
[2211]8#include "mr_mem.h"
[2382]9#include "mr_str.h"
[1]10#include "../common/mondostructures.h"
11#include "../common/libmondo.h"
12#include "mr-externs.h"
13#include "mondo-rstr-tools.h"
14
[128]15extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
[1]16extern bool g_I_have_just_nuked;
[2030]17/*
[1]18extern char *g_tmpfs_mountpt;
[2030]19*/
[1]20extern char *g_isodir_device;
21extern long g_current_progress, g_maximum_progress;
[128]22extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the
[1242]23 // user chooses them
[128]24extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which
[1242]25 // were archived as images, not just /dev entries
26 // ... e.g. NTFS, BeOS partitions
[128]27extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
[1242]28 // restore only these
[128]29extern char *g_mondo_home; // homedir of Mondo; usually /usr/local/share/mondo
[1]30
31extern t_bkptype g_backup_media_type;
32
33extern int g_partition_table_locked_up;
[1316]34extern char *MONDO_LOGFILE;
[1]35
[1645]36/* Reference to global bkpinfo */
37extern struct s_bkpinfo *bkpinfo;
38
[949]39/* Should we use or not extended attributes and acl when restoring */
40char *g_getfattr = NULL;
41char *g_getfacl = NULL;
42
[1850]43extern void kill_anything_like_this(char *str);
[1968]44extern int skip_obdr(void);
[2696]45extern int mount_media();
[2022]46extern int set_tape_block_size_with_mt(long internal_tape_block_size);
[1850]47
[1]48/**
[1242]49* @addtogroup restoreUtilityGroup
50* @{
51*/
[1]52/**
[1242]53* Free the malloc()s for the filename variables.
54*/
[1967]55void free_MR_global_filenames(void)
[1]56{
[1242]57paranoid_free(g_filelist_imagedevs);
58paranoid_free(g_imagedevs_restthese);
59paranoid_free(g_mondo_home);
[2030]60/*
[1242]61paranoid_free(g_tmpfs_mountpt);
[2030]62*/
[2325]63mr_free(g_isodir_device);
[1]64
65}
66
67
68
69/**
[1242]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*/
[2357]76void ask_about_these_imagedevs(char *infname, char *outfname) {
77
[1242]78FILE *fin;
79FILE *fout;
[2357]80char *incoming = NULL;
81char *question = NULL;
[1]82
[1242]83assert_string_is_neither_NULL_nor_zerolength(infname);
84assert_string_is_neither_NULL_nor_zerolength(outfname);
[1]85
[1242]86if (!(fin = fopen(infname, "r"))) {
[2357]87 fatal_error("Cannot openin infname");
[1242]88}
89if (!(fout = fopen(outfname, "w"))) {
[2357]90 fatal_error("Cannot openin outfname");
[1242]91}
[2357]92for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
93 mr_strip_spaces(incoming);
[1]94
[2357]95 if (incoming[0] == '\0') {
96 mr_free(incoming);
97 continue;
98 }
[1]99
[2357]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);
[1242]106}
[2357]107mr_free(incoming);
108mr_free(question);
[1242]109paranoid_fclose(fout);
110paranoid_fclose(fin);
[1]111}
112
113/**************************************************************************
[1242]114*ASK_ABOUT_THESE_IMAGEDEVS *
115**************************************************************************/
[1]116
117/**
[1242]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*/
[128]124bool is_file_in_list(char *f, char *list_fname, char *preamble)
[1]125{
126
[2280]127char *command = NULL;
[2334]128char *file = NULL;
129char *tmp = NULL;
[1242]130int res;
[1]131
[1242]132assert_string_is_neither_NULL_nor_zerolength(f);
133assert_string_is_neither_NULL_nor_zerolength(list_fname);
134assert(preamble != NULL);
[1]135
[1242]136if (strncmp(preamble, f, strlen(preamble)) == 0) {
[2334]137 mr_asprintf(file, "%s", f + strlen(preamble));
[1242]138} else {
[2334]139 mr_asprintf(file, "%s", f);
[1]140}
[1242]141if (file[0] == '/' && file[1] == '/') {
[2334]142 mr_asprintf(tmp, "%s", file);
143 mr_free(file);
144
145 mr_asprintf(file, "%s", tmp + 1);
146 mr_free(tmp);
[1242]147}
[2280]148log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
[2323]149mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
[2334]150mr_free(file);
151
[1242]152res = run_program_and_log_output(command, FALSE);
[2282]153mr_free(command);
[1242]154if (res) {
[2280]155 return (FALSE);
[1242]156} else {
[2280]157 return (TRUE);
[1242]158}
159}
[128]160
[1]161/**************************************************************************
[1242]162*END_IS_FILE_IN_LIST *
163**************************************************************************/
[1]164
165
166
167/**
[1242]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*/
[1645]176int iso_fiddly_bits(bool nuke_me_please)
[1]177{
[2280]178 char *mount_isodir_command = NULL;
179 char *command = NULL;
180 char *mds = NULL;
181 int retval = 0, i;
182 bool already_mounted = FALSE;
[2316]183 char *isodir_format = NULL;
[1]184
[1242]185g_ISO_restore_mode = TRUE;
[2325]186mr_free(g_isodir_device);
[2623]187g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
[1242]188if (bkpinfo->disaster_recovery) {
[2211]189 /* Patch Conor Daly 26-june-2004
190 * Don't let this clobber an existing bkpinfo->isodir */
191 if (!bkpinfo->isodir[0]) {
[2323]192 mr_free(bkpinfo->isodir);
[2324]193 mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
[2211]194 }
195 /* End patch */
[2323]196 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
[2211]197 run_program_and_log_output(command, 5);
[2280]198 mr_free(command);
[2211]199 log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
[1242]200}
[1]201
[2325]202/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
[2816]203if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
[2316]204 mr_free(isodir_format);
[2211]205 return (1);
[1242]206}
[2623]207paranoid_system("umount "MNT_CDROM" 2> /dev/null"); /* just in case */
[1]208
[1242]209if (is_this_device_mounted(g_isodir_device)) {
[2211]210 log_to_screen("WARNING - isodir is already mounted");
211 already_mounted = TRUE;
[1242]212} else {
[2323]213 mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
[2316]214 if (isodir_format) {
215 mr_strcat(mount_isodir_command, " -t %s", isodir_format);
[2211]216 }
[2316]217
[2211]218 mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
[2351]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);
[2211]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
[1242]228 ("I have mounted the device where the ISO files are stored.");
229}
[2316]230mr_free(isodir_format);
231
[1242]232if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
[1736]233 mount_media();
[1242]234}
[1736]235i = what_number_cd_is_this(); /* has the side-effect of calling mount_media() */
[2242]236mds = media_descriptor_string(bkpinfo->backup_media_type);
237mr_free(mds);
238
[2280]239log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
[1242]240if (i < 0) {
[2323]241 popup_and_OK("Cannot find ISO images in the directory you specified.");
242 retval = 1;
[1242]243}
[2323]244log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
[1242]245return (retval);
246}
[1]247
248
249
250
251/**
[1242]252* Kill all Petris processes.
253*/
[1850]254void kill_petris(void) {
[1852]255 kill_anything_like_this("petris");
[1]256}
[128]257
[1]258/**************************************************************************
[1242]259*END_KILL_PETRIS *
260**************************************************************************/
[1]261
262
263/**
[1843]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 */
[1771]271int mount_device(char *device, char *mpt, char *format, bool writeable)
272{
273int res = 0;
274
275/** malloc **/
[2280]276char *tmp = NULL;
277char *command = NULL;
278char *mountdir = NULL;
279char *mountpoint = NULL;
[2211]280char *additional_parameters = NULL;
[1771]281
282assert_string_is_neither_NULL_nor_zerolength(device);
283assert_string_is_neither_NULL_nor_zerolength(mpt);
284assert(format != NULL);
285
[1843]286 if (!strcmp(mpt, "/1")) {
[2323]287 mr_asprintf(mountpoint, "/");
[1843]288 log_msg(3, "Mommm! SME is being a dildo!");
289 } else {
[2323]290 mr_asprintf(mountpoint, "%s", mpt);
[1843]291 }
[1771]292
[1843]293 if (!strcmp(mountpoint, "lvm")) {
294 return (0);
295 }
296 if (!strcmp(mountpoint, "image")) {
297 return (0);
298 }
[2323]299 mr_asprintf(tmp, "Mounting device %s ", device);
[1843]300 log_msg(1, tmp);
[1937]301 /* Deal with additional params only if not /proc or /sys */
[2323]302 mr_asprintf(additional_parameters, "");
[1937]303 if (strcmp(format, "proc") && strcmp(format, "sys")) {
304 if (writeable) {
[2211]305 mr_strcat(additional_parameters, "-o rw");
[1937]306 } else {
[2211]307 mr_strcat(additional_parameters, "-o ro");
[1937]308 }
[2331]309 tmp = find_home_of_exe("setfattr");
310 if (tmp) {
[2211]311 mr_strcat(additional_parameters, ",user_xattr");
[1937]312 }
[2331]313 mr_free(tmp);
314
315 tmp = find_home_of_exe("setfacl");
316 if (tmp) {
[2211]317 mr_strcat(additional_parameters, ",acl");
[1937]318 }
[2331]319 mr_free(tmp);
[1843]320 }
[1771]321
322 if (!strcmp(mountpoint, "swap")) {
[2323]323 mr_asprintf(command, "swapon %s", device);
324 mr_asprintf(mountdir, "swap");
[1771]325 } else {
[1843]326 if (!strcmp(mountpoint, "/")) {
[2323]327 mr_asprintf(mountdir, "%s", MNT_RESTORING);
[1843]328 } else {
[2323]329 mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
[1843]330 }
[2323]331 mr_asprintf(command, "mkdir -p %s", mountdir);
[1843]332 run_program_and_log_output(command, FALSE);
[2280]333 mr_free(command);
334
[2323]335 mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
[1843]336 log_msg(2, "command='%s'", command);
337 }
[2280]338 mr_free(additional_parameters);
[1843]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");
[2280]343 mr_free(command);
[2323]344 mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
[1771]345 res = run_program_and_log_output(command, TRUE);
[1843]346 }
347 if (res) {
[2334]348 log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
[1843]349 log_msg(1, "command was '%s'", command);
350 if (!strcmp(mountpoint, "swap")) {
351 log_to_screen(tmp);
[1771]352 } else {
[1843]353 log_msg(2, "Retrying w/o the '-t' switch");
[2280]354 mr_free(command);
[2323]355 mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
[1843]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 }
[1771]364 }
365 }
366
[1843]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
[2280]373mr_free(tmp);
374mr_free(command);
375mr_free(mountdir);
376mr_free(mountpoint);
[1771]377
[1843]378 return (res);
[1771]379}
380/**************************************************************************
[1843]381 *END_MOUNT_DEVICE *
[1771]382**************************************************************************/
383
384
385/**
[1843]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 */
[2351]391int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
[1]392{
[1242]393int retval = 0, lino, res;
[2280]394char *tmp = NULL;
[2211]395char *these_failed = NULL;
396struct mountlist_itself *mountlist = NULL;
[1]397
[1242]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));
[1843]402 sort_mountlist_by_mountpoint(mountlist, 0);
[1]403
404
[1843]405 mvaddstr_and_log_it(g_currentY, 0, "Mounting devices ");
[2351]406 open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
[128]407
[2323]408 mr_asprintf(these_failed, "");
[1843]409 for (lino = 0; lino < mountlist->entries; lino++) {
410 if (!strcmp(mountlist->el[lino].device, "/proc")) {
[2351]411 log_msg(1, "Again with the /proc - why is this in your mountlist?");
[1843]412 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
[2324]413 log_to_screen("%s is already mounted", mountlist->el[lino].device);
[1843]414 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
[1242]415 && strcmp(mountlist->el[lino].mountpoint, "lvm")
416 && strcmp(mountlist->el[lino].mountpoint, "raid")
417 && strcmp(mountlist->el[lino].mountpoint, "image")) {
[2323]418 mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
[1843]419 update_progress_form(tmp);
[2280]420 mr_free(tmp);
[2334]421 res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
422
[1843]423 retval += res;
424 if (res) {
[2211]425 mr_strcat(these_failed, "%s ",mountlist->el[lino].device);
[1843]426 }
427 }
428 g_current_progress++;
[1]429 }
[1843]430 close_progress_form();
431 if (retval) {
432 if (g_partition_table_locked_up > 0) {
[2351]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.");
[1843]436 }
[2323]437 mr_asprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed);
[1843]438
439 if (!ask_me_yes_or_no(tmp)) {
440 retval = 0;
[2351]441 log_to_screen("Continuing, although some device(s) failed to be mounted");
[1843]442 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
443 } else {
444 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
[2351]445 log_to_screen("Unable to mount some or all of your partitions.");
[1843]446 }
[2280]447 mr_free(tmp);
[1843]448 } else {
449 log_to_screen("All partitions were mounted OK.");
450 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
451 }
[2211]452 paranoid_free(these_failed);
453
[1937]454 /* Also mounting under MNT_RESTORING special FS */
455 (void)mount_device("/proc","/proc","proc",TRUE);
456 (void)mount_device("/sys","/sys","sysfs",TRUE);
[2351]457 run_program_and_log_output("df -m -P", 3);
[1843]458 paranoid_free(mountlist);
459 return (retval);
[1242]460}
461/**************************************************************************
462*END_MOUNT_ALL_DEVICES *
463**************************************************************************/
[1]464
465
466/**
[1242]467* Fix some miscellaneous things in the filesystem so the system will come
468* up correctly on the first boot.
469*/
[128]470void protect_against_braindead_sysadmins()
[1]471{
[1242]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);
[1]479}
[1242]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}
[128]492
[1]493/**************************************************************************
[1242]494*END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS *
495**************************************************************************/
[1]496
497
[2623]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;
[1]508
[2623]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 }
[1]515
[2623]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
[1]526/**
[2623]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 */
[2644]535void get_cfg_file_from_initrd()
[2623]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/**
[1242]636* Fill out @p bkpinfo based on @p cfg_file.
[2462]637* @param cfg_file The mondorestore.cfg file to read into @p bkpinfo.
[1242]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*/
[1645]642int read_cfg_file_into_bkpinfo(char *cfgf)
[1]643{
[1242]644/** add mallocs **/
645char *value = NULL;
646char *tmp = NULL;
[2280]647char *tmp1 = NULL;
[1242]648char *envtmp1 = NULL;
649char *envtmp2 = NULL;
650char *command = NULL;
651char *iso_mnt = NULL;
652char *iso_path = NULL;
653char *old_isodir = NULL;
[2334]654char *cfg_file = NULL;
[1242]655t_bkptype media_specified_by_user;
[1]656
657// assert_string_is_neither_NULL_nor_zerolength(cfg_file);
[1242]658assert(bkpinfo != NULL);
[2623]659assert(cfgf != NULL);
[1]660
[1242]661media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
[1]662
[2607]663if ((value = read_cfg_var(cfg_file, "backup-media-type")) != NULL) {
[2325]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...");
[2623]682 run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
[2325]683 }
[2623]684 if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
[2325]685 bkpinfo->backup_media_type = cdr;
[2623]686 run_program_and_log_output("umount "MNT_CDROM, 1);
[2325]687 log_it
688 ("Re-jigging configuration AGAIN. CD-R, not ISO.");
689 }
[128]690 }
[2325]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);
[1242]697 }
[2389]698 } else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
699 /* Stay compatible with previous versions by allowing nfs as an entry here */
[2382]700 bkpinfo->backup_media_type = netfs;
[2325]701 bkpinfo->please_dont_eject = TRUE;
[2404]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
[2325]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 }
[2404]719 mr_free(value);
[2325]720
[2704]721 tmp = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
[2383]722 if (strstr(tmp, "pxe")) {
[2325]723 /* We need to override prefix value in PXE mode as it's
[2382]724 * already done in start-netfs */
[2325]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 }
[2383]732 mr_free(tmp);
[2325]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;
[128]738 } else {
[2325]739 fatal_error("UNKNOWN bkp-media-type");
[1]740 }
[1242]741} else {
[2325]742 fatal_error("backup-media-type not specified!");
[1242]743}
[2325]744mr_free(value);
745
[1242]746if (bkpinfo->disaster_recovery) {
[1736]747 if (bkpinfo->backup_media_type == cdstream) {
[2325]748 mr_free(bkpinfo->media_device);
749 mr_asprintf(bkpinfo->media_device, "/dev/cdrom");
[1736]750 bkpinfo->media_size[0] = 1999 * 1024;
751 bkpinfo->media_size[1] = 650; /* good guess */
752 } else if (bkpinfo->backup_media_type == usb) {
[2127]753 envtmp1 = getenv("MRUSBDEV");
754 if (envtmp1 == NULL) {
[2325]755 if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
[2127]756 fatal_error("Cannot get USB device name from cfg file");
757 }
758 } else {
[2325]759 mr_asprintf(value,"%s", envtmp1);
[1736]760 }
[2325]761 mr_free(bkpinfo->media_device);
762 mr_asprintf(bkpinfo->media_device, "%s1", value);
763 mr_free(value);
[2280]764 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
[2325]765 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
766 if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
[1736]767 fatal_error("Cannot get tape device name from cfg file");
768 }
[2325]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 }
[2280]779 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
[1736]780 } else {
[2325]781 mr_free(bkpinfo->media_device);
782 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
[1736]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]");
[1]786 }
[1242]787} else {
[2325]788 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
[1242]789}
[128]790
[2325]791value = read_cfg_var(cfg_file, "use-star");
792if (value && strstr(value, "yes")) {
[1948]793 bkpinfo->use_star = TRUE;
794 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
[1242]795}
[2325]796mr_free(value);
[1242]797
[2325]798value = read_cfg_var(cfg_file, "obdr");
799if (value && strstr(value, "TRUE")) {
[1948]800 bkpinfo->use_obdr = TRUE;
801 log_msg(1, "OBDR mode activated");
802}
[2325]803mr_free(value);
[1948]804
[2325]805value = read_cfg_var(cfg_file, "acl");
806if (value && strstr(value, "TRUE")) {
[2323]807 mr_asprintf(g_getfacl,"setfacl");
[1948]808 log_msg(1, "We will restore ACLs");
[2331]809 tmp = find_home_of_exe("setfacl");
810 if (!tmp) {
[1948]811 log_msg(1, "Unable to restore ACLs as no setfacl found");
812 }
[2331]813 mr_free(tmp);
[1242]814}
[2325]815mr_free(value);
816
817value = read_cfg_var(cfg_file, "xattr");
818if (value && strstr(value, "TRUE")) {
[2323]819 mr_asprintf(g_getfattr,"setfattr");
[1948]820 log_msg(1, "We will restore XATTRs");
[2331]821 tmp = find_home_of_exe("setfattr");
822 if (!tmp) {
[1948]823 log_msg(1, "Unable to restore XATTRs as no setfattr found");
824 }
[2331]825 mr_free(tmp);
[1242]826}
[2325]827mr_free(value);
[1242]828
[2325]829value = read_cfg_var(cfg_file, "internal-tape-block-size");
830if (value != NULL) {
831 bkpinfo->internal_tape_block_size = atol(value);
[1242]832} else {
[2325]833 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
[1242]834}
[2325]835log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
836mr_free(value);
[1242]837
[2338]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
[2325]850value = read_cfg_var(cfg_file, "use-lzo");
851if (value && strstr(value, "yes")) {
[2338]852 bkpinfo->use_lzma = FALSE;
[2325]853 bkpinfo->use_lzo = TRUE;
854 bkpinfo->use_gzip = FALSE;
[2326]855 mr_free(bkpinfo->zip_exe);
856 mr_asprintf(bkpinfo->zip_exe, "lzop");
[2327]857 mr_free(bkpinfo->zip_suffix);
858 mr_asprintf(bkpinfo->zip_suffix, "lzo");
[2325]859}
860mr_free(value);
861
862value = read_cfg_var(cfg_file, "use-gzip");
863if (value && strstr(value, "yes")) {
[2338]864 bkpinfo->use_lzma = FALSE;
[1242]865 bkpinfo->use_lzo = FALSE;
866 bkpinfo->use_gzip = TRUE;
[2326]867 mr_free(bkpinfo->zip_exe);
868 mr_asprintf(bkpinfo->zip_exe, "gzip");
[2327]869 mr_free(bkpinfo->zip_suffix);
870 mr_asprintf(bkpinfo->zip_suffix, "gz");
[1242]871}
[2325]872mr_free(value);
873
874value = read_cfg_var(cfg_file, "use-comp");
875if (value && strstr(value, "yes")) {
[2338]876 bkpinfo->use_lzma = FALSE;
[2325]877 bkpinfo->use_lzo = FALSE;
878 bkpinfo->use_gzip = FALSE;
[2326]879 mr_free(bkpinfo->zip_exe);
880 mr_asprintf(bkpinfo->zip_exe, "bzip2");
[2327]881 mr_free(bkpinfo->zip_suffix);
882 mr_asprintf(bkpinfo->zip_suffix, "bz2");
[1242]883}
[2325]884mr_free(value);
[1]885
[2327]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
[2325]893value = read_cfg_var(cfg_file, "differential");
894if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
895 bkpinfo->differential = TRUE;
[1242]896}
897log_msg(2, "differential var = '%s'", value);
[2325]898mr_free(value);
[1242]899if (bkpinfo->differential) {
[2325]900 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
[1242]901} else {
[2325]902 log_msg(2, "This is a regular (full) backup");
[1242]903}
904
[2623]905tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
[2704]906tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
[2383]907if (tmp || strstr(tmp1, "donteject")) {
[2280]908 bkpinfo->please_dont_eject = TRUE;
909 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
[1242]910}
[2325]911mr_free(tmp);
[2383]912mr_free(tmp1);
[1242]913
[2382]914if (bkpinfo->backup_media_type == netfs) {
[1736]915 if (!cfgf) {
[2382]916 if (bkpinfo->netfs_mount) {
917 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
[2325]918 }
[2382]919 if (bkpinfo->netfs_remote_dir) {
920 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
[2325]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");
[1736]923 } else {
[2382]924 mr_free(bkpinfo->netfs_mount);
[2623]925 bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
[2325]926
[2382]927 mr_free(bkpinfo->netfs_remote_dir);
[2623]928 bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
[2325]929
[2382]930 if (bkpinfo->netfs_mount != NULL) {
931 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
[2325]932 }
[2382]933 if (bkpinfo->netfs_remote_dir != NULL) {
934 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
[2325]935 }
[2382]936 if (bkpinfo->netfs_proto != NULL) {
937 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
938 }
[1]939 }
[2704]940 tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
[2383]941 if (strstr(tmp1, "pxe")) {
942 mr_free(tmp1);
[1968]943 /* We need to override values in PXE mode as it's
[2382]944 * already done in start-netfs */
945 envtmp1 = getenv("netfsmount");
[1736]946 if (envtmp1 == NULL) {
[2382]947 fatal_error("no netfsmount variable in environment");
[1736]948 }
949 envtmp2 = getenv("dirimg");
950 if (envtmp2 == NULL) {
951 fatal_error("no dirimg variable in environment");
952 }
[2382]953 mr_free(bkpinfo->netfs_mount);
954 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
[2325]955
[2382]956 mr_free(bkpinfo->netfs_remote_dir);
957 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
[2383]958 } else {
959 mr_free(tmp1);
[1]960 }
[2383]961
[1242]962} else if (bkpinfo->backup_media_type == iso) {
[1736]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 */
[2323]967 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
[2623]968 iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
969 iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
[2323]970 mr_free(bkpinfo->isodir);
[2324]971 mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
[2325]972 mr_free(iso_mnt);
973
[1736]974 if (!bkpinfo->isodir[0]) {
[2323]975 mr_free(bkpinfo->isodir);
976 bkpinfo->isodir = old_isodir;
977 } else {
978 mr_free(old_isodir);
[128]979 }
[1736]980 if (!bkpinfo->disaster_recovery) {
981 if (strcmp(old_isodir, bkpinfo->isodir)) {
[2323]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);
[1736]987 }
988 }
[2325]989 mr_free(g_isodir_device);
[2623]990 g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
[2323]991 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
992
[1736]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 */
[2323]997 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
[1736]998 log_it("command = %s", command);
[2704]999 iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
[2383]1000 log_it("res of it = %s", iso_mnt);
[2280]1001 mr_free(command);
[1736]1002 } else {
[2325]1003 mr_asprintf(iso_mnt, "/tmp/isodir");
[2323]1004 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
[2280]1005 run_program_and_log_output(tmp1, 5);
1006 mr_free(tmp1);
1007
[2323]1008 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
[2280]1009 if (run_program_and_log_output(tmp1, 3)) {
[2325]1010 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
[1736]1011 bkpinfo->backup_media_type = cdr;
[2325]1012 mr_free(bkpinfo->media_device);
1013 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
[1736]1014 if (mount_media()) {
[2280]1015 mr_free(tmp1);
[2323]1016 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
[1736]1017 } else {
[2323]1018 log_msg(1, "You backed up to disk, then burned some CDs.");
[1736]1019 }
[128]1020 }
[2280]1021 mr_free(tmp1);
[128]1022 }
[1736]1023 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1024 if (bkpinfo->backup_media_type == iso) {
[2323]1025 mr_free(bkpinfo->isodir);
1026 mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1027 bkpinfo->isodir = tmp1;
[1736]1028 }
[2325]1029 mr_free(iso_mnt);
[1]1030 }
[2325]1031 mr_free(iso_path);
[1242]1032}
[1]1033
[1242]1034if (media_specified_by_user != none) {
[2623]1035 if (! bkpinfo->disaster_recovery) {
[1736]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;
[2623]1041 get_cfg_file_from_initrd();
[1736]1042 }
[128]1043 }
[1736]1044 bkpinfo->backup_media_type = media_specified_by_user;
[1242]1045}
1046g_backup_media_type = bkpinfo->backup_media_type;
1047paranoid_free(value);
1048return (0);
[1]1049
1050}
[128]1051
[1]1052/**************************************************************************
[1242]1053*END_READ_CFG_FILE_INTO_BKPINFO *
1054**************************************************************************/
[1]1055
1056
1057
[128]1058
[1]1059/**
[1843]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 */
[1]1069struct
[1645]1070s_node *process_filelist_and_biggielist()
[1]1071{
[1242]1072struct s_node *filelist;
[1]1073
[2280]1074char *command = NULL;
[1242]1075char *tmp;
[2357]1076char *tmp1 = NULL;
[1242]1077int res = 0;
1078pid_t pid;
[1]1079
[1242]1080assert(bkpinfo != NULL);
1081malloc_string(tmp);
[1]1082
[1987]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)) {
[2623]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);
[1987]1089 log_msg(1, "tarcommand = %s", command);
1090 run_program_and_log_output(command, 1);
[2280]1091 mr_free(command);
1092
[1987]1093 } else {
[2323]1094 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
[1987]1095 insist_on_this_cd_number(1);
1096 log_msg(2, "Back from iotcn");
1097 run_program_and_log_output("mount", 1);
[2623]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");
[1]1099
[1987]1100 log_msg(1, "tarcommand = %s", command);
1101 run_program_and_log_output(command, 1);
[2280]1102 mr_free(command);
1103
[2623]1104 if (!does_file_exist(MINDI_CACHE"/biggielist.txt")) {
1105 fatal_error("all.tar.gz did not include "MINDI_CACHE"/biggielist.txt");
[2029]1106 }
[2623]1107 if (!does_file_exist(MINDI_CACHE"/filelist.full.gz")) {
1108 fatal_error("all.tar.gz did not include "MINDI_CACHE"/filelist.full.gz");
[1987]1109 }
[128]1110 }
[1987]1111 chdir(tmp);
[2049]1112
[1987]1113 log_msg(2, "Forking");
1114 pid = fork();
1115 switch (pid) {
1116 case -1:
1117 fatal_error("Forking error");
1118 break;
[1]1119
[1987]1120 case 0:
1121 log_to_screen("Pre-processing filelist");
[2623]1122 mr_asprintf(command, "grep -E '^/dev/.*' "MINDI_CACHE"/biggielist.txt > %s 2> /dev/null", g_filelist_imagedevs);
[128]1123 paranoid_system(command);
[2280]1124 mr_free(command);
[128]1125 exit(0);
1126 break;
1127
1128 default:
[541]1129 open_evalcall_form("Pre-processing filelist");
[128]1130 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1131 usleep(100000);
1132 update_evalcall_form(0);
1133 }
[1]1134 }
[128]1135 close_evalcall_form();
[1]1136
[128]1137 log_msg(3, "loading filelist");
[2623]1138 filelist = load_filelist(MINDI_CACHE"/filelist.full.gz");
[128]1139 log_msg(3, "deleting original filelist");
[2623]1140 unlink(MINDI_CACHE"/filelist.full.gz");
[128]1141 if (g_text_mode) {
[541]1142 printf("Restore which directory? --> ");
[2357]1143 mr_getline(tmp1, stdin);
1144 toggle_path_selection(filelist, tmp1, TRUE);
1145 if (strlen(tmp1) == 0) {
[128]1146 res = 1;
1147 } else {
1148 res = 0;
1149 }
[2357]1150 mr_free(tmp1);
[128]1151 } else {
1152 res = edit_filelist(filelist);
[1]1153 }
[128]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();
[1]1161
[2623]1162 // NB: It's not necessary to add biggielist.txt to the filelist.full
[128]1163 // file. The filelist.full file already contains the filename of EVERY
1164 // file backed up - regular and biggie files.
[1]1165
[128]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 }
[1]1172
[128]1173 paranoid_free(tmp);
1174 return (filelist);
1175}
[1]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 */
[128]1191int backup_crucial_file(char *path_root, char *filename)
[1]1192{
[2280]1193 char *tmp = NULL;
1194 char *command = NULL;
[128]1195 int res;
[1]1196
[128]1197 assert(path_root != NULL);
1198 assert_string_is_neither_NULL_nor_zerolength(filename);
1199
[2323]1200 mr_asprintf(tmp, "%s/%s", path_root, filename);
1201 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
[2280]1202 mr_free(tmp);
[128]1203
1204 res = run_program_and_log_output(command, 5);
[2280]1205 mr_free(command);
[128]1206 return (res);
[1]1207}
1208
[2094]1209void offer_to_make_initrd() {
[1]1210
[2094]1211if (bkpinfo->restore_mode != nuke) {
[2110]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 ?")) {
[2136]1214 log_msg(1,"Launching shell for manual initrd recreation");
[2816]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 }
[2110]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 {
[2094]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
[1]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 */
[128]1245int run_boot_loader(bool offer_to_hack_scripts)
[1]1246{
[128]1247 int res;
1248 int retval = 0;
[1]1249
1250 /** malloc *******/
[2325]1251 char *device = NULL;
1252 char *name = NULL;
[1845]1253 char *cmd = NULL;
[1]1254
[1845]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 */
[2323]1259 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
[1845]1260 run_program_and_log_output(cmd, 3);
[1873]1261 paranoid_free(cmd);
[1845]1262
[128]1263 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
[2095]1264 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
[2451]1265 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
[128]1266 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1267 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
[1845]1268 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1269 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
[2623]1270 device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.device");
1271 name = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.name");
[2280]1272 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
[2376]1273 sync();
[2094]1274
1275 offer_to_make_initrd();
[128]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 }
[1]1285#ifdef __FreeBSD__
[128]1286 else if (!strcmp(name, "BOOT0")) {
[2323]1287 mr_asprintf(tmp, "boot0cfg -B %s", device);
[128]1288 res = run_program_and_log_output(tmp, FALSE);
[1873]1289 paranoid_free(tmp);
[128]1290 } else {
[2323]1291 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
[128]1292 if (!system(tmp)) {
[2280]1293 mr_free(tmp);
[2323]1294 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
[128]1295 res = run_program_and_log_output(tmp, 3);
1296 } else {
[2280]1297 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
[128]1298 }
[2280]1299 mr_free(tmp);
[128]1300 }
[1]1301#else
[128]1302 else {
1303 log_to_screen
[541]1304 ("Unable to determine type of boot loader. Defaulting to LILO.");
[128]1305 res = run_lilo(offer_to_hack_scripts);
1306 }
[1]1307#endif
[2325]1308 mr_free(device);
1309 mr_free(name);
1310
[128]1311 retval += res;
1312 if (res) {
[541]1313 log_to_screen("Your boot loader returned an error");
[128]1314 } else {
[541]1315 log_to_screen("Your boot loader ran OK");
[128]1316 }
1317 return (retval);
[1]1318}
[128]1319
[1]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 */
[2331]1331char *find_my_editor(void) {
1332
1333 char *tmp = NULL;
[128]1334 static char output[MAX_STR_LEN];
[2331]1335
1336 tmp = find_home_of_exe("pico");
1337 if (tmp) {
[128]1338 strcpy(output, "pico");
[2331]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 }
[128]1353 }
[2331]1354 mr_free(tmp);
1355
1356 tmp = find_home_of_exe(output);
1357 if (!tmp) {
[128]1358 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1359 }
[2331]1360 mr_free(tmp);
[128]1361 return (output);
[1]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 */
[128]1371int run_grub(bool offer_to_run_stabgrub, char *bd)
[1]1372{
1373 /** malloc **/
[2280]1374 char *command = NULL;
[2316]1375 char *boot_device = NULL;
[2280]1376 char *tmp = NULL;
[2334]1377 char *editor = NULL;
[2316]1378 char *p = NULL;
[1]1379
[2316]1380 int res = 0;
1381 bool done;
[1]1382
[128]1383 assert_string_is_neither_NULL_nor_zerolength(bd);
[2323]1384 mr_asprintf(boot_device, "%s", bd);
[128]1385
1386 if (offer_to_run_stabgrub
[2316]1387 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
[128]1388 /* interactive mode */
1389 mvaddstr_and_log_it(g_currentY,
1390 0,
[2451]1391 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
[128]1392 for (done = FALSE; !done;) {
[2316]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 }
[2323]1401 mr_asprintf(command, "stabgrub-me %s", p);
[2316]1402 mr_free(p);
1403
[128]1404 res = run_program_and_log_output(command, 1);
[2280]1405 mr_free(command);
1406
[128]1407 if (res) {
1408 popup_and_OK
[541]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.");
[128]1410 newtSuspend();
1411 system("chroot " MNT_RESTORING);
1412 newtResume();
[541]1413 popup_and_OK("Thank you.");
[128]1414 } else {
1415 done = TRUE;
1416 }
[2451]1417 popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
[128]1418 if (!g_text_mode) {
1419 newtSuspend();
1420 }
[2334]1421 mr_asprintf(editor, "%s", find_my_editor());
1422
[2323]1423 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
[128]1424 paranoid_system(tmp);
[2280]1425 mr_free(tmp);
1426
[2323]1427 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
[1547]1428 paranoid_system(tmp);
[2280]1429 mr_free(tmp);
1430
[2451]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 }
[128]1436 paranoid_system(tmp);
[2280]1437 mr_free(tmp);
1438
[2323]1439 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
[1547]1440 paranoid_system(tmp);
[2280]1441 mr_free(tmp);
[2334]1442 mr_free(editor);
[2280]1443
[128]1444 if (!g_text_mode) {
1445 newtResume();
1446 }
1447 }
[2316]1448 } else {
[128]1449 /* nuke mode */
[2280]1450 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1451 log_msg(1, "Yay! grub-MR found...");
[2462]1452 mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
[2280]1453 log_msg(1, "command = %s", command);
1454 } else {
[2323]1455 mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
[2280]1456 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1457 }
[128]1458 mvaddstr_and_log_it(g_currentY,
1459 0,
[541]1460 "Running GRUB... ");
[2227]1461 log_it("%s",command);
[128]1462 res = run_program_and_log_output(command, 1);
[2280]1463 mr_free(command);
1464
[128]1465 if (res) {
1466 popup_and_OK
[541]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.");
[128]1468 newtSuspend();
1469 system("chroot " MNT_RESTORING);
1470 newtResume();
[541]1471 popup_and_OK("Thank you.");
[128]1472 }
[1]1473 }
[2316]1474 mr_free(boot_device);
1475
[128]1476 if (res) {
[541]1477 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
[128]1478 log_to_screen
[1315]1479 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
[128]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 {
[541]1490 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
[128]1491 }
[1]1492
[128]1493 return (res);
[1]1494}
[128]1495
[1]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 */
[128]1506int run_elilo(bool offer_to_run_stabelilo)
[1]1507{
1508 /** malloc **/
[2280]1509 char *command = NULL;
1510 char *tmp = NULL;
[2334]1511 char *editor = NULL;
[1]1512
[128]1513 int res;
1514 int done;
[1]1515
[128]1516 if (offer_to_run_stabelilo
[2094]1517 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
[1]1518
[128]1519 /* interactive mode */
1520 {
1521 mvaddstr_and_log_it(g_currentY,
1522 0,
[541]1523 "Modifying fstab and elilo.conf... ");
[2323]1524 mr_asprintf(command, "stabelilo-me");
[128]1525 res = run_program_and_log_output(command, 3);
[2280]1526 mr_free(command);
1527
[128]1528 if (res) {
1529 popup_and_OK
[541]1530 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
[128]1531 for (done = FALSE; !done;) {
1532 if (!g_text_mode) {
1533 newtSuspend();
1534 }
[2334]1535 mr_asprintf(editor, "%s", find_my_editor());
1536
[2323]1537 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
[128]1538 paranoid_system(tmp);
[2280]1539 mr_free(tmp);
1540
[2323]1541 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
[128]1542 paranoid_system(tmp);
[2280]1543 mr_free(tmp);
1544
[2334]1545 mr_free(editor);
1546
[128]1547 if (!g_text_mode) {
1548 newtResume();
1549 }
[1]1550// newtCls();
[541]1551 if (ask_me_yes_or_no("Edit them again?")) {
[128]1552 continue;
1553 }
1554 done = TRUE;
1555 }
1556 } else {
[541]1557 log_to_screen("elilo.conf and fstab were modified OK");
[1]1558 }
[128]1559 } else
1560 /* nuke mode */
[1]1561 {
[128]1562 res = TRUE;
[1]1563 }
[128]1564 return (res);
1565}
[1]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 */
[128]1577int run_lilo(bool offer_to_run_stablilo)
[1]1578{
1579 /** malloc **/
[2280]1580 char *command = NULL;
1581 char *tmp = NULL;
[2334]1582 char *editor = NULL;
[1]1583
[128]1584 int res;
1585 int done;
1586 bool run_lilo_M = FALSE;
[1]1587
[128]1588 if (!run_program_and_log_output
1589 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1590 run_lilo_M = TRUE;
1591 }
[1]1592
[128]1593 if (offer_to_run_stablilo
[2094]1594 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
[1]1595
[128]1596 /* interactive mode */
1597 {
1598 mvaddstr_and_log_it(g_currentY,
1599 0,
[541]1600 "Modifying fstab and lilo.conf, and running LILO... ");
[2323]1601 mr_asprintf(command, "stablilo-me");
[128]1602 res = run_program_and_log_output(command, 3);
[2280]1603 mr_free(command);
1604
[128]1605 if (res) {
1606 popup_and_OK
[541]1607 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
[128]1608 for (done = FALSE; !done;) {
1609 if (!g_text_mode) {
1610 newtSuspend();
1611 }
[2334]1612 mr_asprintf(editor, "%s", find_my_editor());
1613
[2323]1614 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
[128]1615 paranoid_system(tmp);
[2280]1616 mr_free(tmp);
1617
[2323]1618 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
[128]1619 paranoid_system(tmp);
[2280]1620 mr_free(tmp);
1621
[2334]1622 mr_free(editor);
1623
[128]1624 if (!g_text_mode) {
1625 newtResume();
1626 }
[1]1627// newtCls();
[541]1628 if (ask_me_yes_or_no("Edit them again?")) {
[128]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
[541]1642 ("LILO failed. Re-edit system files?");
[128]1643 } else {
1644 done = TRUE;
1645 }
1646 }
1647 } else {
[541]1648 log_to_screen("lilo.conf and fstab were modified OK");
[1]1649 }
[128]1650 } else
1651 /* nuke mode */
1652 {
1653 mvaddstr_and_log_it(g_currentY,
1654 0,
[541]1655 "Running LILO... ");
[128]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);
[1]1663 }
[128]1664 if (res) {
[541]1665 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
[128]1666 log_to_screen
[541]1667 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
[128]1668 } else {
[541]1669 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
[128]1670 }
[1]1671 }
[128]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);
[1]1677 }
[128]1678 return (res);
1679}
[1]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 */
[128]1692int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
[1]1693{
1694 /** malloc **/
[2280]1695 char *command = NULL;
[2316]1696 char *boot_device = NULL;
[2280]1697 char *tmp = NULL;
[128]1698 char *editor;
[2316]1699 char *p = NULL;
[128]1700 int res;
1701 int done;
[1]1702
[128]1703 assert_string_is_neither_NULL_nor_zerolength(bd);
[1]1704
[2323]1705 mr_asprintf(boot_device, "%s", bd);
[1]1706
[128]1707 if (offer_to_hack_scripts
[2316]1708 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
[128]1709 /* interactive mode */
1710 mvaddstr_and_log_it(g_currentY, 0,
[541]1711 "Modifying fstab and restoring MBR... ");
[128]1712 for (done = FALSE; !done;) {
1713 if (!run_program_and_log_output("which vi", FALSE)) {
[541]1714 popup_and_OK("You will now edit fstab");
[128]1715 if (!g_text_mode) {
1716 newtSuspend();
1717 }
[2334]1718 mr_asprintf(editor, "%s", find_my_editor());
[2323]1719 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
[2334]1720 mr_free(editor);
1721
[128]1722 paranoid_system(tmp);
[2280]1723 mr_free(tmp);
[128]1724 if (!g_text_mode) {
1725 newtResume();
1726 }
1727 }
[2316]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 }
[2323]1736 mr_asprintf(command, "stabraw-me %s", p);
[2316]1737 mr_free(p);
1738
[128]1739 res = run_program_and_log_output(command, 3);
[2280]1740 mr_free(command);
1741
[128]1742 if (res) {
[541]1743 done = ask_me_yes_or_no("Modifications failed. Re-try?");
[128]1744 } else {
1745 done = TRUE;
1746 }
1747 }
[2316]1748 } else {
[128]1749 /* nuke mode */
[2462]1750 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
[2280]1751 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1752
[128]1753 mvaddstr_and_log_it(g_currentY, 0,
[541]1754 "Restoring MBR... ");
[128]1755 res = run_program_and_log_output(command, 3);
[2280]1756 mr_free(command);
[1]1757 }
[2316]1758 mr_free(boot_device);
[2280]1759
[128]1760 if (res) {
[541]1761 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
[128]1762 log_to_screen
[1315]1763 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
[128]1764 } else {
[541]1765 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
[128]1766 }
1767 return (res);
[1]1768}
[128]1769
[1]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 */
[1645]1782void setup_MR_global_filenames()
[1]1783{
[128]1784 assert(bkpinfo != NULL);
[1]1785
[128]1786 malloc_string(g_filelist_imagedevs);
1787 malloc_string(g_imagedevs_restthese);
1788 malloc_string(g_mondo_home);
[1]1789
[2321]1790 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1791 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
[2623]1792 if (! bkpinfo->disaster_recovery) {
1793 /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
[2644]1794 get_cfg_file_from_initrd();
[128]1795 }
[1]1796}
[128]1797
[1]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 */
[128]1809void streamline_changes_file(char *output_file, char *input_file)
[1]1810{
[128]1811 FILE *fin;
1812 FILE *fout;
[2357]1813 char *incoming = NULL;
[1]1814
[128]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 }
[2357]1825 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
[128]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.. */
[2357]1834 mr_free(incoming);
[128]1835 }
[2357]1836 mr_free(incoming);
[128]1837 paranoid_fclose(fout);
1838 paranoid_fclose(fin);
[1]1839}
[128]1840
[1]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 */
[128]1849void twenty_seconds_til_yikes()
[1]1850{
[128]1851 int i;
1852 /* MALLOC * */
[2280]1853 char *tmp = NULL;
[1]1854
[128]1855 if (does_file_exist("/tmp/NOPAUSE")) {
1856 return;
1857 }
[541]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.",
[128]1861 "", 20);
1862 for (i = 0; i < 20; i++) {
1863 g_current_progress = i;
[2323]1864 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
[128]1865 update_progress_form(tmp);
[2280]1866 mr_free(tmp);
[128]1867 sleep(1);
1868 }
1869 close_progress_form();
[1]1870}
[128]1871
[1]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 */
[128]1882int unmount_all_devices(struct mountlist_itself
1883 *p_external_copy_of_mountlist)
[1]1884{
[128]1885 struct mountlist_itself *mountlist;
1886 int retval = 0, lino, res = 0, i;
[2280]1887 char *command = NULL;
[2211]1888 char *tmp = NULL;
[1]1889
[128]1890 assert(p_external_copy_of_mountlist != NULL);
[1]1891
[128]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);
[1]1896
[2351]1897 run_program_and_log_output("df -m -P", 3);
[541]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.",
[128]1902 "", mountlist->entries);
1903 chdir("/");
1904 for (i = 0;
1905 i < 10
1906 &&
1907 run_program_and_log_output
[792]1908 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
[128]1909 i++) {
1910 sleep(1);
1911 log_msg(2, "Waiting for buffer() to finish");
1912 }
[1]1913
[2376]1914 sync();
[1]1915
[2323]1916 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
[1322]1917 if (run_program_and_log_output(tmp, FALSE)) {
[128]1918 log_msg(1,
[1315]1919 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
[1]1920 }
[2211]1921 paranoid_free(tmp);
[128]1922 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1923 run_program_and_log_output("mkdir -p " MNT_RESTORING
1924 "/mnt/.boot.d", 5);
[1]1925 }
[1971]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
[128]1931 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1932 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
1933 continue;
1934 }
[2323]1935 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
[128]1936 update_progress_form(tmp);
[2211]1937
[128]1938 if (is_this_device_mounted(mountlist->el[lino].device)) {
1939 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
[2323]1940 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
[128]1941 } else {
1942 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
[2323]1943 mr_asprintf(command, "umount %s/", MNT_RESTORING);
[128]1944 log_msg(3,
1945 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
1946 } else {
[2323]1947 mr_asprintf(command, "umount " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
[2144]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 }
[128]1956 }
1957 }
1958 log_msg(10, "The 'umount' command is '%s'", command);
1959 res = run_program_and_log_output(command, 3);
[2280]1960 mr_free(command);
[128]1961 } else {
[2211]1962 mr_strcat(tmp, "...not mounted anyway :-) OK");
[128]1963 res = 0;
1964 }
1965 g_current_progress++;
1966 if (res) {
[2211]1967 mr_strcat(tmp, "...Failed");
[128]1968 retval++;
1969 log_to_screen(tmp);
1970 } else {
1971 log_msg(2, tmp);
1972 }
[2211]1973 paranoid_free(tmp);
[128]1974 }
1975 close_progress_form();
1976 if (retval) {
[541]1977 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
[128]1978 } else {
[541]1979 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
[128]1980 }
1981 if (retval) {
[541]1982 log_to_screen("Unable to unmount some of your partitions.");
[128]1983 } else {
[541]1984 log_to_screen("All partitions were unmounted OK.");
[128]1985 }
1986 free(mountlist);
1987 return (retval);
[1]1988}
[128]1989
[1]1990/**************************************************************************
1991 *END_UNMOUNT_ALL_DEVICES *
1992 **************************************************************************/
1993
1994
1995
1996/**************************************************************************
1997 *END_GET_CFG_FILE_FROM_ARCHIVE *
1998 **************************************************************************/
1999
2000/* @} - end restoreUtilityGroup */
2001
[128]2002void wait_until_software_raids_are_prepped(char *mdstat_file,
2003 int wait_for_percentage)
[1]2004{
[558]2005 struct raidlist_itself *raidlist;
[128]2006 int unfinished_mdstat_devices = 9999, i;
[2280]2007 char *screen_message = NULL;
[1]2008
[558]2009 raidlist = malloc(sizeof(struct raidlist_itself));
[128]2010
2011 assert(wait_for_percentage <= 100);
[2230]2012 log_it("wait_until_software_raids_are_prepped");
[128]2013 while (unfinished_mdstat_devices > 0) {
[558]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);
[128]2018 return;
[1]2019 }
[558]2020 for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2021 if (raidlist->el[i].progress < wait_for_percentage) {
[128]2022 unfinished_mdstat_devices++;
[704]2023 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2024 {
2025 continue;
2026 }
[558]2027 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
[2323]2028 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
[128]2029 open_evalcall_form(screen_message);
[2280]2030 mr_free(screen_message);
2031
[558]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);
[128]2035 sleep(2);
[558]2036 // FIXME: Prefix '/dev/' should really be dynamic!
2037 if (parse_mdstat(raidlist, "/dev/")) {
[128]2038 break;
2039 }
2040 }
2041 close_evalcall_form();
2042 }
[1]2043 }
[128]2044 }
[558]2045 paranoid_free(raidlist);
[1]2046}
[2094]2047
2048
Note: See TracBrowser for help on using the repository browser.