source: trunk/mondo/mondo/mondorestore/mondo-rstr-tools.c @ 808

Last change on this file since 808 was 808, checked in by bruno, 13 years ago

merge -r793:807 $SVN_M/branches/stable
src => common for the moment it's easier to manage merges

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