source: MondoRescue/branches/3.1/mondo/src/mondorestore/mondo-rstr-tools.c@ 2937

Last change on this file since 2937 was 2937, checked in by Bruno Cornec, 12 years ago

svn merge -r 2849:2935 ../3.0

  • Adds 3 binaries called potentially by udev o support USB key mount at restore time (Victor Gattegno)
  • mindi only sets the boot flag of a USB device if none is present already (should avoid flip/flop situation)
  • Fix a compatibility bug in analyze-my-lvm whete exclude lists with '|' was incorrectly analyzed (' ' still expected)
  • Precise that -J is not supported by mondorestore yet.
  • Fix a compatibility bug in mindi where exclude lists with '|' was incorrectly analyzed (' ' still expected)
  • Install an MBR on USB devices when possible
  • Improve error message in case mondorestore isn't found
  • Adds support for more virtio devices for KVM restore
  • Improve mbr.bin handling
  • Fix an issue in test of FindKernel for Xen and non Xen cases
    • Fix #492 by removing an extra useless fi
    • Move fvat nd fat modules to CDROM_MODS in order to have them in the initrd to support saving logs to a USB device e.g.
    • Fix an error when dmidecode reports comments before system name
    • Fix previous broken patch on comment management for bkphw
    • Improve msgs printed during kbd analysis
    • Fix a small remaining pb with new comment support
    • Try to again improve the mount/umount stuff in mondo -Adds mention to OEL, CentOS, ScientifLinux as RHEL clones
  • Fix a panadoid_free done on the wrong variable (solve a memory leak)
  • Solve #495 by skipping the potential (auto-read-only) when analyzin /proc/mdstat result
  • Fix some markup in man pages
  • adds the post-nuke script sample for Debian (Guillaume Pernot/Andrée Leidenfrost)
  • Avoid a useless umount when changing of afio set, let insist_on_cd check and perform if needed
  • Copy everything under .ssh of root account to allow for sshfs mount without passwd at restore time.
  • Adds support for bnx2i driver
  • Try to fix #496 by supporting the protocol in the output of the mount command (sshfs#...)
  • Uses the -d option of the mount command to avoid leaving loop devices in use. Probably provoked by the usage of a more recent busybox, but anyway that option doesn't hurt, and does nothing for non-loop devices. Should fix the problems reported on the ML with NFS and more than 8 ISO images (8 being the default number of loop devices available)
  • Attempt to fix #436 by adding some newtDrawForm where appropriate.
  • Fix bugs in the kernel detection routine of mindi (some echo were done without capturing their output, confusing the return). This should also help the Xen detection issue
  • Change the logging function to be nearer from 2.2.10, and start using some
  • Initialize some global fields with an empty string, now that newt Draws more regularly progress forms
  • Mindi progression still not good, but showing now 3% when calling mindi. Would need a specific handling for the progress bar to evolve more afterwards
  • Add compatibility with the latest SSSTK + PSP content for HP ProLiant + branding homogeneous now. We only take conrep out of the SSSTK pending a package availability. Using hpacuscripting now. Review of parameters called following test made.
  • Fix #501 by pushing BOOT_SIZE to 36864 for certain Ubuntu cases
  • Fix some remaining inconsistencis in the ProLiant HW backup. ready for usage.
  • Fix an issue on udevadm call (needs an intermediate variable)
  • Fix a remaining ProLiant tool call
  • Remove again some wrong variable initialization for Net in order to not have strange messages now we call Draw more often
  • Adds support for hwaddr (MAC addresses) at restore time, and map to the correct NIC if it's found at restore time (based on code from Stefan Heijmans)
  • Try to Fix #499 by changing init in order to never exit, and rebooting using sysrq in /proc (not portable). Maybe should move to using a real init, and a separated rcS script.
  • Fixes the shell msg error by using setsid as per Busybox FAQ
  • Fix #491 by correctly checking Xen kernel used for a dom0 env (apollo13)
  • Improves logging in Die()
  • Improve again ProLiant HW support, by adding references to the yet to come SSSTK rpm so that conrep is called at its future right place.
  • Improve mindi support for kernel 3.x
  • Fix #499 for good, by using a real init from busybox and moving our init script to etc/init.d/rcS. We also now call the reboot from busybox to exit, which indeed reset the system correctly (in a VM at least which wasn't the case before). Reauires a new mindi-busybox as well.
  • Attempt to solve #503 by handling /lib64 separately for udev and only if not a link (to /lib) for Ubuntu 64
  • Improve again previous tests for bug #503
  • Improve -d option description for NFS
  • Allow http download for ftp content
  • New italian mirror
  • Fix #505 by documenting environment variables
    • Fix a bug where on OBDR mode compression was turned off to create the OBDR content but not back on (report from the mailing list)
  • solve http://trac.mondorescue.org/ticket/520 by Victor Gattegno
  • Fix #524 as option -U needs a size also
  • Removes useless gendf option
  • Fix #511 now stabgrub is called also after conf file modifications
  • Adds support for SUID binaries
  • remove a useless xenkernelname variable from mindi
  • Should fix #512 by clearing old scratchdir before changing to a new
  • Simplify the function engaging SCSI for Smart Array controllers, and support as many controller as we have
  • Add some binaries used on SLES 10 by udev
  • Fix a syntax issue in newt-specific.c
  • Fix a memory free bug where a used variable was freed to early
  • Fix a memory free bug where a used variable was misused in asprintf/free
  • Fix #498 by using an external program (hpsa_obdr_mode) which can set the mode of the tape to CD-ROM or Sequential at will.

That program will have to be downloaded from http://cciss.sf.net

  • Adds support for the route command in mindi-busybox
  • Force block size back to 32768 in OBDR mode after skipping the 2 tape marks, to read the additional rootfs data corerctly - Fix #498 for good it seems
  • Adds support for a new pata_atiixp driver
  • Fix #525 and improve printing when no /etc/raidtab, but still md devices
  • Exclude /run similarly to /sys and /proc
  • Fix a bug in mindi when having multiple swap partiions with same starting string (/dev/dm-1 and /dev/dm-16). We now add a space in the grep to avoid mischoice.
  • Fix grub installation if we had to go in the hack part which wasn't using the correct variables to make decisions !
  • Remove all mention of mondorescue.com from code
  • Fix some website typo on the download page and precise that we now develop on Mageia
  • Exclude sysfs devpts and tmpfs partitions found in RHEL 6.2 from analyze by mindi (made error messages)
  • Force activation of first partition which should not be optional as everything is destroyed before
  • Fix a bug in analyze-my-lvm where LVs were created in random order (the one of lvscan) instead of using the dm-xxx order, which creates issues at restore time between the mapping created then and the one we had at backup time which could be inconssistent

-mondoarchive now exists if the mt command is missing when needed

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