source: 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, 9 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.