source: branches/2.2.8/mondo/src/mondorestore/mondo-rstr-tools.c @ 2049

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