source: MondoRescue/branches/stable/mondo/src/mondorestore/mondo-rstr-tools.c@ 1842

Last change on this file since 1842 was 1842, checked in by Bruno Cornec, 16 years ago
  • Fix lack of /etc/raidtab at restore rime in the right place
  • Adds support for nls_utf8 and pata_serverworks Patches from Dirk Husung (husung_at_tu-harburg.de)
  • Add efibootmgr to deplist.txt in order to be able to modify EFI menu at restore time on ia64
  • Usage of the new testver param of pb 0.8.12 to deliver 2.2.5 packages in a test dir.
  • Update pbcl files for upcoming delivery of 2.2.5
  • Fix an issue on parted output (K instead of KB) in parted2fdisk at restore time
  • Adds support for alb/aft types of bonding on Intel cards (Mark Pinkerton <Mark.Pinkerton_at_emageon.com>)
  • Escape variables in a perl script like mindi-bkphw
  • Better Proliant support at restore time now.
  • Fix a label bug where the variable label should also be re-initialized at each loop
  • start-nfs should NOT do exit => kernel panix as init exits
  • some other fixes for init on denymods
  • Adds boot options denymods (for udev) and forcemods (if not udev)
  • kqemu is denied. Probably should also be done for kvm stuff
  • Fix again the bug on modules link at root of the initrd. Hopefully for good.
  • Wait more around the USB CD emulated by iLO as it takes up to 5 seconds to come up
  • Attempt to fix udev support for RHEL 5.1
  • Better support for automatic iLO Virtual Media with udev
  • Some VMWare support improvements (however, it seems that VMWare support won't be possible anytime soon)
  • during init at restore time, copy all static evices availble for udev, as some distro implementation are no

t yet supported correctly for udev. Not very elegant, but should solve our current issues

  • Fedora 8 now supported as a build target for pb
  • svn.log removed.
  • dependencies reviewd for rhel_3
  • Attempt to fix the lack of modules loaded at restore time - especially fs device drivers
  • removes bkphw dir before potential creation
  • render mount command more vebose at restore time
  • Should fix #217
  • Increase BOOT_SIZE and EXTRA_SIZE to support features such as HW recovery
  • Handles udev.files files which could be symlinks
  • Improve udev support for distro with compressed modules (mdv e.g.)
  • Fix modules.dep copy
  • /sbin/pam_console_apply is needed by mdv udev conf
  • Adds support for nohw boot option to avoid re-setuping the HW conf
  • Improved support for Proliant on cpqacuxe
  • RstHW should be called after driver initialization
  • For debian/ubuntu mindi dpends on mindi-busybox
  • Update mindi-busybox pbcl for correct debian changelog generation, and up2date infos
  • Should fix #215
  • Fix #214 (Thanks to xdelaruelle)
  • Fix again svn.log not used anymore with new pb version
  • Adaptation of build process to upcoming 0.8.12 version of pb
  • Remove MONOTONIC clock to continue to support 2.4 kernels (RHEL 3 e.g. or ESX)
  • Attempt to solve ia64 BMC access through the serial port
  • parted2fdisk binary no more generated
  • do not require perl modules (strict.pm) at restore time
  • try to avoid modprobe messages at restore time
  • on ia64 now use the perl script parted2fdisk at retore time also
  • Also modprobe modules for udev after decompressing the additional ones
  • replace gzip -v9 by gzip -c9. Fix a bug at least on ia64
  • For all modules supported, create symlinks under the mountpoint and extract dev files as some are not automat ically created at the moment
  • Support /vmfs/volumes for ESX
  • Finally do not use vdf for ESX. Only creates issues.
  • Avoids continuing hw support if no product name found
  • Improves ia64 support for bootable image build
  • Fix a potential problem with ramdisk_blocksize param
  • MAKEDEV should also be included in deplist.txt
  • More fixes for udev support for Debian
  • Do not mount /boot if it's already mounted - avoids ESX hang
  • Fix NICs renumbering on Debian at least
  • Udev startup improvement to support iLO + NFS so modprobing all modules seems required as of now
  • Update to version 1.7.3 of busybox for pb
  • Load USB earlier in order to support KBD such as with iLO
  • Do busybox ldd first in order to create a potential /lib64 link correctly and then use it later in the image
  • Use variable DF in mindi to be able to support the ESX vdf
  • Fix mindi for Debian x86_64 where /lib64 is a link
  • Fix issue at restore time for ext2fs params not reused (Fix from Klaus Ade Johnstad <klaus_at_skolelinux.no>)
  • Do not copy udev files if they do not exist In udev case do not insert modules at all (udev should do it alone) May avoid the issue with rhel4.5 kernel ? To be tested
  • Update dependencies for rpm base build as well
  • And also perl is a debian/ubuntu dep
  • Better debian/ubuntu dependecies requirements (mtools)
  • Fix modes on mindi-bkphw (Thanks Phil Walker phil.walker_at_hp.com)
  • Complete rev [1771] for upper case RESTORE cli with syslinux as well
  • Update mindi-busybox to 1.7.3
  • Use RESTORE consistently across mondo to restore without interaction (report from Takeshi Shoji t.shoji_at_tripodw.jp)

(merge -r1769:1841 $SVN_M/branches/2.2.5)

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