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

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

STD_PREFIX only for restore now, waiting for removal also.

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