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

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

bkptype_to_string is now a public function (not static anymore)

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