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

Last change on this file since 1663 was 1663, checked in by Bruno Cornec, 12 years ago
  • Fix bug #197 (based on an initial patch of Scott Cummings)
  • Fix a bug where df was using locale to print messages and wasn't filtered correctly
  • mkdtemp checked in configure
  • reset_bkpinfo called as early as possible by both main program.
  • It creates a tmpdir cleanly with mkdtemp in setup_tmpdir subfunction, which takes in account TMPIR and TMP env var. Remains to see what tmpfs does and tests
  • configure.in should also be filtered.
  • Remove g_bkpinfo_DONTUSETHIS
  • remove bkpinfo also from header files
  • Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
  • Apply patch from Andree Leidenfrost, modified a bit to use bkpinfo->tmpdir instead of /tmp or MINDI_CACHE when appropriate. Fix security issues in mondo. Thanks al ot Andree for catching all those issues.
  • /tmp => /var/log for mondorestore.log in mindi
  • Update linux terminfo to fix a color issue (Andree Leidenfrost)
  • Removes useless log file (Andree Leidenfrost)
  • replace vi with find_my_editor during restore (Andree Leidenfrost)
  • sync in bg in mindi (VMWare issue to look at)
  • mindi/mindi-busybox have a different version than mondo for pb
  • PB-SUF also added to spec file
  • Fix a bug for pb build (omission of PB-SUF declaration)

(merge -r1631:1662 $SVN_M/branches/2.2.5)

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