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

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

merge -r781:793 $SVN_M/branches/stable

  • Property svn:keywords set to Id
File size: 72.6 KB
Line 
1/*
2 * $Id: mondo-rstr-tools.c 794 2006-09-13 23:05:18Z 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        } else if (!strcmp(value, "tape")) {
854            bkpinfo->backup_media_type = tape;
855        } else if (!strcmp(value, "udev")) {
856            bkpinfo->backup_media_type = udev;
857        } else {
858            fatal_error("UNKNOWN bkp-media-type");
859        }
860    } else {
861        fatal_error("backup-media-type not specified!");
862    }
863    paranoid_free(value);
864
865    if (bkpinfo->disaster_recovery) {
866        if (bkpinfo->backup_media_type == cdstream) {
867            paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
868            bkpinfo->media_size[0] = 1999 * 1024;
869            bkpinfo->media_size[1] = 650;   /* good guess */
870        } else if (bkpinfo->backup_media_type == tape
871                   || bkpinfo->backup_media_type == udev) {
872            paranoid_free(bkpinfo->media_device);
873            if (read_cfg_var(cfg_file, "media-dev", bkpinfo->media_device)) {
874                fatal_error("Cannot get tape device name from cfg file");
875            }
876            read_cfg_var(cfg_file, "media-size", value);
877            bkpinfo->media_size[1] = atol(value);
878            paranoid_free(value);
879
880            asprintf(&tmp, "Backup medium is TAPE --- dev=%s",
881                    bkpinfo->media_device);
882            log_msg(2, tmp);
883            paranoid_free(tmp);
884        } else {
885            paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
886            bkpinfo->media_size[0] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
887            bkpinfo->media_size[1] = 1999 * 1024;   /* 650, probably, but we don't need this var anyway */
888            log_msg(2, "Backup medium is CD-R[W]");
889        }
890    } else {
891        log_msg(2,
892                "Not in Disaster Recovery Mode. No need to derive device name from config file.");
893    }
894
895    read_cfg_var(cfg_file, "use-star", value);
896    if (strstr(value, "yes")) {
897        bkpinfo->use_star = TRUE;
898        log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
899    }
900    paranoid_free(value);
901
902    if (0 == read_cfg_var(cfg_file, "internal-tape-block-size", value)) {
903        bkpinfo->internal_tape_block_size = atol(value);
904        log_msg(1, "Internal tape block size has been custom-set to %ld",
905                bkpinfo->internal_tape_block_size);
906    } else {
907        bkpinfo->internal_tape_block_size =
908            DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
909        log_msg(1, "Internal tape block size = default (%ld)",
910                DEFAULT_INTERNAL_TAPE_BLOCK_SIZE);
911    }
912    paranoid_free(value);
913
914    read_cfg_var(cfg_file, "use-lzo", value);
915    if (strstr(value, "yes")) {
916        bkpinfo->use_lzo = TRUE;
917        paranoid_alloc(bkpinfo->zip_exe, "lzop");
918        paranoid_alloc(bkpinfo->zip_suffix, "lzo");
919    } else {
920        paranoid_free(value);
921        read_cfg_var(cfg_file, "use-comp", value);
922        if (strstr(value, "yes")) {
923            bkpinfo->use_lzo = FALSE;
924            paranoid_alloc(bkpinfo->zip_exe, "bzip2");
925            paranoid_alloc(bkpinfo->zip_suffix, "bz2");
926        } else {
927            // Just to be sure
928            bkpinfo->zip_exe = NULL;
929            bkpinfo->zip_suffix = NULL;
930        }
931    }
932    paranoid_free(value);
933
934    read_cfg_var(cfg_file, "differential", value);
935    if (!strcmp(value, "yes") || !strcmp(value, "1")) {
936        bkpinfo->differential = TRUE;
937    }
938    log_msg(2, "differential var = '%s'", value);
939    paranoid_free(value);
940
941    if (bkpinfo->differential) {
942        log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
943    } else {
944        log_msg(2, "This is a regular (full) backup");
945    }
946
947    read_cfg_var(g_mondo_cfg_file, "please-dont-eject", tmp);
948#ifdef __FreeBSD__
949    tmp1 = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
950#else
951    tmp1 = call_program_and_get_last_line_of_output("cat /proc/cmdline");
952#endif
953    if ((tmp != NULL) || strstr(tmp1,"donteject")) {
954        bkpinfo->please_dont_eject = TRUE;
955        log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
956    }
957    paranoid_free(tmp);
958    paranoid_free(tmp1);
959
960    if (bkpinfo->backup_media_type == nfs) {
961        if (!cfgf) {
962            log_msg(2, "nfs_mount remains %s", bkpinfo->nfs_mount);
963            log_msg(2, "nfs_remote_dir remains %s",
964                    bkpinfo->nfs_remote_dir);
965            log_msg(2,
966                    "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
967        } else {
968            paranoid_free(bkpinfo->nfs_mount);
969            paranoid_free(bkpinfo->nfs_remote_dir);
970            read_cfg_var(g_mondo_cfg_file, "nfs-server-mount",
971                         bkpinfo->nfs_mount);
972            read_cfg_var(g_mondo_cfg_file, "nfs-server-path",
973                         bkpinfo->nfs_remote_dir);
974            log_msg(2, "nfs_mount is %s", bkpinfo->nfs_mount);
975            log_msg(2, "nfs_remote_dir is %s", bkpinfo->nfs_remote_dir);
976        }
977    } else if (bkpinfo->backup_media_type == iso) {
978        /* Patch by Conor Daly 23-june-2004
979         * to correctly mount iso-dev and set a sensible
980         * isodir in disaster recovery mode
981         */
982        paranoid_alloc(old_isodir,bkpinfo->isodir);
983        read_cfg_var(g_mondo_cfg_file, "iso-mnt", iso_mnt);
984        read_cfg_var(g_mondo_cfg_file, "isodir", iso_path);
985        if (iso_mnt && iso_path) {
986            paranoid_free(bkpinfo->isodir);
987            asprintf(&bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
988        }
989        paranoid_free(iso_mnt);
990        paranoid_free(iso_path);
991
992        if (!bkpinfo->disaster_recovery) {
993            if (strcmp(old_isodir, bkpinfo->isodir)) {
994                log_it
995                    ("user nominated isodir differs from archive, keeping user's choice: %s %s\n",
996                     old_isodir, bkpinfo->isodir);
997            }
998        }
999        paranoid_free(old_isodir);
1000
1001        paranoid_free(g_isodir_device);
1002        read_cfg_var(g_mondo_cfg_file, "iso-dev", g_isodir_device);
1003        log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
1004        if (bkpinfo->disaster_recovery) {
1005            if (is_this_device_mounted(g_isodir_device)) {
1006                log_msg(2, "NB: isodir is already mounted");
1007                /* Find out where it's mounted */
1008                asprintf(&command,
1009                        "mount | grep -w %s | tail -n1 | cut -d' ' -f3",
1010                        g_isodir_device);
1011                log_it("command = %s", command);
1012                tmp = call_program_and_get_last_line_of_output(command);
1013                log_it("res of it = %s", tmp);
1014                iso_mnt = tmp;
1015                paranoid_free(command);
1016            } else {
1017                asprintf(&iso_mnt, "/tmp/isodir");
1018                asprintf(&tmp, "mkdir -p %s", iso_mnt);
1019                run_program_and_log_output(tmp, 5);
1020                paranoid_free(tmp);
1021
1022                asprintf(&tmp, "mount %s %s", g_isodir_device, iso_mnt);
1023                if (run_program_and_log_output(tmp, 3)) {
1024                    log_msg(1,
1025                            "Unable to mount isodir. Perhaps this is really a CD backup?");
1026                    bkpinfo->backup_media_type = cdr;
1027                    paranoid_alloc(bkpinfo->media_device, "/dev/cdrom");
1028                    paranoid_free(bkpinfo->isodir);
1029                    paranoid_free(iso_mnt);
1030                    paranoid_free(iso_path);
1031                    asprintf(&iso_mnt, "%s", "");
1032                    asprintf(&iso_path, "%s", "");
1033
1034                    if (mount_cdrom(bkpinfo)) {
1035                        fatal_error
1036                            ("Unable to mount isodir. Failed to mount CD-ROM as well.");
1037                    } else {
1038                        log_msg(1,
1039                                "You backed up to disk, then burned some CDs. Naughty monkey!");
1040                    }
1041                }
1042                paranoid_free(tmp);
1043            }
1044            /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1045            if (bkpinfo->backup_media_type == iso) {
1046                paranoid_free(bkpinfo->isodir);
1047                asprintf(&bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
1048            }
1049            paranoid_free(iso_mnt);
1050            paranoid_free(iso_path);
1051        }
1052    }
1053
1054    if (media_specified_by_user != none) {
1055        if (g_restoring_live_from_cd) {
1056            if (bkpinfo->backup_media_type != media_specified_by_user) {
1057                log_msg(2,
1058                        "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1059                interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
1060                media_specified_by_user = bkpinfo->backup_media_type;
1061                get_cfg_file_from_archive(bkpinfo);
1062/*
1063              if (media_specified_by_user != cdr && media_specified_by_user == cdrw)
1064                { g_restoring_live_from_cd = FALSE; }
1065*/
1066            }
1067        }
1068        bkpinfo->backup_media_type = media_specified_by_user;
1069    }
1070    g_backup_media_type = bkpinfo->backup_media_type;
1071    bkpinfo->backup_media_string = bkptype_to_string(bkpinfo->backup_media_type);
1072    g_backup_media_string = bkpinfo->backup_media_string;
1073    return (0);
1074}
1075/**************************************************************************
1076 *END_READ_CFG_FILE_INTO_BKPINFO                                          *
1077 **************************************************************************/
1078
1079
1080/**
1081 * Allow the user to edit the filelist and biggielist.
1082 * The filelist is unlinked after it is read.
1083 * @param bkpinfo The backup information structure. Fields used:
1084 * - @c bkpinfo->backup_media_type
1085 * - @c bkpinfo->isodir
1086 * - @c bkpinfo->media_device
1087 * - @c bkpinfo->tmpdir
1088 * @return The filelist structure containing the information read from disk.
1089 */
1090struct
1091s_node *process_filelist_and_biggielist(struct s_bkpinfo *bkpinfo)
1092{
1093    struct s_node *filelist;
1094
1095    char *command = NULL;
1096    char *tmp = NULL;
1097    int res = 0;
1098    size_t n = 0;
1099    pid_t pid;
1100
1101    assert(bkpinfo != NULL);
1102    malloc_string(tmp);
1103
1104    if (does_file_exist(g_filelist_full)
1105        && does_file_exist(g_biggielist_txt)) {
1106        log_msg(1, "%s exists", g_filelist_full);
1107        log_msg(1, "%s exists", g_biggielist_txt);
1108        log_msg(2,
1109                "Filelist and biggielist already recovered from media. Yay!");
1110    } else {
1111        getcwd(tmp, MAX_STR_LEN);
1112        chdir(bkpinfo->tmpdir);
1113        log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1114        log_to_screen("Extracting filelist and biggielist from media...");
1115        unlink("/tmp/filelist.full");
1116        unlink("/" FILELIST_FULL_STUB);
1117        unlink("/tmp/i-want-my-lvm");
1118        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1119            asprintf(&command,
1120                    "tar -zxf %s %s %s %s %s %s",
1121                    bkpinfo->media_device,
1122                    MOUNTLIST_FNAME_STUB,
1123                    BIGGIELIST_TXT_STUB,
1124                    FILELIST_FULL_STUB,
1125                    "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1126            log_msg(1, "tarcommand = %s", command);
1127            run_program_and_log_output(command, 1);
1128            paranoid_free(command);
1129        } else {
1130            log_msg(2,
1131                    "Calling insist_on_this_cd_number; bkpinfo->isodir=%s",
1132                    bkpinfo->isodir);
1133            insist_on_this_cd_number(bkpinfo, 1);
1134            log_msg(2, "Back from iotcn");
1135            run_program_and_log_output("mount", 1);
1136            asprintf(&command,
1137                    "tar -zxf %s/images/all.tar.gz %s %s %s %s %s",
1138                    MNT_CDROM,
1139                    MOUNTLIST_FNAME_STUB,
1140                    BIGGIELIST_TXT_STUB,
1141                    FILELIST_FULL_STUB,
1142                    "tmp/i-want-my-lvm", MONDO_CFG_FILE_STUB);
1143
1144            log_msg(1, "tarcommand = %s", command);
1145            run_program_and_log_output(command, 1);
1146            paranoid_free(command);
1147
1148            if (!does_file_exist(BIGGIELIST_TXT_STUB)) {
1149                fatal_error
1150                    ("all.tar.gz did not include tmp/biggielist.txt");
1151            }
1152            if (!does_file_exist(FILELIST_FULL_STUB)) {
1153                fatal_error
1154                    ("all.tar.gz did not include tmp/filelist.full.gz");
1155            }
1156        }
1157        asprintf(&command, "cp -f %s %s", MONDO_CFG_FILE_STUB,
1158                g_mondo_cfg_file);
1159        run_program_and_log_output(command, FALSE);
1160        paranoid_free(command);
1161
1162        asprintf(&command, "cp -f %s/%s %s", bkpinfo->tmpdir,
1163                BIGGIELIST_TXT_STUB, g_biggielist_txt);
1164        log_msg(1, "command = %s", command);
1165        paranoid_system(command);
1166        paranoid_free(command);
1167
1168        asprintf(&command, "ln -sf %s/%s %s", bkpinfo->tmpdir,
1169                FILELIST_FULL_STUB, g_filelist_full);
1170        log_msg(1, "command = %s", command);
1171        paranoid_system(command);
1172        paranoid_free(command);
1173    }
1174
1175    if (am_I_in_disaster_recovery_mode()
1176        &&
1177        ask_me_yes_or_no(_
1178                         ("Do you want to retrieve the mountlist as well?")))
1179    {
1180        asprintf(&command, "ln -sf %s/%s /tmp", MOUNTLIST_FNAME_STUB,
1181                bkpinfo->tmpdir);
1182        paranoid_system(command);
1183        paranoid_free(command);
1184    }
1185
1186    chdir(tmp);
1187    paranoid_free(tmp);
1188
1189    if (!does_file_exist(g_biggielist_txt)) {
1190        log_msg(1, "Warning - %s not found", g_biggielist_txt);
1191    }
1192    if (!does_file_exist(g_filelist_full)) {
1193        log_msg(1, "Warning - %s does not exist", g_filelist_full);
1194    }
1195//  popup_and_OK("Wonderful.");
1196
1197    log_msg(2, "Forking");
1198    pid = fork();
1199    switch (pid) {
1200    case -1:
1201        fatal_error("Forking error");
1202        break;
1203
1204    case 0:
1205        log_to_screen(("Pre-processing filelist"));
1206        if (!does_file_exist(g_biggielist_txt)) {
1207            asprintf(&command, "> %s", g_biggielist_txt);
1208            paranoid_system(command);
1209            paranoid_free(command);
1210        }
1211        asprintf(&command, "grep  -x \"/dev/.*\" %s > %s",
1212                g_biggielist_txt, g_filelist_imagedevs);
1213        paranoid_system(command);
1214        paranoid_free(command);
1215        exit(0);
1216        break;
1217
1218    default:
1219        open_evalcall_form(_("Pre-processing filelist"));
1220        while (!waitpid(pid, (int *) 0, WNOHANG)) {
1221            usleep(100000);
1222            update_evalcall_form(0);
1223        }
1224    }
1225    close_evalcall_form();
1226
1227    log_msg(3, "loading filelist");
1228    filelist = load_filelist(g_filelist_full);
1229    log_msg(3, "deleting original filelist");
1230    unlink(g_filelist_full);
1231    if (g_text_mode) {
1232        printf(_("Restore which directory? --> "));
1233        getline(&tmp, &n, stdin);
1234        toggle_path_selection(filelist, tmp, TRUE);
1235        if (strlen(tmp) == 0) {
1236            res = 1;
1237        } else {
1238            res = 0;
1239        }
1240        paranoid_free(tmp);
1241    } else {
1242        res = edit_filelist(filelist);
1243    }
1244    if (res) {
1245        log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1246        free_filelist(filelist);
1247        return (NULL);
1248    }
1249    ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1250    close_evalcall_form();
1251
1252    // NB: It's not necessary to add g_biggielist_txt to the filelist.full
1253    // file. The filelist.full file already contains the filename of EVERY
1254    // file backed up - regular and biggie files.
1255
1256    // However, we do want to make sure the imagedevs selected by the user
1257    // are flagged for restoring.
1258    if (length_of_file(g_imagedevs_restthese) > 2) {
1259        add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1260                                      TRUE);
1261    }
1262    return (filelist);
1263}
1264/**************************************************************************
1265 *END_ PROCESS_FILELIST_AND_BIGGIELIST                                    *
1266 **************************************************************************/
1267
1268
1269/**
1270 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1271 * The backup filename is the filename of the original with ".pristine" added.
1272 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1273 * @param filename The filename (absolute path) within @p path_root.
1274 * @return 0 for success, nonzero for failure.
1275 */
1276int backup_crucial_file(char *path_root, char *filename)
1277{
1278    char *command = NULL;
1279    int res = 0;
1280
1281    assert(path_root != NULL);
1282    assert_string_is_neither_NULL_nor_zerolength(filename);
1283
1284    asprintf(&command, "cp -f %s/%s %s/%s.pristine", path_root, filename,path_root, filename);
1285    res = run_program_and_log_output(command, 5);
1286    paranoid_free(command);
1287    return (res);
1288}
1289
1290
1291/**
1292 * Install the user's boot loader in the MBR.
1293 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1294 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1295 * @return 0 for success, nonzero for failure.
1296 */
1297int run_boot_loader(bool offer_to_hack_scripts)
1298{
1299    int res;
1300    int retval = 0;
1301
1302    char *device = NULL;
1303    char *tmp = NULL;
1304    char *name = NULL;
1305
1306    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1307    backup_crucial_file(MNT_RESTORING, "/etc/grub.conf");
1308    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1309    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1310    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
1311    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
1312    asprintf(&tmp, "run_boot_loader: device='%s', name='%s'", device, name);
1313    log_msg(2, tmp);
1314    paranoid_free(tmp);
1315
1316    sync();
1317    if (!strcmp(name, "LILO")) {
1318        res = run_lilo(offer_to_hack_scripts);
1319    } else if (!strcmp(name, "ELILO")) {
1320        res = run_elilo(offer_to_hack_scripts);
1321    } else if (!strcmp(name, "GRUB")) {
1322//      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?")))
1323//        {
1324        res = run_grub(offer_to_hack_scripts, device);
1325//    unlink(DO_MBR_PLEASE);
1326//  }
1327//      else
1328//        {
1329//    log_msg(1, "Not running run_grub(). Was a bad idea anyway.");
1330//    res = 1;
1331//  }
1332    } else if (!strcmp(name, "RAW")) {
1333        res = run_raw_mbr(offer_to_hack_scripts, device);
1334    }
1335#ifdef __FreeBSD__
1336    else if (!strcmp(name, "BOOT0")) {
1337        asprintf(&tmp, "boot0cfg -B %s", device);
1338        res = run_program_and_log_output(tmp, FALSE);
1339        paranoid_free(tmp);
1340    } else {
1341        asprintf(&tmp, "ls /dev | grep -xq %ss[1-4].*", device);
1342        if (!system(tmp)) {
1343            paranoid_free(tmp);
1344            asprintf(&tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1345            res = run_program_and_log_output(tmp, 3);
1346        } else {
1347            log_msg(1,
1348                    "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1349        }
1350        paranoid_free(tmp);
1351    }
1352#else
1353    else {
1354        log_to_screen
1355            (_
1356             ("Unable to determine type of boot loader. Defaulting to LILO."));
1357        res = run_lilo(offer_to_hack_scripts);
1358    }
1359#endif
1360    paranoid_free(device);
1361    paranoid_free(name);
1362
1363    retval += res;
1364    if (res) {
1365        log_to_screen(_("Your boot loader returned an error"));
1366    } else {
1367        log_to_screen(_("Your boot loader ran OK"));
1368    }
1369    return (retval);
1370}
1371/**************************************************************************
1372 *END_ RUN_BOOT_LOADER                                                    *
1373 **************************************************************************/
1374
1375
1376/**
1377 * Attempt to find the user's editor.
1378 * @return The editor found ("vi" if none could be found).
1379 * @note The returned string points to malloced storage that needs to be freed by caller
1380 */
1381char *find_my_editor(void)
1382{
1383    char *output = NULL;
1384    char *tmp = NULL;
1385
1386    /* BERLIOS: This should use $EDITOR + conf file rather first */
1387    tmp = find_home_of_exe("pico");
1388    if (tmp) {
1389        asprintf(&output, "pico");
1390    } else {
1391        tmp = find_home_of_exe("nano");
1392        if (tmp) {
1393            asprintf(&output, "nano");
1394        } else {
1395            tmp = find_home_of_exe("vi");
1396            if (tmp) {
1397                asprintf(&output, "vi");
1398            } else {
1399                asprintf(&output, "emacs");
1400            }
1401        }
1402    }
1403    paranoid_free(tmp);
1404
1405    tmp = find_home_of_exe(output);
1406    if (!tmp) {
1407        log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1408    }
1409    paranoid_free(tmp);
1410    return (output);
1411}
1412
1413
1414/**
1415 * Install GRUB on @p bd.
1416 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1417 * @param bd The boot device where GRUB is installed.
1418 * @return 0 for success, nonzero for failure.
1419 */
1420int run_grub(bool offer_to_run_stabgrub, char *bd)
1421{
1422    char *command = NULL;
1423    char *tmp = NULL;
1424    char *editor = NULL;
1425
1426    int res = 0;
1427    int done = 0;
1428
1429    assert_string_is_neither_NULL_nor_zerolength(bd);
1430
1431    if (offer_to_run_stabgrub
1432        && ask_me_yes_or_no(_("Did you change the mountlist?")))
1433        /* interactive mode */
1434    {
1435        mvaddstr_and_log_it(g_currentY,
1436                            0,
1437                            _
1438                            ("Modifying fstab and grub.conf, and running GRUB...                             "));
1439        for (done = FALSE; !done;) {
1440            popup_and_get_string(_("Boot device"),
1441                                 _("Please confirm/enter the boot device. If in doubt, try /dev/hda"), bd);
1442            asprintf(&command, "stabgrub-me %s", bd);
1443            res = run_program_and_log_output(command, 1);
1444            paranoid_free(command);
1445
1446            if (res) {
1447                popup_and_OK
1448                    (_
1449                     ("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."));
1450                newtSuspend();
1451                system("chroot " MNT_RESTORING);
1452                newtResume();
1453                popup_and_OK(_("Thank you."));
1454            } else {
1455                done = TRUE;
1456            }
1457            popup_and_OK(_("You will now edit fstab and grub.conf"));
1458            if (!g_text_mode) {
1459                newtSuspend();
1460            }
1461            editor = find_my_editor();
1462            asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1463            paranoid_system(tmp);
1464            paranoid_free(tmp);
1465
1466            asprintf(&tmp, "%s " MNT_RESTORING "/etc/grub.conf", editor);
1467            paranoid_free(editor);
1468
1469            paranoid_system(tmp);
1470            paranoid_free(tmp);
1471
1472            if (!g_text_mode) {
1473                newtResume();
1474            }
1475        }
1476    } else {
1477        /* nuke mode */
1478        if (!run_program_and_log_output("which grub-MR", FALSE)) {
1479            log_msg(1, "Yay! grub-MR found...");
1480            asprintf(&command, "grub-MR %s /tmp/mountlist.txt", bd);
1481            log_msg(1, "command = %s", command);
1482        } else {
1483            asprintf(&command, "chroot " MNT_RESTORING " grub-install %s", bd);
1484            log_msg(1, "WARNING - grub-MR not found; using grub-install");
1485        }
1486        mvaddstr_and_log_it(g_currentY,
1487                            0,
1488                            _
1489                            ("Running GRUB...                                                 "));
1490        iamhere(command);
1491        res = run_program_and_log_output(command, 1);
1492        paranoid_free(command);
1493
1494        if (res) {
1495            popup_and_OK
1496                (_
1497                 ("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."));
1498            newtSuspend();
1499            system("chroot " MNT_RESTORING);
1500            newtResume();
1501            popup_and_OK(_("Thank you."));
1502        }
1503    }
1504    if (res) {
1505        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1506        log_to_screen
1507            (_
1508             ("GRUB ran w/error(s). See /tmp/mondo-restore.log for more info."));
1509        log_msg(1, "Type:-");
1510        log_msg(1, "    mount-me");
1511        log_msg(1, "    chroot " MNT_RESTORING);
1512        log_msg(1, "    mount /boot");
1513        log_msg(1, "    grub-install '(hd0)'");
1514        log_msg(1, "    exit");
1515        log_msg(1, "    unmount-me");
1516        log_msg(1,
1517                "If you're really stuck, please e-mail the mailing list.");
1518    } else {
1519        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1520    }
1521    return (res);
1522}
1523/**************************************************************************
1524 *END_RUN_GRUB                                                            *
1525 **************************************************************************/
1526
1527
1528/**
1529 * Install ELILO on the user's boot drive (determined by elilo.conf).
1530 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1531 * @return 0 for success, nonzero for failure.
1532 */
1533int run_elilo(bool offer_to_run_stabelilo)
1534{
1535    char *command = NULL;
1536    char *tmp = NULL;
1537    char *editor = NULL;
1538
1539    int res = 0;
1540    int done = 0;
1541
1542    if (offer_to_run_stabelilo
1543        && ask_me_yes_or_no(_("Did you change the mountlist?")))
1544
1545        /* interactive mode */
1546    {
1547        mvaddstr_and_log_it(g_currentY,
1548                            0,
1549                            _
1550                            ("Modifying fstab and elilo.conf...                             "));
1551        asprintf(&command, "stabelilo-me");
1552        res = run_program_and_log_output(command, 3);
1553        paranoid_free(command);
1554
1555        if (res) {
1556            popup_and_OK
1557                (_
1558                 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist."));
1559            for (done = FALSE; !done;) {
1560                if (!g_text_mode) {
1561                    newtSuspend();
1562                }
1563                editor = find_my_editor();
1564                asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1565                paranoid_system(tmp);
1566                paranoid_free(tmp);
1567
1568                asprintf(&tmp, "%s " MNT_RESTORING "/etc/elilo.conf", editor);
1569                paranoid_free(editor);
1570
1571                paranoid_system(tmp);
1572                paranoid_free(tmp);
1573
1574                if (!g_text_mode) {
1575                    newtResume();
1576                }
1577//              newtCls();
1578                if (ask_me_yes_or_no(_("Edit them again?"))) {
1579                    continue;
1580                }
1581                done = TRUE;
1582            }
1583        } else {
1584            log_to_screen(_("elilo.conf and fstab were modified OK"));
1585        }
1586    } else
1587        /* nuke mode */
1588    {
1589        res = TRUE;
1590    }
1591    return (res);
1592}
1593/**************************************************************************
1594 *END_RUN_ELILO                                                            *
1595 **************************************************************************/
1596
1597
1598/**
1599 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1600 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1601 * @return 0 for success, nonzero for failure.
1602 */
1603int run_lilo(bool offer_to_run_stablilo)
1604{
1605  /** malloc **/
1606    char *command = NULL;
1607    char *tmp = NULL;
1608    char *editor = NULL;
1609
1610    int res = 0;
1611    int done = 0;
1612    bool run_lilo_M = FALSE;
1613
1614    if (!run_program_and_log_output
1615        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1616        run_lilo_M = TRUE;
1617    }
1618
1619    if (offer_to_run_stablilo
1620        && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1621        /* interactive mode */
1622        mvaddstr_and_log_it(g_currentY,
1623                            0,
1624                            _
1625                            ("Modifying fstab and lilo.conf, and running LILO...                             "));
1626        asprintf(&command, "stablilo-me");
1627        res = run_program_and_log_output(command, 3);
1628        paranoid_free(command);
1629
1630        if (res) {
1631            popup_and_OK
1632                (_
1633                 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist."));
1634            for (done = FALSE; !done;) {
1635                if (!g_text_mode) {
1636                    newtSuspend();
1637                }
1638                editor = find_my_editor();
1639                asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1640                paranoid_system(tmp);
1641                paranoid_free(tmp);
1642
1643                asprintf(&tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1644                paranoid_free(editor);
1645
1646                paranoid_system(tmp);
1647                paranoid_free(tmp);
1648
1649                if (!g_text_mode) {
1650                    newtResume();
1651                }
1652//              newtCls();
1653                if (ask_me_yes_or_no(_("Edit them again?"))) {
1654                    continue;
1655                }
1656                res =
1657                    run_program_and_log_output("chroot " MNT_RESTORING
1658                                               " lilo -L", 3);
1659                if (res) {
1660                    res =
1661                        run_program_and_log_output("chroot " MNT_RESTORING
1662                                                   " lilo", 3);
1663                }
1664                if (res) {
1665                    done =
1666                        ask_me_yes_or_no
1667                        (_("LILO failed. Re-edit system files?"));
1668                } else {
1669                    done = TRUE;
1670                }
1671            }
1672        } else {
1673            log_to_screen(_("lilo.conf and fstab were modified OK"));
1674        }
1675    } else {
1676        /* nuke mode */
1677        mvaddstr_and_log_it(g_currentY,
1678                            0,
1679                            _
1680                            ("Running LILO...                                                 "));
1681        res =
1682            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1683                                       3);
1684        if (res) {
1685            res =
1686                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1687                                           3);
1688        }
1689        if (res) {
1690            mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1691            log_to_screen
1692                (_
1693                 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please."));
1694        } else {
1695            mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1696        }
1697    }
1698    if (run_lilo_M) {
1699        run_program_and_log_output("chroot " MNT_RESTORING
1700                                   " lilo -M /dev/hda", 3);
1701        run_program_and_log_output("chroot " MNT_RESTORING
1702                                   " lilo -M /dev/sda", 3);
1703    }
1704    return (res);
1705}
1706
1707/**************************************************************************
1708 *END_RUN_LILO                                                            *
1709 **************************************************************************/
1710
1711
1712/**
1713 * Install a raw MBR onto @p bd.
1714 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1715 * @param bd The device to copy the stored MBR to.
1716 * @return 0 for success, nonzero for failure.
1717 */
1718int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1719{
1720    char *command = NULL;
1721    char *tmp = NULL;
1722    char *editor = NULL;
1723    int res = 0;
1724    int done = 0;
1725
1726    assert_string_is_neither_NULL_nor_zerolength(bd);
1727
1728    if (offer_to_hack_scripts
1729        && ask_me_yes_or_no(_("Did you change the mountlist?"))) {
1730        /* interactive mode */
1731        mvaddstr_and_log_it(g_currentY, 0,
1732                            _
1733                            ("Modifying fstab and restoring MBR...                           "));
1734        for (done = FALSE; !done;) {
1735            if (!run_program_and_log_output("which vi", FALSE)) {
1736                popup_and_OK(_("You will now edit fstab"));
1737                if (!g_text_mode) {
1738                    newtSuspend();
1739                }
1740                editor = find_my_editor();
1741                asprintf(&tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1742                paranoid_free(editor);
1743
1744                paranoid_system(tmp);
1745                paranoid_free(tmp);
1746
1747                if (!g_text_mode) {
1748                    newtResume();
1749                }
1750//              newtCls();
1751            }
1752            popup_and_get_string(_("Boot device"),
1753                                 _
1754                                 ("Please confirm/enter the boot device. If in doubt, try /dev/hda"), bd);
1755            asprintf(&command, "stabraw-me %s", bd);
1756            res = run_program_and_log_output(command, 3);
1757            paranoid_free(command);
1758
1759            if (res) {
1760                done =
1761                    ask_me_yes_or_no(_("Modifications failed. Re-try?"));
1762            } else {
1763                done = TRUE;
1764            }
1765        }
1766    } else {
1767        /* nuke mode */
1768        mvaddstr_and_log_it(g_currentY, 0,
1769                            _
1770                            ("Restoring MBR...                                               "));
1771        asprintf(&command, "raw-MR %s /tmp/mountlist.txt", bd);
1772        log_msg(2, "run_raw_mbr() --- command='%s'", command);
1773        res = run_program_and_log_output(command, 3);
1774        paranoid_free(command);
1775    }
1776    if (res) {
1777        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
1778        log_to_screen
1779            (_
1780             ("MBR+fstab processed w/error(s). See /tmp/mondo-restore.log for more info."));
1781    } else {
1782        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1783    }
1784    return (res);
1785}
1786/**************************************************************************
1787 *END_RUN_RAW_MBR                                                         *
1788 **************************************************************************/
1789
1790
1791/**
1792 * Turn signal trapping on or off.
1793 * @param on If TRUE, then do full cleanup when we receive a signal; if FALSE, then
1794 * print a message and exit immediately.
1795 */
1796void set_signals(int on)
1797{
1798    int signals[] =
1799        { SIGKILL, SIGPIPE, SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT,
1800        SIGSTOP, 0
1801    };
1802    int i;
1803    for (i = 0; signals[i]; i++) {
1804        if (on) {
1805            signal(signals[i], terminate_daemon);
1806        } else {
1807            signal(signals[i], termination_in_progress);
1808        }
1809    }
1810}
1811
1812/**************************************************************************
1813 *END_SET_SIGNALS                                                         *
1814 **************************************************************************/
1815
1816
1817/**
1818 * malloc() and set sensible defaults for the mondorestore filename variables.
1819 * @param bkpinfo The backup information structure. Fields used:
1820 * - @c bkpinfo->tmpdir
1821 * - @c bkpinfo->disaster_recovery
1822 */
1823void setup_MR_global_filenames(struct s_bkpinfo *bkpinfo)
1824{
1825    assert(bkpinfo != NULL);
1826
1827    asprintf(&g_biggielist_txt, "%s/%s",bkpinfo->tmpdir , BIGGIELIST_TXT_STUB);
1828    asprintf(&g_filelist_full, "%s/%s", bkpinfo->tmpdir, FILELIST_FULL_STUB);
1829    asprintf(&g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1830    asprintf(&g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these",
1831            bkpinfo->tmpdir);
1832    paranoid_free(g_mondo_cfg_file);
1833    paranoid_free(g_mountlist_fname);
1834    if (bkpinfo->disaster_recovery) {
1835        asprintf(&g_mondo_cfg_file, "/%s", MONDO_CFG_FILE_STUB);
1836        asprintf(&g_mountlist_fname, "/%s", MOUNTLIST_FNAME_STUB);
1837    } else {
1838        asprintf(&g_mondo_cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
1839        asprintf(&g_mountlist_fname, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
1840    }
1841}
1842/**************************************************************************
1843 *END_SET_GLOBAL_FILENAME                                                 *
1844 **************************************************************************/
1845
1846
1847/**
1848 * Copy @p input_file (containing the result of a compare) to @p output_file,
1849 * deleting spurious "changes" along the way.
1850 * @param output_file The output file to write with spurious changes removed.
1851 * @param input_file The input file, a list of changed files created by a compare.
1852 */
1853void streamline_changes_file(char *output_file, char *input_file)
1854{
1855    FILE *fin;
1856    FILE *fout;
1857    char *incoming = NULL;
1858    size_t n = 0;
1859
1860    assert_string_is_neither_NULL_nor_zerolength(output_file);
1861    assert_string_is_neither_NULL_nor_zerolength(input_file);
1862
1863    if (!(fin = fopen(input_file, "r"))) {
1864        log_OS_error(input_file);
1865        return;
1866    }
1867    if (!(fout = fopen(output_file, "w"))) {
1868        fatal_error("cannot open output_file");
1869    }
1870    for (getline(&incoming, &n, fin); !feof(fin);
1871         getline(&incoming, &n, fin)) {
1872        if (strncmp(incoming, "etc/adjtime", 11)
1873            && strncmp(incoming, "etc/mtab", 8)
1874            && strncmp(incoming, "tmp/", 4)
1875            && strncmp(incoming, "boot/map", 8)
1876            && !strstr(incoming, "incheckentry")
1877            && strncmp(incoming, "etc/mail/statistics", 19)
1878            && strncmp(incoming, "var/", 4))
1879            fprintf(fout, "%s", incoming);  /* don't need \n here, for some reason.. */
1880    }
1881    paranoid_free(incoming);
1882    paranoid_fclose(fout);
1883    paranoid_fclose(fin);
1884}
1885/**************************************************************************
1886 *END_STREAMLINE_CHANGES_FILE                                             *
1887 **************************************************************************/
1888
1889
1890/**
1891 * Exit due to a signal (normal cleanup).
1892 * @param sig The signal we're exiting due to.
1893 */
1894void terminate_daemon(int sig)
1895{
1896    log_to_screen
1897        (_
1898         ("Mondorestore is terminating in response to a signal from the OS"));
1899    paranoid_MR_finish(254);
1900}
1901/**************************************************************************
1902 *END_TERMINATE_DAEMON                                                    *
1903 **************************************************************************/
1904
1905
1906/**
1907 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1908 */
1909void twenty_seconds_til_yikes()
1910{
1911    int i;
1912    char *tmp = NULL;
1913
1914    if (does_file_exist("/tmp/NOPAUSE")) {
1915        return;
1916    }
1917    open_progress_form(_("CAUTION"),
1918                       _
1919                       ("Be advised: I am about to ERASE your hard disk(s)!"),
1920                       _("You may press Ctrl+Alt+Del to abort safely."),
1921                       "", 20);
1922    for (i = 0; i < 20; i++) {
1923        g_current_progress = i;
1924        asprintf(&tmp, _("You have %d seconds left to abort."), 20 - i);
1925        update_progress_form(tmp);
1926        paranoid_free(tmp);
1927        sleep(1);
1928    }
1929    close_progress_form();
1930}
1931/**************************************************************************
1932 *END_TWENTY_SECONDS_TIL_YIKES                                            *
1933 **************************************************************************/
1934
1935
1936/**
1937 * Exit due to a signal (no cleanup).
1938 * @param sig The signal we're exiting due to.
1939 */
1940void termination_in_progress(int sig)
1941{
1942    log_msg(1, "Termination in progress");
1943    usleep(1000);
1944    pthread_exit(0);
1945}
1946/**************************************************************************
1947 *END_TERMINATION_IN_PROGRESS                                             *
1948 **************************************************************************/
1949
1950
1951/**
1952 * Unmount all devices in @p p_external_copy_of_mountlist.
1953 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1954 * @return 0 for success, nonzero for failure.
1955 */
1956int unmount_all_devices(struct mountlist_itself
1957                        *p_external_copy_of_mountlist)
1958{
1959    struct mountlist_itself *mountlist;
1960    int retval = 0;
1961    int lino = 0;
1962    int res = 0;
1963    int i = 0;
1964    char *command = NULL;
1965    char *tmp = NULL;
1966    char *tmp1 = NULL;
1967
1968    assert(p_external_copy_of_mountlist != NULL);
1969
1970    mountlist = malloc(sizeof(struct mountlist_itself));
1971    memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1972           sizeof(struct mountlist_itself));
1973    sort_mountlist_by_mountpoint(mountlist, 0);
1974
1975    run_program_and_log_output("df -m", 3);
1976    mvaddstr_and_log_it(g_currentY, 0, _("Unmounting devices      "));
1977    open_progress_form(_("Unmounting devices"),
1978                       _("Unmounting all devices that were mounted,"),
1979                       _
1980                       ("in preparation for the post-restoration reboot."),
1981                       "", mountlist->entries);
1982    chdir("/");
1983    for (i = 0;
1984         i < 10
1985         &&
1986         run_program_and_log_output
1987         ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1988         i++) {
1989        sleep(1);
1990        log_msg(2, "Waiting for buffer() to finish");
1991    }
1992
1993    sync();
1994
1995    if (run_program_and_log_output
1996        ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/tmp/", FALSE)) {
1997        log_msg(1,
1998                "Error. Failed to copy log to PC's /tmp dir. (Mounted read-only?)");
1999    }
2000    if (run_program_and_log_output
2001        ("cp -f /tmp/mondo-restore.log " MNT_RESTORING "/root/", FALSE)) {
2002        log_msg(1,
2003                "Error. Failed to copy log to PC's /root dir. (Mounted read-only?)");
2004    }
2005    if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
2006        run_program_and_log_output("mkdir -p " MNT_RESTORING
2007                                   "/mnt/.boot.d", 5);
2008    }
2009    for (lino = mountlist->entries - 1; lino >= 0; lino--) {
2010        if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2011            continue;
2012        }
2013        asprintf(&tmp, _("Unmounting device %s  "),
2014                mountlist->el[lino].device);
2015
2016        update_progress_form(tmp);
2017
2018        if (is_this_device_mounted(mountlist->el[lino].device)) {
2019            if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2020                asprintf(&command, "swapoff %s", mountlist->el[lino].device);
2021            } else {
2022                if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2023                    asprintf(&command, "umount %s/", MNT_RESTORING);
2024                    log_msg(3,
2025                            "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2026                } else {
2027                    asprintf(&command, "umount " MNT_RESTORING "%s",
2028                            mountlist->el[lino].mountpoint);
2029                }
2030            }
2031            log_msg(10, "The 'umount' command is '%s'", command);
2032            res = run_program_and_log_output(command, 3);
2033            paranoid_free(command);
2034        } else {
2035            asprintf(&tmp1, "%s%s", tmp, _("...not mounted anyway :-) OK"));
2036            paranoid_free(tmp);
2037            tmp = tmp1;
2038            res = 0;
2039        }
2040        g_current_progress++;
2041        if (res) {
2042            asprintf(&tmp1, "%s%s", tmp, _("...Failed"));
2043            paranoid_free(tmp);
2044            tmp = tmp1;
2045            retval++;
2046            log_to_screen(tmp);
2047        } else {
2048            log_msg(2, tmp);
2049        }
2050        paranoid_free(tmp);
2051    }
2052    close_progress_form();
2053    if (retval) {
2054        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
2055    } else {
2056        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2057    }
2058    if (retval) {
2059        log_to_screen(_("Unable to unmount some of your partitions."));
2060    } else {
2061        log_to_screen(_("All partitions were unmounted OK."));
2062    }
2063    free(mountlist);
2064    return (retval);
2065}
2066/**************************************************************************
2067 *END_UNMOUNT_ALL_DEVICES                                                 *
2068 **************************************************************************/
2069
2070
2071/**
2072 * Extract mondo-restore.cfg and the mountlist from the tape inserted
2073 * to the ./tmp/ directory.
2074 * @param dev The tape device to read from.
2075 * @return 0 for success, nonzero for failure.
2076 */
2077int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
2078{
2079    char *command = NULL;
2080    int res = 0;
2081    // BERLIOS: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
2082    long tape_block_size = 32768;
2083
2084    // tar -zxvf-
2085    asprintf(&command,
2086            "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s",
2087            dev,
2088            tape_block_size,
2089            1024L * 1024 * 32 / tape_block_size,
2090            MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB,
2091            BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, "tmp/i-want-my-lvm");
2092    log_msg(2, "command = '%s'", command);
2093    res = run_program_and_log_output(command, -1);
2094    paranoid_free(command);
2095
2096    if (res != 0 && does_file_exist(MONDO_CFG_FILE_STUB)) {
2097        res = 0;
2098    }
2099    return (res);
2100}
2101
2102
2103/**
2104 * Get the configuration file from the floppy, tape, or CD.
2105 * @param bkpinfo The backup information structure. Fields used:
2106 * - @c bkpinfo->backup_media_type
2107 * - @c bkpinfo->media_device
2108 * - @c bkpinfo->tmpdir
2109 * @return 0 for success, nonzero for failure.
2110 */
2111int get_cfg_file_from_archive(struct s_bkpinfo *bkpinfo)
2112{
2113    int retval = 0;
2114    char *command = NULL;
2115    char *cfg_file = NULL;
2116    char *mounted_cfgf_path = NULL;
2117    char *tmp = NULL;
2118    char *tmp1 = NULL;
2119    char *sav = NULL;
2120    char *mountpt = NULL;
2121    char *ramdisk_fname = NULL;
2122    char *mountlist_file = NULL;
2123    int res = 0;
2124
2125    bool try_plan_B;
2126
2127    assert(bkpinfo != NULL);
2128    log_msg(2, "gcffa --- starting");
2129    log_to_screen(_("I'm thinking..."));
2130    asprintf(&mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
2131    chdir(bkpinfo->tmpdir);
2132    // MONDO_CFG_FILE_STUB is missing the '/' at the start, FYI, by intent
2133    unlink(MONDO_CFG_FILE_STUB);
2134
2135    unlink(FILELIST_FULL_STUB);
2136    unlink(BIGGIELIST_TXT_STUB);
2137    unlink("tmp/i-want-my-lvm");
2138    asprintf(&command, "mkdir -p %s", mountpt);
2139    run_program_and_log_output(command, FALSE);
2140    paranoid_free(command);
2141
2142    asprintf(&cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
2143    asprintf(&mountlist_file, "%s/%s", bkpinfo->tmpdir,
2144            MOUNTLIST_FNAME_STUB);
2145    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
2146
2147    /* Floppy? */
2148    asprintf(&tmp, "mkdir -p %s", mountpt);
2149    run_program_and_log_output(tmp, FALSE);
2150    paranoid_free(tmp);
2151
2152    asprintf(&tmp, "mkdir -p %s/tmp", bkpinfo->tmpdir);
2153    run_program_and_log_output(tmp, FALSE);
2154    paranoid_free(tmp);
2155
2156    asprintf(&command, "mount /dev/fd0u1722 %s", mountpt);
2157    asprintf(&tmp,
2158            "(sleep 15; kill `ps | grep \"%s\" | cut -d' ' -f1` 2> /dev/null) &",
2159            command);
2160    log_msg(1, "tmp = '%s'", tmp);
2161    system(tmp);
2162    paranoid_free(tmp);
2163
2164    res = run_program_and_log_output(command, FALSE);
2165    paranoid_free(command);
2166
2167    if (res) {
2168        asprintf(&command, "mount /dev/fd0H1440 %s", mountpt);
2169        res = run_program_and_log_output(command, FALSE);
2170        paranoid_free(command);
2171    }
2172    if (res) {
2173        try_plan_B = TRUE;
2174    } else {
2175        try_plan_B = TRUE;
2176        log_msg(2,
2177                "Mounted floppy OK but I don't trust it because the archives might contain more up-to-date config file than the floppy does.");
2178// NB: If busybox does not support 'mount -o loop' then Plan A WILL NOT WORK.
2179        log_msg(2, "Processing floppy (plan A?)");
2180        asprintf(&ramdisk_fname, "%s/mindi.rdz", mountpt);
2181        if (!does_file_exist(ramdisk_fname)) {
2182            paranoid_free(ramdisk_fname);
2183            asprintf(&ramdisk_fname, "%s/initrd.img", mountpt);
2184        }
2185        if (!does_file_exist(ramdisk_fname)) {
2186            log_msg(2,
2187                    "Cannot find ramdisk file on mountpoint. Are you sure that's a boot disk in the drive?");
2188        }
2189        if (extract_config_file_from_ramdisk
2190            (bkpinfo, ramdisk_fname, cfg_file, mountlist_file)) {
2191            log_msg(2,
2192                    "Warning - failed to extract config file from ramdisk. I think this boot disk is mangled.");
2193        }
2194        asprintf(&command, "umount %s", mountpt);
2195        run_program_and_log_output(command, 5);
2196        paranoid_free(command);
2197
2198        unlink(ramdisk_fname);
2199        paranoid_free(ramdisk_fname);
2200    }
2201    if (!does_file_exist(cfg_file)) {
2202        log_msg(2, "gcffa --- we don't have cfg file yet.");
2203        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2204            try_plan_B = TRUE;
2205        } else {
2206            log_msg(2, "gcffa --- calling mount_cdrom now :)");
2207            if (!mount_cdrom(bkpinfo)) {
2208                log_msg(2,
2209                        "gcffa --- managed to mount CD; so, no need for Plan B");
2210                try_plan_B = FALSE;
2211            } else {
2212                try_plan_B = TRUE;
2213            }
2214            if (what_number_cd_is_this(bkpinfo) > 1) {
2215                insist_on_this_cd_number(bkpinfo,
2216                                         (g_current_media_number = 1));
2217            }
2218        }
2219        if (try_plan_B) {
2220            log_msg(2, "gcffa --- OK, switching to Plan B");
2221            chdir(bkpinfo->tmpdir);
2222            run_program_and_log_output("mkdir -p tmp", FALSE);
2223
2224            if (bkpinfo->media_device == NULL) {
2225                asprintf(&bkpinfo->media_device, "/dev/st0");
2226                log_msg(2, "media_device is blank; assuming %s",
2227                        bkpinfo->media_device);
2228            }
2229            asprintf(&sav, bkpinfo->media_device);
2230            if (extract_cfg_file_and_mountlist_from_tape_dev
2231                (bkpinfo->media_device)) {
2232                paranoid_alloc(bkpinfo->media_device, "/dev/st0");
2233                if (extract_cfg_file_and_mountlist_from_tape_dev
2234                    (bkpinfo->media_device)) {
2235                    paranoid_alloc(bkpinfo->media_device, "/dev/osst0");
2236                    if (extract_cfg_file_and_mountlist_from_tape_dev
2237                        (bkpinfo->media_device)) {
2238                        paranoid_alloc(bkpinfo->media_device, "/dev/ht0");
2239                        if (extract_cfg_file_and_mountlist_from_tape_dev
2240                            (bkpinfo->media_device)) {
2241                            log_msg(3,
2242                                    "I tried lots of devices but none worked.");
2243                            paranoid_alloc(bkpinfo->media_device, sav);
2244                        }
2245                    }
2246                }
2247            }
2248            paranoid_free(sav);
2249
2250            if (!does_file_exist("tmp/mondo-restore.cfg")) {
2251                log_to_screen(_
2252                              ("Cannot find config info on tape/CD/floppy"));
2253                return (1);
2254            }
2255        } else {
2256            log_msg(2,
2257                    "gcffa --- looking at mounted CD for mindi-boot.2880.img");
2258            /* BERLIOS : Useless ?
2259            asprintf(&command,
2260                    "mount " MNT_CDROM
2261                    "/images/mindi-boot.2880.img -o loop %s", mountpt);
2262                    */
2263            asprintf(&mounted_cfgf_path, "%s/%s", mountpt, cfg_file);
2264            if (!does_file_exist(mounted_cfgf_path)) {
2265                log_msg(2,
2266                        "gcffa --- Plan C, a.k.a. untarring some file from all.tar.gz");
2267                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
2268                run_program_and_log_output(command, TRUE);
2269                paranoid_free(command);
2270
2271                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
2272                    fatal_error
2273                        ("Please reinsert the disk/CD and try again.");
2274                }
2275            }
2276            paranoid_free(mounted_cfgf_path);
2277        }
2278    }
2279    paranoid_free(mountpt);
2280
2281    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
2282        log_msg(1, "gcffa --- great! We've got the config file");
2283        tmp1 = call_program_and_get_last_line_of_output("pwd");
2284        asprintf(&tmp, "%s/%s", tmp1,MONDO_CFG_FILE_STUB);
2285        asprintf(&command, "cp -f %s %s", tmp, cfg_file);
2286        iamhere(command);
2287
2288        if (strcmp(tmp, cfg_file)
2289            && run_program_and_log_output(command, 1)) {
2290            log_msg(1,
2291                    "... but an error occurred when I tried to move it to %s",
2292                    cfg_file);
2293        } else {
2294            log_msg(1, "... and I moved it successfully to %s", cfg_file);
2295        }
2296        paranoid_free(command);
2297
2298        asprintf(&command, "cp -f %s/%s %s",tmp1,
2299                MOUNTLIST_FNAME_STUB, mountlist_file);
2300        paranoid_free(tmp1);
2301
2302        iamhere(command);
2303        if (strcmp(tmp, cfg_file)
2304            && run_program_and_log_output(command, 1)) {
2305            log_msg(1, "Failed to get mountlist");
2306        } else {
2307            log_msg(1, "Got mountlist too");
2308            paranoid_free(command);
2309            asprintf(&command, "cp -f %s %s", mountlist_file,
2310                    g_mountlist_fname);
2311            if (run_program_and_log_output(command, 1)) {
2312                log_msg(1, "Failed to copy mountlist to /tmp");
2313            } else {
2314                log_msg(1, "Copied mountlist to /tmp as well OK");
2315                paranoid_free(command);
2316                asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2317                run_program_and_log_output(command, 1);
2318            }
2319        }
2320        paranoid_free(command);
2321        paranoid_free(tmp);
2322    }
2323    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2324    if (!does_file_exist(cfg_file)) {
2325        iamhere(cfg_file);
2326        log_msg(1, "%s not found", cfg_file);
2327        log_to_screen
2328            (_
2329             ("Oh dear. Unable to recover configuration file from boot disk"));
2330        return (1);
2331    }
2332
2333    log_to_screen(_("Recovered mondo-restore.cfg"));
2334    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
2335        log_to_screen(_("...but not mountlist.txt - a pity, really..."));
2336    }
2337/* start SAH */
2338    else {
2339        asprintf(&command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB,
2340                bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
2341        run_program_and_log_output(command, FALSE);
2342        paranoid_free(command);
2343    }
2344/* end SAH */
2345
2346    asprintf(&command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
2347    paranoid_free(cfg_file);
2348
2349    run_program_and_log_output(command, FALSE);
2350    paranoid_free(command);
2351
2352    asprintf(&command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
2353    paranoid_free(mountlist_file);
2354
2355    run_program_and_log_output(command, FALSE);
2356    paranoid_free(command);
2357
2358    asprintf(&command, "cp -f etc/raidtab /etc/");
2359    run_program_and_log_output(command, FALSE);
2360    paranoid_free(command);
2361
2362    asprintf(&command, "cp -f tmp/i-want-my-lvm /tmp/");
2363    run_program_and_log_output(command, FALSE);
2364    paranoid_free(command);
2365
2366    g_backup_media_type = bkpinfo->backup_media_type;
2367    bkpinfo->backup_media_string = bkptype_to_string(bkpinfo->backup_media_type);
2368    g_backup_media_string = bkpinfo->backup_media_string;
2369    return (retval);
2370}
2371/**************************************************************************
2372 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
2373 **************************************************************************/
2374/* @} - end restoreUtilityGroup */
2375
2376
2377void wait_until_software_raids_are_prepped(char *mdstat_file,
2378                                           int wait_for_percentage)
2379{
2380    struct raidlist_itself *raidlist = NULL;
2381    int unfinished_mdstat_devices = 9999, i = 0;
2382    char *screen_message = NULL;
2383
2384    raidlist = malloc(sizeof(struct raidlist_itself));
2385
2386    assert(wait_for_percentage <= 100);
2387    iamhere("Help, my boat is sync'ing. (Get it? Urp! Urp!)");
2388    while (unfinished_mdstat_devices > 0) {
2389        if (parse_mdstat(raidlist, "/dev/")) {
2390            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2391            log_msg(1, "Sorry, cannot read %s", MDSTAT_FILE);
2392            return;
2393        }
2394        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries;
2395             i++) {
2396            if (raidlist->el[i].progress < wait_for_percentage) {
2397                unfinished_mdstat_devices++;
2398                log_msg(1, "Sync'ing %s (i=%d)",
2399                        raidlist->el[i].raid_device, i);
2400                asprintf(&screen_message, "Sync'ing %s",
2401                        raidlist->el[i].raid_device);
2402                open_evalcall_form(screen_message);
2403                paranoid_free(screen_message);
2404
2405                if (raidlist->el[i].progress == -1) { // delayed while another partition inits
2406                    continue;
2407                }
2408                while (raidlist->el[i].progress < wait_for_percentage) {
2409                    log_msg(1, "Percentage sync'ed: %d",
2410                            raidlist->el[i].progress);
2411                    update_evalcall_form(raidlist->el[i].progress);
2412                    sleep(2);
2413                    // FIXME: Prefix '/dev/' should really be dynamic!
2414                    if (parse_mdstat(raidlist, "/dev/")) {
2415                        break;
2416                    }
2417                }
2418                close_evalcall_form();
2419            }
2420        }
2421    }
2422    paranoid_free(raidlist);
2423}
Note: See TracBrowser for help on using the repository browser.