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

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

svn merge -r 1923:1938 $SVN_M/branches/2.2.6

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