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

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

Continue on configuration file items (compression)

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