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

Last change on this file since 1275 was 1275, checked in by bruno, 12 years ago

find_my_editor now uses first the value of the env var EDITOR

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