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

Last change on this file since 1639 was 1639, checked in by Bruno Cornec, 13 years ago

More conf file items handled

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