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

Last change on this file since 689 was 689, checked in by bcornec, 13 years ago

Still other memory management improvements ( I hope :-)

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