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

Last change on this file since 1903 was 1903, checked in by bruno, 11 years ago

merge -r 1842:1889 2.2.5

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