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

Last change on this file since 914 was 914, checked in by bruno, 13 years ago

merge -r902:913 $SVN_M/branches/stable

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