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

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

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

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