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

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

prefix is also now read from conf file

  • Property svn:keywords set to Id
File size: 70.6 KB
Line 
1/***************************************************************************
2 * $Id: mondo-rstr-tools.c 1628 2007-09-09 01:14:36Z 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
19extern char *bkptype_to_string(t_bkptype bt);
20
21extern bool g_sigpipe_caught;
22extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
23extern bool g_I_have_just_nuked;
24extern char *g_tmpfs_mountpt;
25extern char *g_isodir_device;
26extern char *g_isodir_format;
27extern long g_current_progress, g_maximum_progress;
28extern char *g_biggielist_txt;  // where 'biggielist.txt' is stored, on ramdisk / tempdir;
29                          // biggielist.txt is the list of big files stored on the
30                          // backup media set in question
31extern char *g_filelist_full;   // filelist.full.gz is the list of all regular files
32                          // (excluding big files) stored on the backup media set
33extern char *g_biggielist_pot;  // list of big files which _could_ be restored, if the
34                          // user chooses them
35extern char *g_filelist_imagedevs;  // list of devices (e.g. /dev/hda1, /dev/sda5) which
36                             // were archived as images, not just /dev entries
37                             // ... e.g. NTFS, BeOS partitions
38extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
39                              // restore only these
40extern char *g_mondo_cfg_file;  // where m*ndo-restore.cfg (the config file) is stored
41extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
42
43extern t_bkptype g_backup_media_type;
44extern char *g_backup_media_string;
45
46extern int g_partition_table_locked_up;
47extern char *MONDO_LOGFILE;
48
49/* Should we use or not extended attributes and acl when restoring */
50char *g_getfattr = NULL;
51char *g_getfacl = NULL;
52
53/**
54 * @addtogroup restoreUtilityGroup
55 * @{
56 */
57/**
58 * Free the malloc()s for the filename variables.
59 */
60void free_MR_global_filenames(void)
61{
62    mr_free(g_biggielist_txt);
63    mr_free(g_filelist_full);
64    mr_free(g_filelist_imagedevs);
65    mr_free(g_imagedevs_restthese);
66    mr_free(g_mondo_cfg_file);
67    mr_free(g_mountlist_fname);
68    mr_free(g_tmpfs_mountpt);
69    mr_free(g_isodir_device);
70    mr_free(g_isodir_format);
71}
72
73
74/**
75 * Ask the user which imagedevs from the list contained in @p infname should
76 * actually be restored.
77 * @param infname The file containing a list of all imagedevs.
78 * @param outfname The location of the output file containing the imagedevs the user wanted to restore.
79 * @ingroup restoreUtilityGroup
80 */
81void ask_about_these_imagedevs(char *infname, char *outfname)
82{
83    FILE *fin = NULL;
84    FILE *fout = NULL;
85  /************************************************************************
86   * allocate memory regions. test and set  -sab 16 feb 2003              *
87   ************************************************************************/
88    char *incoming = NULL;
89    char *question = NULL;
90
91    size_t n = 0;
92
93    assert_string_is_neither_NULL_nor_zerolength(infname);
94    assert_string_is_neither_NULL_nor_zerolength(outfname);
95
96    if (!(fin = fopen(infname, "r"))) {
97        fatal_error("Cannot openin infname");
98    }
99    if (!(fout = fopen(outfname, "w"))) {
100        fatal_error("Cannot openin outfname");
101    }
102    for (mr_getline(&incoming, &n, fin);
103         !feof(fin); mr_getline(&incoming, &n, fin)) {
104        mr_strip_spaces(incoming);
105
106        if (incoming[0] == '\0') {
107            continue;
108        }
109
110        mr_asprintf(&question,
111                 _("Should I restore the image of %s ?"), incoming);
112
113        if (ask_me_yes_or_no(question)) {
114            fprintf(fout, "%s\n", incoming);
115        }
116        mr_free(question);
117    }
118
119  /*** free memory ***********/
120    mr_free(incoming);
121
122    paranoid_fclose(fout);
123    paranoid_fclose(fin);
124}
125
126/**************************************************************************
127 *ASK_ABOUT_THESE_IMAGEDEVS                                               *
128 **************************************************************************/
129
130
131/**
132 * Extract @c mondo-restore.cfg and @c mountlist.txt from @p ramdisk_fname.
133 * @param bkpinfo The backup information structure. @c tmpdir is the only field used.
134 * @param ramdisk_fname The filename of the @b compressed ramdisk to look in.
135 * @param output_cfg_file Where to put the configuration file extracted.
136 * @param output_mountlist_file Where to put the mountlist file extracted.
137 * @return 0 for success, nonzero for failure.
138 * @ingroup restoreUtilityGroup
139 */
140int
141extract_config_file_from_ramdisk(struct s_bkpinfo *bkpinfo,
142                                 char *ramdisk_fname,
143                                 char *output_cfg_file,
144                                 char *output_mountlist_file)
145{
146    char *mountpt = NULL;
147    char *command = NULL;
148    char *orig_fname = NULL;
149    int retval = 0;
150
151    assert(bkpinfo != NULL);
152    assert_string_is_neither_NULL_nor_zerolength(ramdisk_fname);
153    assert_string_is_neither_NULL_nor_zerolength(output_cfg_file);
154    assert_string_is_neither_NULL_nor_zerolength(output_mountlist_file);
155    mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
156    mr_asprintf(&command, "mkdir -p %s", mountpt);
157    run_program_and_log_output(command, FALSE);
158    mr_free(command);
159
160    mr_asprintf(&command, "gzip -dc %s > %s/mindi.rd 2> /dev/null",
161            ramdisk_fname, bkpinfo->tmpdir);
162    run_program_and_log_output(command, FALSE);
163    mr_free(command);
164
165    mr_asprintf(&command, "umount %s", mountpt);
166    run_program_and_log_output(command, FALSE);
167    mr_free(command);
168
169    mr_asprintf(&command, "mount -o loop %s/mindi.rd -t ext2 %s",
170            bkpinfo->tmpdir, mountpt);
171    run_program_and_log_output(command, FALSE);
172    mr_free(command);
173
174    mr_asprintf(&command, "mkdir -p %s/tmp", bkpinfo->tmpdir);
175    run_program_and_log_output(command, FALSE);
176    mr_free(command);
177
178    mr_asprintf(&command, "cp -f %s/%s %s", // %s/%s becomes {mountpt}/tmp/m*ndo-restore.cfg
179            mountpt, g_mondo_cfg_file, output_cfg_file);
180    run_program_and_log_output(command, FALSE);
181    mr_free(command);
182
183    mr_asprintf(&orig_fname, "%s/%s", mountpt, g_mountlist_fname);
184    if (does_file_exist(orig_fname)) {
185        mr_asprintf(&command, "cp -f %s %s", orig_fname, output_mountlist_file);
186        run_program_and_log_output(command, FALSE);
187        mr_free(command);
188    }
189    mr_asprintf(&command, "umount %s", mountpt);
190    mr_free(mountpt);
191
192    run_program_and_log_output(command, FALSE);
193    mr_free(command);
194
195    if (!does_file_exist(output_cfg_file)
196        || (!does_file_exist(output_mountlist_file)
197            && does_file_exist(orig_fname))) {
198        mr_msg(2, "Failed to extract %s and/or %s from ramdisk",
199                output_cfg_file, output_mountlist_file);
200        retval = 1;
201    } else {
202        retval = 0;
203    }
204    mr_free(orig_fname);
205    return (retval);
206}
207
208
209/**
210 * Keep trying to get mondo-restore.cfg from the archive, until the user gives up.
211 * @param bkpinfo The backup information structure.
212 */
213void get_cfg_file_from_archive_or_bust(struct s_bkpinfo *bkpinfo)
214{
215    while (get_cfg_file_from_archive(bkpinfo)) {
216        if (!ask_me_yes_or_no
217            (_
218             ("Failed to find config file/archives. Choose another source?")))
219        {
220            fatal_error("Could not find config file/archives. Aborting.");
221        }
222        interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
223    }
224}
225
226
227/**
228 * Determine whether @p list_fname contains a line containing @p f.
229 * @param f The line to search for.
230 * @param list_fname The file to search in.
231 * @param preamble Ignore this beginning part of @p f ("" to disable).
232 * @return TRUE if it's in the list, FALSE if it's not.
233 */
234bool is_file_in_list(char *f, char *list_fname, char *preamble)
235{
236
237  /** needs malloc **/
238    char *command = NULL;
239    char *file = NULL;
240    char *tmp = NULL;
241    int res = 0;
242
243    assert_string_is_neither_NULL_nor_zerolength(f);
244    assert_string_is_neither_NULL_nor_zerolength(list_fname);
245    assert(preamble != NULL);
246
247    if (strncmp(preamble, f, strlen(preamble)) == 0) {
248        mr_asprintf(&file, f + strlen(preamble));
249    } else {
250        mr_asprintf(&file, f);
251    }
252    if (file[0] == '/' && file[1] == '/') {
253        mr_asprintf(&tmp, file);
254        mr_free(file);
255        mr_asprintf(&file, tmp + 1);
256        mr_free(tmp);
257    }
258    mr_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles",
259            f, file);
260    mr_asprintf(&command, "grep -E '^%s$' %s", file, list_fname);
261    mr_free(file);
262
263    res = run_program_and_log_output(command, FALSE);
264    mr_free(command);
265    if (res) {
266        return (FALSE);
267    } else {
268        return (TRUE);
269    }
270}
271/**************************************************************************
272 *END_IS_FILE_IN_LIST                                                     *
273 **************************************************************************/
274
275
276/**
277 * Set up an ISO backup.
278 * @param bkpinfo The backup information structure. Fields used:
279 * - @c bkpinfo->backup_media_type
280 * - @c bkpinfo->disaster_recovery
281 * - @c bkpinfo->isodir
282 * @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
283 * @return 0 for success, nonzero for failure.
284 */
285int iso_fiddly_bits(struct s_bkpinfo *bkpinfo, bool nuke_me_please)
286{
287    char *mount_isodir_command = NULL;
288    char *command = NULL;
289    int retval = 0, i = 0;
290    bool already_mounted = FALSE;
291
292    assert(bkpinfo != NULL);
293
294    g_ISO_restore_mode = TRUE;
295    read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
296    if (bkpinfo->disaster_recovery) {
297    /* Patch Conor Daly 26-june-2004
298     * Don't let this clobber an existing bkpinfo->isodir */
299        if (!bkpinfo->isodir) {
300            mr_allocstr(bkpinfo->isodir, "/tmp/isodir");
301        }
302/* End patch */
303        mr_asprintf(&command, "mkdir -p %s", bkpinfo->isodir);
304        run_program_and_log_output(command, 5);
305        mr_free(command);
306        mr_msg(2, "Setting isodir to %s", bkpinfo->isodir);
307    }
308
309    if (!get_isodir_info
310        (g_isodir_device, g_isodir_format, bkpinfo->isodir,
311         nuke_me_please)) {
312        return (1);
313    }
314    paranoid_system("umount " MNT_CDROM " 2> /dev/null");   /* just in case */
315
316    if (is_this_device_mounted(g_isodir_device)) {
317        log_to_screen(_("WARNING - isodir is already mounted"));
318        already_mounted = TRUE;
319    } else {
320        if (strlen(g_isodir_format) > 1) {
321            mr_asprintf(&mount_isodir_command, "mount %s -t %s -o ro %s", g_isodir_device, g_isodir_format, bkpinfo->isodir);
322        } else {
323            mr_asprintf(&mount_isodir_command, "mount %s -o ro %s", g_isodir_device, bkpinfo->isodir);
324        }
325        run_program_and_log_output("df -m", FALSE);
326        mr_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?",
327                mount_isodir_command);
328        if (run_program_and_log_output(mount_isodir_command, FALSE)) {
329            popup_and_OK
330                (_
331                 ("Cannot mount the device where the ISO files are stored."));
332            mr_free(mount_isodir_command);
333            return (1);
334        }
335        mr_free(mount_isodir_command);
336        log_to_screen
337            (_
338             ("I have mounted the device where the ISO files are stored."));
339    }
340    if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
341        mount_cdrom(bkpinfo);
342    }
343    i = what_number_cd_is_this(bkpinfo);    /* has the side-effect of calling mount_cdrom() */
344    mr_msg(1, "%s #%d has been mounted via loopback mount",
345            bkpinfo->backup_media_string, i);
346    if (i < 0) {
347        popup_and_OK
348            (_("Cannot find ISO images in the directory you specified."));
349        retval = 1;
350    }
351    mr_msg(2, "%ld: bkpinfo->isodir is now %s", __LINE__,
352            bkpinfo->isodir);
353    return (retval);
354}
355
356
357/**
358 * Kill all Petris processes.
359 */
360void kill_petris(void)
361{
362    char *command = NULL;
363    mr_asprintf(&command,
364            "kill `ps 2> /dev/null | grep petris 2> /dev/null | grep -v grep | cut -d' ' -f2` 2> /dev/null");
365    paranoid_system(command);
366    mr_free(command);
367}
368
369/**************************************************************************
370 *END_KILL_PETRIS                                                         *
371 **************************************************************************/
372
373/**
374 * Mount @p device at @p mpt as @p format.
375 * @param device The device (/dev entry) to mount.
376 * @param mpt The directory to mount it on.
377 * @param format The filesystem type of @p device.
378 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
379 * @return 0 for success, nonzero for failure.
380 */
381int mount_device(char *device, char *mpt, char *format, bool writeable)
382{
383    int res = 0;
384
385    char *command = NULL;
386    char *mountdir = NULL;
387    char *mountpoint = NULL;
388    char *additional_parameters = NULL;
389 
390    assert_string_is_neither_NULL_nor_zerolength(device);
391    assert_string_is_neither_NULL_nor_zerolength(mpt);
392    assert(format != NULL);
393
394    if (!strcmp(mpt, "/1")) {
395        mr_asprintf(&mountpoint, "/");
396        mr_msg(3, "Mommm! SME is being a dildo!");
397    } else {
398        mr_asprintf(&mountpoint, mpt);
399    }
400
401    if (!strcmp(mountpoint, "lvm")) {
402        mr_free(mountpoint);
403        return (0);
404    }
405    if (!strcmp(mountpoint, "image")) {
406        mr_free(mountpoint);
407        return (0);
408    }
409    mr_msg(1, "Mounting device %s   ", device);
410    if (writeable) {
411        mr_asprintf(&additional_parameters, "-o rw");
412    } else {
413        mr_asprintf(&additional_parameters, "-o ro");
414    }
415    if (find_home_of_exe("setfattr")) {
416        mr_strcat(additional_parameters, ",user_xattr");
417    }
418    if (find_home_of_exe("setfacl")) {
419        mr_strcat(additional_parameters, ",acl");
420    }
421
422    if (!strcmp(mountpoint, "swap")) {
423        mr_asprintf(&command, "swapon %s", device);
424    } else {
425        if (!strcmp(mountpoint, "/")) {
426            mr_asprintf(&mountdir, MNT_RESTORING);
427        } else {
428            mr_asprintf(&mountdir, "%s%s", MNT_RESTORING, mountpoint);
429        }
430        mr_asprintf(&command, "mkdir -p %s", mountdir);
431        run_program_and_log_output(command, FALSE);
432        mr_free(command);
433
434        mr_asprintf(&command, "mount -t %s %s %s %s 2>> %s", format, device,
435                additional_parameters, mountdir, MONDO_LOGFILE);
436        mr_msg(2, "command='%s'", command);
437    }
438    mr_free(additional_parameters);
439
440    res = run_program_and_log_output(command, TRUE);
441    if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
442        mr_msg(1, "Re-trying without the fancy extra parameters");
443        mr_free(command);
444
445        mr_asprintf(&command, "mount -t %s %s %s 2>> %s", format, device,
446                mountdir, MONDO_LOGFILE);
447        res = run_program_and_log_output(command, TRUE);
448    }
449    if (res) {
450        mr_msg(1, "Unable to mount device %s (type %s) at %s", device,
451                format, mountdir);
452        mr_msg(1, "command was '%s'", command);
453        if (!strcmp(mountpoint, "swap")) {
454            log_to_screen("Unable to mount device %s (type %s) at %s", device,
455                format, mountdir);
456        } else {
457            mr_msg(2, "Retrying w/o the '-t' switch");
458            mr_free(command);
459
460            mr_asprintf(&command, "mount %s %s 2>> %s", device, mountdir,
461                    MONDO_LOGFILE);
462            mr_msg(2, "2nd command = '%s'", command);
463            res = run_program_and_log_output(command, TRUE);
464            if (res == 0) {
465                mr_msg(1,
466                        "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
467            }
468        }
469    }
470    mr_free(command);
471    mr_free(mountdir);
472
473    if (res && !strcmp(mountpoint, "swap")) {
474        mr_msg(2, "That's ok. It's just a swap partition.");
475        mr_msg(2, "Non-fatal error. Returning 0.");
476        res = 0;
477    }
478    mr_free(mountpoint);
479
480    return (res);
481}
482/**************************************************************************
483 *END_MOUNT_DEVICE                                                        *
484 **************************************************************************/
485
486
487/**
488 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
489 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
490 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
491 * @return The number of errors encountered (0 for success).
492 */
493int mount_all_devices(struct mountlist_itself
494                      *p_external_copy_of_mountlist, bool writeable)
495{
496    int retval = 0;
497    int lino = 0;
498    int res = 0;
499    char *tmp = NULL;
500    char *these_failed = NULL;
501    char *format = NULL;
502    struct mountlist_itself *mountlist = NULL;
503
504    assert(p_external_copy_of_mountlist != NULL);
505    mountlist = (struct mountlist_itself *)mr_malloc(sizeof(struct mountlist_itself));
506    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
507           sizeof(struct mountlist_itself));
508    sort_mountlist_by_mountpoint(mountlist, 0);
509
510    mvaddstr_and_log_it(g_currentY, 0, _("Mounting devices         "));
511    open_progress_form(_("Mounting devices"),
512                       _("I am now mounting all the drives."),
513                       _("This should not take long."),
514                       "", mountlist->entries);
515
516    for (lino = 0; lino < mountlist->entries; lino++) {
517        if (!strcmp(mountlist->el[lino].device, "/proc")) {
518            mr_msg(1,
519                    "Again with the /proc - why is this in your mountlist?");
520        } else if (is_this_device_mounted(mountlist->el[lino].device)) {
521            log_to_screen(_("%s is already mounted"),
522                    mountlist->el[lino].device);
523        } else if (strcmp(mountlist->el[lino].mountpoint, "none")
524                   && strcmp(mountlist->el[lino].mountpoint, "lvm")
525                   && strcmp(mountlist->el[lino].mountpoint, "raid")
526                   && strcmp(mountlist->el[lino].mountpoint, "image")) {
527            mr_asprintf(&tmp, "Mounting %s", mountlist->el[lino].device);
528            update_progress_form(tmp);
529            mr_free(tmp);
530
531            mr_asprintf(&format, mountlist->el[lino].format);
532            if (!strcmp(format, "ext3")) {
533                mr_free(format);
534                mr_asprintf(&format, "ext2");
535            }
536            res = mount_device(mountlist->el[lino].device,
537                               mountlist->el[lino].mountpoint,
538                               format, writeable);
539            retval += res;
540            if (res) {
541                if (these_failed != NULL) { /* not the first time */
542                    mr_strcat(these_failed, " %s", mountlist->el[lino].device);
543                } else { /* The first time */
544                    mr_asprintf(&these_failed, "%s", mountlist->el[lino].device);
545                }
546            }
547            mr_free(format);
548        }
549        g_current_progress++;
550    }
551    close_progress_form();
552    run_program_and_log_output("df -m", TRUE);
553    if (retval) {
554        if (g_partition_table_locked_up > 0) {
555            log_to_screen
556                (_
557                 ("fdisk's ioctl() call to refresh its copy of the partition table causes the kernel to"));
558            log_to_screen(_
559                          ("lock up the partition table. You might have to reboot and use Interactive Mode to"));
560            log_to_screen(_
561                          ("format and restore *without* partitioning first. Sorry for the inconvenience."));
562        }
563        mr_asprintf(&tmp, _("Could not mount devices %s- shall I abort?"),
564                these_failed);
565        mr_free(these_failed);
566
567        if (!ask_me_yes_or_no(tmp)) {
568            retval = 0;
569            log_to_screen
570                (_
571                 ("Continuing, although some devices failed to be mounted"));
572            mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
573        } else {
574            mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
575            log_to_screen
576                (_("Unable to mount some or all of your partitions."));
577        }
578        mr_free(tmp);
579    } else {
580        log_to_screen(_("All partitions were mounted OK."));
581        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
582    }
583    run_program_and_log_output("df -m", 3);
584    mr_free(mountlist);
585    return (retval);
586}
587 /**************************************************************************
588  *END_MOUNT_ALL_DEVICES                                                   *
589  **************************************************************************/
590
591
592/**
593 * Mount the CD-ROM device at /mnt/cdrom.
594 * @param bkpinfo The backup information structure. Fields used:
595 * - @c bkpinfo->backup_media_type
596 * - @c bkpinfo->disaster_recovery
597 * - @c bkpinfo->isodir
598 * - @c bkpinfo->media_device
599 * @return 0 for success, nonzero for failure.
600 */
601int mount_cdrom(struct s_bkpinfo *bkpinfo)
602{
603    char *mount_cmd = NULL;
604    int i = 0, res = 0;
605#ifdef __FreeBSD__
606    char *mddev = NULL;
607#endif
608
609    assert(bkpinfo != NULL);
610
611    if (bkpinfo->backup_media_type == tape
612        || bkpinfo->backup_media_type == udev) {
613        mr_msg(8, "Tape/udev. Therefore, no need to mount CDROM.");
614        return 0;
615    }
616
617    if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
618        mr_msg(2, "mount_cdrom() - CD already mounted. Fair enough.");
619        return (0);
620    }
621
622    if (bkpinfo->backup_media_type == nfs) {
623        mr_msg(2, "Mounting for NFS thingy");
624        mr_msg(2, "isodir = %s", bkpinfo->isodir);
625        if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
626            && am_I_in_disaster_recovery_mode()) {
627            strcpy(bkpinfo->isodir, "/tmp/isodir");
628            mr_msg(1, "isodir is being set to %s", bkpinfo->isodir);
629        }
630#ifdef __FreeBSD__
631        mr_asprintf(&mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
632                bkpinfo->nfs_remote_dir, bkpinfo->prefix,
633                g_current_media_number);
634        mddev = make_vn(mount_cmd);
635        mr_free(mount_cmd);
636
637        mr_asprintf(&mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
638        mr_free(mddev);
639#else
640        mr_asprintf(&mount_cmd,
641                "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
642                bkpinfo->isodir, bkpinfo->nfs_remote_dir, bkpinfo->prefix,
643                g_current_media_number, MNT_CDROM);
644#endif
645
646    } else if (bkpinfo->backup_media_type == iso) {
647#ifdef __FreeBSD__
648        mr_asprintf(&mount_cmd, "%s/%s-%d.iso", bkpinfo->isodir,
649                bkpinfo->prefix, g_current_media_number);
650        mddev = make_vn(mount_cmd);
651        mr_free(mount_cmd);
652
653        mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
654        mr_free(mddev);
655#else
656        mr_asprintf(&mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
657                bkpinfo->isodir, bkpinfo->prefix, g_current_media_number,
658                MNT_CDROM);
659#endif
660    } else if (strstr(bkpinfo->media_device, "/dev/"))
661#ifdef __FreeBSD__
662    {
663        mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
664                MNT_CDROM);
665    }
666#else
667    {
668        mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
669                bkpinfo->media_device, MNT_CDROM);
670    }
671#endif
672
673    else {
674        if (bkpinfo->disaster_recovery
675            && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
676            mr_allocstr(bkpinfo->media_device,
677                   last_line_of_file("/tmp/CDROM-LIVES-HERE"));
678        }
679
680#ifdef __FreeBSD__
681        mr_asprintf(&mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
682                MNT_CDROM);
683#else
684        mr_asprintf(&mount_cmd, "mount %s -t iso9660 -o ro %s",
685                bkpinfo->media_device, MNT_CDROM);
686#endif
687
688    }
689    mr_msg(2, "(mount_cdrom) --- command = %s", mount_cmd);
690    for (i = 0; i < 2; i++) {
691        res = run_program_and_log_output(mount_cmd, FALSE);
692        if (!res) {
693            break;
694        } else {
695            mr_msg(2, "Failed to mount CD-ROM drive.");
696            sleep(5);
697            run_program_and_log_output("sync", FALSE);
698        }
699    }
700    mr_free(mount_cmd);
701
702    if (res) {
703        mr_msg(2, "Failed, despite %d attempts", i);
704    } else {
705        mr_msg(2, "Mounted CD-ROM drive OK");
706    }
707    return (res);
708}
709/**************************************************************************
710 *END_MOUNT_CDROM                                                         *
711 **************************************************************************/
712
713
714/**
715 * Fix some miscellaneous things in the filesystem so the system will come
716 * up correctly on the first boot.
717 */
718void protect_against_braindead_sysadmins()
719{
720    run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
721                               FALSE);
722    run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
723                               FALSE);
724    if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
725        chmod(MNT_RESTORING "/tmp",1777 );
726    }
727    run_program_and_log_output("mkdir -p " MNT_RESTORING
728                               "/var/run/console", FALSE);
729    chmod(MNT_RESTORING "/dev/null",0777);
730    run_program_and_log_output("cd " MNT_RESTORING
731                               "; 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",
732                               TRUE);
733    run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
734                               TRUE);
735    run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
736                               TRUE);
737}
738/**************************************************************************
739 *END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS                                 *
740 **************************************************************************/
741
742
743/**
744 * Fill out @p bkpinfo based on @p cfg_file.
745 * @param cfg_file The mondo-restore.cfg file to read into @p bkpinfo.
746 * @param bkpinfo The backup information structure to fill out with information
747 * from @p cfg_file.
748 * @return 0 for success, nonzero for failure.
749 */
750int read_cfg_file_into_bkpinfo(char *cfgf, struct s_bkpinfo *bkpinfo)
751{
752    char *value = NULL;
753    char *tmp = NULL;
754    char *envtmp1 = NULL;
755    char *envtmp2 = NULL;
756    char *command = NULL;
757    char *iso_mnt = NULL;
758    char *iso_path = NULL;
759    char *old_isodir = NULL;
760    char *cfg_file = NULL;
761    t_bkptype media_specified_by_user;
762
763    malloc_string(value);
764    assert(bkpinfo != NULL);
765
766    if (!cfgf) {
767        cfg_file = g_mondo_cfg_file;
768    } else {
769        cfg_file = cfgf;
770    }
771
772    media_specified_by_user = bkpinfo->backup_media_type;   // or 'none', if not specified
773
774    if (0 == read_cfg_var(cfg_file, "backup-media-type", value)) {
775        if (!strcmp(value, "cdstream")) {
776            bkpinfo->backup_media_type = cdstream;
777        } else if (!strcmp(value, "cdr")) {
778            bkpinfo->backup_media_type = cdr;
779        } else if (!strcmp(value, "cdrw")) {
780            bkpinfo->backup_media_type = cdrw;
781        } else if (!strcmp(value, "dvd")) {
782            bkpinfo->backup_media_type = dvd;
783        } else if (!strcmp(value, "iso")) {
784            // Patch by Conor Daly - 2004/07/12
785            bkpinfo->backup_media_type = iso;
786            if (am_I_in_disaster_recovery_mode()) {
787                /* Check to see if CD is already mounted before mounting it... */
788                if (!is_this_device_mounted("/dev/cdrom")) {
789                    mr_msg(2,
790                            "NB: CDROM device not mounted, mounting...");
791                    run_program_and_log_output("mount /dev/cdrom "
792                                               MNT_CDROM, 1);
793                }
794                if (does_file_exist(MNT_CDROM "/archives/filelist.0")) {
795                    bkpinfo->backup_media_type = cdr;
796                    run_program_and_log_output("umount " MNT_CDROM, 1);
797                    log_it
798                        ("Re-jigging configuration AGAIN. CD-R, not ISO.");
799                }
800            }
801            if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
802                mr_allocstr(bkpinfo->prefix,value);
803            } else {
804                mr_allocstr(bkpinfo->prefix,STD_PREFIX);
805            }
806        } else if (!strcmp(value, "nfs")) {
807            bkpinfo->backup_media_type = nfs;
808            if (read_cfg_var(cfg_file, "iso-prefix", value) == 0) {
809                mr_allocstr(bkpinfo->prefix,value);
810            } else {
811                mr_allocstr(bkpinfo->prefix,STD_PREFIX);
812            }
813            if (strstr(call_program_and_get_last_line_of_output
814               ("cat /proc/cmdline"), "pxe")) {
815                /* We need to override prefix value in PXE mode as it's
816                * already done in start-nfs */
817                envtmp1 = getenv("imgname");
818                if (envtmp1 == NULL) {
819                    fatal_error("no imgname variable in environment");
820                }
821                mr_allocstr(bkpinfo->prefix,envtmp1);
822            }
823
824        } else if (!strcmp(value, "tape")) {
825            bkpinfo->backup_media_type = tape;
826        } else if (!strcmp(value, "udev")) {
827            bkpinfo->backup_media_type = udev;
828        } else {
829            fatal_error("UNKNOWN bkp-media-type");
830        }
831    } else {
832        fatal_error("backup-media-type not specified!");
833    }
834    if (bkpinfo->disaster_recovery) {
835        if (bkpinfo->backup_media_type == cdstream) {
836            mr_allocstr(bkpinfo->media_device, "/dev/cdrom");
837            bkpinfo->media_size = (long)650;    /* good guess */
838        } else if (bkpinfo->backup_media_type == tape
839                   || bkpinfo->backup_media_type == udev) {
840            if (read_cfg_var(cfg_file, "media-dev", value)) {
841                fatal_error("Cannot get tape device name from cfg file");
842            }
843            mr_allocstr(bkpinfo->media_device, value);
844            read_cfg_var(cfg_file, "media-size", value);
845            bkpinfo->media_size = atol(value);
846            mr_msg(2, "Backup medium is TAPE --- dev=%s",
847                    bkpinfo->media_device);
848        } else {
849            mr_allocstr(bkpinfo->media_device, "/dev/cdrom");   /* we don't really need this var */
850            bkpinfo->media_size = (long)1999*1024;  /* 650, probably, but we don't need this var anyway */
851            mr_msg(2, "Backup medium is CD-R[W]");
852        }
853    } else {
854        mr_msg(2,
855                "Not in Disaster Recovery Mode. No need to derive device name from config file.");
856    }
857
858    read_cfg_var(cfg_file, "use-star", value);
859    if (strstr(value, "yes")) {
860        bkpinfo->use_star = TRUE;
861        mr_msg(1, "Goody! ... bkpinfo->use_star is now true.");
862    }
863
864    read_cfg_var(cfg_file, "acl", value);
865    if (strstr(value, "yes")) {
866        mr_asprintf(&g_getfacl,"setfacl");
867        mr_msg(1, "We will restore ACLs");
868        if (! find_home_of_exe("setfacl")) {
869            mr_msg(1, "Unable to restore ACLs as no setfacl found");
870        }
871    }
872    read_cfg_var(cfg_file, "xattr", value);
873    if (strstr(value, "yes")) {
874        mr_asprintf(&g_getfattr,"setfattr");
875        mr_msg(1, "We will restore XATTRs");
876        if (! find_home_of_exe("setfattr")) {
877            mr_msg(1, "Unable to restore XATTRs as no setfattr found");
878        }
879    }
880
881    if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
882        bkpinfo->internal_tape_block_size = atol(value);
883        mr_msg(1, "Internal tape block size has been custom-set to %ld",
884                bkpinfo->internal_tape_block_size);
885    } else {
886        bkpinfo->internal_tape_block_size =
887            DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
888        mr_msg(1, "Internal tape block size = default (%ld)",
889                DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
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(char *dev)
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    long tape_block_size = 32768;
2056
2057    // tar -zxvf-
2058    mr_asprintf(&command,
2059            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2060            dev,
2061            tape_block_size,
2062            1024L * 1024 * 32 / tape_block_size,
2063            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2064            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2065    mr_msg(2, "command = '%s'", command);
2066    res = run_program_and_log_output(command, -1);
2067    mr_free(command);
2068
2069    if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2070        res = 0;
2071    }
2072    return (res);
2073}
2074
2075
2076/**
2077 * Get the configuration file from the tape, or CD.
2078 * @param bkpinfo The backup information structure. Fields used:
2079 * - @c bkpinfo->backup_media_type
2080 * - @c bkpinfo->media_device
2081 * - @c bkpinfo->tmpdir
2082 * @return 0 for success, nonzero for failure.
2083 */
2084int get_cfg_file_from_archive(struct s_bkpinfo *bkpinfo)
2085{
2086    int retval = 0;
2087    char *command = NULL;
2088    char *cfg_file = NULL;
2089    char *mounted_cfgf_path = NULL;
2090    char *tmp = NULL;
2091    char *mountpt = NULL;
2092    char *ramdisk_fname = NULL;
2093    char *mountlist_file = NULL;
2094    int res = 0;
2095
2096    bool try_plan_B = FALSE;
2097
2098    assert(bkpinfo != NULL);
2099    mr_msg(2, "gcffa --- starting");
2100    log_to_screen(_("I'm thinking..."));
2101    mr_asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2102    chdir(bkpinfo->tmpdir);
2103    // MONDO_CFG_FILE_STUB is missing the '/' at the start, FYI, by intent
2104    unlink(MONDO_CFG_FILE_STUB);
2105
2106    unlink(FILELIST_FULL_STUB);
2107    unlink(BIGGIELIST_TXT_STUB);
2108    unlink("tmp/i-want-my-lvm");
2109    mr_asprintf(&command, "mkdir -p %s", mountpt);
2110    run_program_and_log_output(command, FALSE);
2111    mr_free(command);
2112
2113    mr_asprintf(&cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2114    mr_asprintf(&mountlist_file, "%s/%s", bkpinfo->tmpdir,
2115            MOUNTLIST_FNAME_STUB);
2116    mr_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2117
2118    mr_asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2119    run_program_and_log_output(tmp, FALSE);
2120    mr_free(tmp);
2121
2122    if (!does_file_exist(cfg_file)) {
2123        mr_msg(2, "gcffa --- we don't have cfg file yet.");
2124        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2125            try_plan_B = TRUE;
2126        } else {
2127            mr_msg(2, "gcffa --- calling mount_cdrom now :)");
2128            if (!mount_cdrom(bkpinfo)) {
2129                mr_msg(2,
2130                        "gcffa --- managed to mount CD; so, no need for Plan B");
2131                try_plan_B = FALSE;
2132            } else {
2133                try_plan_B = TRUE;
2134            }
2135            if (what_number_cd_is_this(bkpinfo) > 1) {
2136                insist_on_this_cd_number(bkpinfo,
2137                                         (g_current_media_number = 1));
2138            }
2139        }
2140        if (try_plan_B) {
2141            mr_msg(2, "gcffa --- OK, switching to Plan B");
2142            chdir(bkpinfo->tmpdir);
2143            run_program_and_log_output("mkdir -p tmp", FALSE);
2144
2145            if (strlen(bkpinfo->media_device) == 0) {
2146                mr_allocstr(bkpinfo->media_device, "/dev/st0");
2147                mr_msg(2, "media_device is blank; assuming %s",
2148                        bkpinfo->media_device);
2149            }
2150            mr_asprintf(&tmp, bkpinfo->media_device);
2151            if (extract_cfg_file_and_mountlist_from_tape_dev
2152                (bkpinfo->media_device)) {
2153                mr_allocstr(bkpinfo->media_device, "/dev/st0");
2154                if (extract_cfg_file_and_mountlist_from_tape_dev
2155                    (bkpinfo->media_device)) {
2156                    mr_allocstr(bkpinfo->media_device, "/dev/osst0");
2157                    if (extract_cfg_file_and_mountlist_from_tape_dev
2158                        (bkpinfo->media_device)) {
2159                        mr_allocstr(bkpinfo->media_device, "/dev/ht0");
2160                        if (extract_cfg_file_and_mountlist_from_tape_dev
2161                            (bkpinfo->media_device)) {
2162                            mr_msg(3,
2163                                    "I tried lots of devices but none worked.");
2164                            mr_allocstr(bkpinfo->media_device, tmp);
2165                        }
2166                    }
2167                }
2168            }
2169            mr_free(tmp);
2170
2171            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2172                log_to_screen(_
2173                              ("Cannot find config info on tape/CD"));
2174                return (1);
2175            }
2176        } else {
2177            mr_asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2178            if (!does_file_exist(mounted_cfgf_path)) {
2179                mr_msg(2,
2180                        "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
2181                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
2182                run_program_and_log_output(command, TRUE);
2183                mr_free(command);
2184
2185                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2186                    fatal_error
2187                        ("Please reinsert the disk/CD and try again.");
2188                }
2189            }
2190            mr_free(mounted_cfgf_path);
2191        }
2192    }
2193    mr_free(mountpt);
2194
2195    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2196        mr_msg(1, "gcffa --- great! We've got the config file");
2197        mr_asprintf(&tmp, "%s/%s",
2198                call_program_and_get_last_line_of_output("pwd"),
2199                MONDO_CFG_FILE_STUB);
2200        mr_asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2201        iamhere(command);
2202
2203        if (strcmp(tmp, cfg_file)
2204            && run_program_and_log_output(command, 1)) {
2205            mr_msg(1,
2206                    "... but an error occurred when I tried to move it to %s",
2207                    cfg_file);
2208        } else {
2209            mr_msg(1, "... and I moved it successfully to %s", cfg_file);
2210        }
2211        mr_free(command);
2212
2213        mr_asprintf(&command, "cp -f %s/%s %s",
2214                call_program_and_get_last_line_of_output("pwd"),
2215                MOUNTLIST_FNAME_STUB, mountlist_file);
2216        iamhere(command);
2217        if (strcmp(tmp, cfg_file)
2218            && run_program_and_log_output(command, 1)) {
2219            mr_msg(1, "Failed to get mountlist");
2220        } else {
2221            mr_msg(1, "Got mountlist too");
2222            mr_free(command);
2223            mr_asprintf(&command, "cp -f %s %s", mountlist_file,
2224                    g_mountlist_fname);
2225            if (run_program_and_log_output(command, 1)) {
2226                mr_msg(1, "Failed to copy mountlist to /tmp");
2227            } else {
2228                mr_msg(1, "Copied mountlist to /tmp as well OK");
2229                mr_free(command);
2230                mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2231                run_program_and_log_output(command, 1);
2232            }
2233        }
2234        mr_free(command);
2235        mr_free(tmp);
2236    }
2237    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2238    if (!does_file_exist(cfg_file)) {
2239        iamhere(cfg_file);
2240        mr_msg(1, "%s not found", cfg_file);
2241        log_to_screen
2242            (_
2243             ("Oh dear. Unable to recover configuration file from boot disk"));
2244        return (1);
2245    }
2246
2247    log_to_screen(_("Recovered mondo-restore.cfg"));
2248    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2249        log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2250    }
2251/* start SAH */
2252    else {
2253        mr_asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2254                bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2255        run_program_and_log_output(command, FALSE);
2256        mr_free(command);
2257    }
2258/* end SAH */
2259
2260    mr_asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2261    mr_free(cfg_file);
2262    run_program_and_log_output(command, FALSE);
2263    mr_free(command);
2264
2265    mr_asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2266    mr_free(mountlist_file);
2267    run_program_and_log_output(command, FALSE);
2268    mr_free(command);
2269
2270    mr_asprintf(&command, "cp -f etc/raidtab /etc/");
2271    run_program_and_log_output(command, FALSE);
2272    mr_free(command);
2273
2274    mr_asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2275    run_program_and_log_output(command, FALSE);
2276    mr_free(command);
2277
2278    g_backup_media_type = bkpinfo->backup_media_type;
2279    strncpy(bkpinfo->backup_media_string,bkptype_to_string(bkpinfo->backup_media_type), (size_t)63);
2280    g_backup_media_string = bkpinfo->backup_media_string;
2281    return (retval);
2282}
2283/**************************************************************************
2284 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2285 **************************************************************************/
2286/* @} - end restoreUtilityGroup */
2287
2288
2289void wait_until_software_raids_are_prepped(int wait_for_percentage)
2290{
2291    struct raidlist_itself *raidlist = NULL;
2292    int unfinished_mdstat_devices = 9999, i = 0;
2293    char *screen_message = NULL;
2294
2295    raidlist = (struct raidlist_itself *)mr_malloc(sizeof(struct raidlist_itself));
2296
2297    assert(wait_for_percentage <= 100);
2298    iamhere("wait_until_software_raids_are_prepped");
2299    while (unfinished_mdstat_devices > 0) {
2300            // FIXME: Prefix '/dev/' should really be dynamic!
2301        if (parse_mdstat(raidlist, "/dev/")) {
2302            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2303            mr_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2304            return;
2305        }
2306        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
2307            if (raidlist->el[i].progress < wait_for_percentage) {
2308                unfinished_mdstat_devices++;
2309                if (raidlist->el[i].progress == -1) // delayed while another partition inits
2310                {
2311                    continue;
2312                }
2313                mr_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2314                mr_asprintf(&screen_message, "Sync'ing %s",
2315                        raidlist->el[i].raid_device);
2316                open_evalcall_form(screen_message);
2317                mr_free(screen_message);
2318
2319                while (raidlist->el[i].progress < wait_for_percentage) {
2320                    mr_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2321                    update_evalcall_form(raidlist->el[i].progress);
2322                    sleep(2);
2323                    // FIXME: Prefix '/dev/' should really be dynamic!
2324                    if (parse_mdstat(raidlist, "/dev/")) {
2325                        break;
2326                    }
2327                }
2328                close_evalcall_form();
2329            }
2330        }
2331    }
2332    mr_free(raidlist);
2333}
Note: See TracBrowser for help on using the repository browser.