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

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

Continue to remove floppy support

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