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

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

Huge memory management patch.
Still not finished but a lot as been done.
What remains is around some functions returning strings, and some structure members.
(Could not finish due to laptop failure !)

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