source: branches/2.2.8/mondo/src/mondorestore/mondorestore.c @ 2776

Last change on this file since 2776 was 2776, checked in by Bruno Cornec, 9 years ago

r2145@localhost (orig r2144): bruno | 2009-02-14 02:10:28 +0100
Ok, really fix the Ubuntu problem as we need first to umount /var and then create the dirs


  • Property svn:keywords set to Id
File size: 97.5 KB
Line 
1/***************************************************************************
2$Id: mondorestore.c 2776 2011-04-29 13:35:47Z bruno $
3restores mondoarchive data
4***************************************************************************/
5
6/**
7 * @file
8 * The main file for mondorestore.
9 */
10
11/**************************************************************************
12 * #include statements                                                    *
13 **************************************************************************/
14#include <pthread.h>
15#include "my-stuff.h"
16#include "../common/mondostructures.h"
17#include "../common/libmondo.h"
18#include "mr-externs.h"
19#include "mondo-restore.h"
20#include "mondorestore.h"
21#include "mondo-rstr-compare-EXT.h"
22#include "mondo-rstr-tools-EXT.h"
23
24extern void twenty_seconds_til_yikes(void);
25
26/* Reference to global bkpinfo */
27struct s_bkpinfo *bkpinfo;
28
29
30/* For use in other programs (ex. XMondo) */
31#ifdef MONDORESTORE_MODULE
32#define main __mondorestore_main
33#define g_ISO_restore_mode __mondorestore_g_ISO_restore_mode
34#endif
35
36//static char cvsid[] = "$Id: mondorestore.c 2776 2011-04-29 13:35:47Z bruno $";
37
38/**************************************************************************
39 * Globals                                                                *
40 **************************************************************************/
41/*
42extern char *g_tmpfs_mountpt;   // declared in libmondo-tools.c
43*/
44extern bool g_text_mode;
45extern FILE *g_fprep;
46extern double g_kernel_version;
47extern int g_partition_table_locked_up;
48extern int g_noof_rows;
49
50extern int partition_everything(struct mountlist_itself *mountlist);
51extern int handle_incoming_parameters(int argc, char *argv[]);
52
53/**
54 * @name Restore-Time Globals
55 * @ingroup globalGroup
56 * @{
57 */
58
59/**
60 * If TRUE, then we're restoring from ISOs or an NFS server.
61 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
62 */
63bool g_ISO_restore_mode = FALSE;    /* are we in Iso Mode? */
64
65/**
66 * If TRUE, then we have had a successful "nuke" restore.
67 */
68bool g_I_have_just_nuked = FALSE;
69
70/**
71 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
72 */
73char *g_isodir_device;
74
75/**
76 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
77 */
78char *g_isodir_format;
79
80/**
81 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
82 */
83char *g_biggielist_txt;
84
85/**
86 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
87 * the current archive set.
88 */
89char *g_filelist_full;
90
91/**
92 * The location of a file containing a list of the devices that were archived
93 * as images, not as individual files.
94 */
95char *g_filelist_imagedevs;
96
97/**
98 * The location of a file containing a list of imagedevs to actually restore.
99 * @see g_filelist_imagedevs
100 */
101char *g_imagedevs_restthese;
102
103/**
104 * The location of 'mondo-restore.cfg', containing the metadata
105 * information for this backup.
106 */
107char *g_mondo_cfg_file;
108
109/**
110 * The location of 'mountlist.txt', containing the information on the
111 * user's partitions and hard drives.
112 */
113char *g_mountlist_fname;
114
115/**
116 * Mondo's home directory during backup. Unused in mondorestore; included
117 * to avoid link errors.
118 */
119char *g_mondo_home;
120
121extern char *g_getfacl;
122extern char *g_getfattr;
123
124/* @} - end of "Restore-Time Globals" in globalGroup */
125
126
127
128extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
129                                 char direction);
130
131
132
133/**************************************************************************
134 * COMPAQ PROLIANT Stuff:  needs some special help                        *
135**************************************************************************/
136
137/**
138 * The message to display if we detect that the user is using a Compaq Proliant.
139 */
140#define COMPAQ_PROLIANTS_SUCK "Partition and format your disk using Compaq's disaster recovery CD. After you've done that, please reboot with your Mondo media in Interactive Mode."
141
142
143
144
145/**
146 * Allow the user to modify the mountlist before we partition & format their drives.
147 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
148 * @param mountlist The mountlist to let the user modify.
149 * @param raidlist The raidlist that goes with @p mountlist.
150 * @return 0 for success, nonzero for failure.
151 * @ingroup restoreGuiGroup
152 */
153int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
154                                struct raidlist_itself *raidlist)
155{
156    int retval = 0, res = 0;
157
158    log_msg(2, "let_user_edit_the_mountlist() --- starting");
159
160    assert(bkpinfo != NULL);
161    assert(mountlist != NULL);
162    assert(raidlist != NULL);
163    if (!bkpinfo->disaster_recovery) {
164        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
165        log_msg(2, "I guess you're testing edit_mountlist()");
166    }
167    if (!does_file_exist(g_mountlist_fname)) {
168        log_to_screen(g_mountlist_fname);
169        log_to_screen("does not exist");
170        return (1);
171    }
172
173    retval = load_mountlist(mountlist, g_mountlist_fname);
174    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
175    if (retval) {
176        log_to_screen
177            ("Warning - load_raidtab_into_raidlist returned an error");
178    }
179    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
180    if (res) {
181        return (1);
182    }
183
184    save_mountlist_to_disk(mountlist, g_mountlist_fname);
185    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
186
187    log_to_screen("I have finished editing the mountlist for you.");
188
189    return (retval);
190}
191
192
193
194
195
196/**
197 * Determine whether @p mountlist contains a Compaq diagnostic partition.
198 * @param mountlist The mountlist to examine.
199 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
200 * @ingroup restoreUtilityGroup
201 */
202bool
203partition_table_contains_Compaq_diagnostic_partition(struct
204                                                     mountlist_itself *
205                                                     mountlist)
206{
207    int i;
208
209    assert(mountlist != NULL);
210
211    for (i = 0; i < mountlist->entries; i++) {
212        if (strstr(mountlist->el[i].format, "ompaq")) {
213            log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
214                    i, mountlist->el[i].device, mountlist->el[i].format);
215
216            return (TRUE);
217        }
218    }
219    return (FALSE);
220}
221
222/**************************************************************************
223 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION                *
224 **************************************************************************/
225
226
227/**
228 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
229 * @note This function does not actually check for the presence of a Compaq partition.
230 * @ingroup restoreUtilityGroup
231 */
232void offer_to_abort_because_Compaq_Proliants_suck(void)
233{
234    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
235    if (ask_me_yes_or_no
236        ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
237    {
238        fatal_error
239            ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
240    }
241}
242
243/**************************************************************************
244 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK                        *
245 **************************************************************************/
246
247
248
249/**
250 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
251 * @param bkpinfo The backup information structure. Most fields are used.
252 * @param mountlist The mountlist containing information about the user's partitions.
253 * @param raidlist The raidlist to go with @p mountlist.
254 * @return The return code from the mode function called.
255 * @ingroup restoreGroup
256 */
257int
258catchall_mode(struct mountlist_itself *mountlist,
259              struct raidlist_itself *raidlist)
260{
261    char c, *tmp;
262    int retval = 0;
263
264    iamhere("inside catchall");
265    assert(bkpinfo != NULL);
266    assert(mountlist != NULL);
267    assert(raidlist != NULL);
268    malloc_string(tmp);
269    iamhere("pre wrm");
270    c = which_restore_mode();
271    iamhere("post wrm");
272    if (c == 'I' || c == 'C') {
273        interactively_obtain_media_parameters_from_user(FALSE);
274    } else if (c == 'N') {
275        // Auto mode nothing special to do
276    } else {
277        popup_and_OK("No restoring or comparing will take place today.");
278        if (is_this_device_mounted("/mnt/cdrom")) {
279            run_program_and_log_output("umount /mnt/cdrom", FALSE);
280        }
281        if (g_ISO_restore_mode) {
282            sprintf(tmp, "umount %s", bkpinfo->isodir);
283            run_program_and_log_output(tmp, FALSE);
284        }
285        paranoid_MR_finish(0);
286    }
287
288    iamhere("post int");
289
290    if (bkpinfo->backup_media_type == iso) {
291        if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
292            log_msg(2,
293                    "catchall_mode --- iso_fiddly_bits returned w/ error");
294            return (1);
295        } else {
296            log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
297        }
298    }
299
300    if (c == 'I') {
301        log_msg(2, "IM selected");
302        retval += interactive_mode(mountlist, raidlist);
303    } else if (c == 'N') {
304        log_msg(2, "NM selected");
305        retval += nuke_mode(mountlist, raidlist);
306    } else if (c == 'C') {
307        log_msg(2, "CM selected");
308        retval += compare_mode(mountlist, raidlist);
309    }
310    paranoid_free(tmp);
311    return (retval);
312}
313
314/**************************************************************************
315 *END_CATCHALL_MODE                                                      *
316 **************************************************************************/
317
318/**************************************************************************
319 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
320 **************************************************************************/
321
322
323/**
324 * Locate an executable in the directory structure rooted at @p restg.
325 * @param out_path Where to put the executable.
326 * @param fname The basename of the executable.
327 * @param restg The directory structure to look in.
328 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
329 * @ingroup restoreUtilityGroup
330 */
331void
332find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
333                                                    char *fname,
334                                                    char *restg)
335{
336    assert(out_path != NULL);
337    assert_string_is_neither_NULL_nor_zerolength(fname);
338
339    sprintf(out_path, "%s/sbin/%s", restg, fname);
340    if (does_file_exist(out_path)) {
341        sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
342        if (does_file_exist(out_path)) {
343            sprintf(out_path, "%s/bin/%s", restg, fname);
344            if (does_file_exist(out_path)) {
345                sprintf(out_path, "%s/usr/bin/%s", restg, fname);
346                if (does_file_exist(out_path)) {
347                    strcpy(out_path, fname);
348                }
349            }
350        }
351    }
352}
353
354/**************************************************************************
355 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
356 **************************************************************************/
357
358static void clean_blkid() {
359
360    char *tmp1 = NULL;
361
362    /* Clean up blkid cache file if they exist */
363    asprintf(&tmp1,"%s/etc/blkid.tab",bkpinfo->restore_path);
364    (void)unlink(tmp1);
365    paranoid_free(tmp1);
366    asprintf(&tmp1,"%s/etc/blkid.tab.old",bkpinfo->restore_path);
367    (void)unlink(tmp1);
368    paranoid_free(tmp1);
369}
370
371
372static void clean_multipathconf() {
373
374    char *tmp1 = NULL;
375    char *editor = NULL;
376
377    /* Clean up multiconf cache file if they exist */
378    asprintf(&tmp1,"%s/var/lib/multipath/bindings",bkpinfo->restore_path);
379    (void)unlink(tmp1);
380    paranoid_free(tmp1);
381
382    /* Edit multipath.conf if needed to adapt wwid */
383    asprintf(&tmp1,"%s/etc/multipath.conf", MNT_RESTORING);
384    if (does_file_exist(tmp1)) {
385        log_msg(2, "We may need to clean /etc/multipath.conf");
386    } else {
387        paranoid_free(tmp1);
388        return;
389    }
390    paranoid_free(tmp1);
391
392    if (bkpinfo->restore_mode != nuke) {
393        asprintf(&editor, "%s", find_my_editor());
394        asprintf(&tmp1,"chroot %s %s /etc/multipath.conf", MNT_RESTORING, editor);
395        popup_and_OK("You will now edit multipath.conf");
396        if (!g_text_mode) {
397            newtSuspend();
398        }
399        paranoid_system(tmp1);
400        if (!g_text_mode) {
401            newtResume();
402        }
403        paranoid_free(tmp1);
404        paranoid_free(editor);
405    } else {
406        log_to_screen("Non-interactive mode: no way to give you the keyboard so that you edit your multipath.conf. Hope it's OK");
407        log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you edit your multipath.conf. Hope it's OK");
408    }
409}
410
411
412
413
414/**
415 * @addtogroup restoreGroup
416 * @{
417 */
418/**
419 * Restore the user's data, in a disaster recovery situation, prompting the
420 * user about whether or not to do every step.
421 * The user can edit the mountlist, choose files to restore, etc.
422 * @param bkpinfo The backup information structure. Most fields are used.
423 * @param mountlist The mountlist containing information about the user's partitions.
424 * @param raidlist The raidlist to go with @p mountlist.
425 * @return 0 for success, or the number of errors encountered.
426 */
427int
428interactive_mode(struct mountlist_itself *mountlist,
429                 struct raidlist_itself *raidlist)
430{
431    int retval = 0;
432    int res;
433    int ptn_errs = 0;
434    int fmt_errs = 0;
435
436    bool done;
437    bool restore_all;
438
439  /** needs malloc **********/
440    char *tmp;
441    char *fstab_fname;
442    char *old_restpath;
443
444    struct s_node *filelist;
445
446    /* try to partition and format */
447
448    log_msg(2, "interactive_mode --- starting (great, assertions OK)");
449
450    malloc_string(tmp);
451    malloc_string(fstab_fname);
452    malloc_string(old_restpath);
453    assert(bkpinfo != NULL);
454    assert(mountlist != NULL);
455    assert(raidlist != NULL);
456
457    log_msg(2, "interactive_mode --- assertions OK");
458
459    if (g_text_mode) {
460        if (!ask_me_yes_or_no
461            ("Interactive Mode + textonly = experimental! Proceed anyway?"))
462        {
463            fatal_error("Wise move.");
464        }
465    }
466
467    iamhere("About to load config file");
468    get_cfg_file_from_archive_or_bust();
469    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
470    iamhere("Done loading config file; resizing ML");
471    if (bkpinfo->backup_media_type == nfs) {
472        strcpy(tmp, bkpinfo->prefix);
473        if (popup_and_get_string
474            ("Prefix", "Prefix of your ISO images ?", tmp, MAX_STR_LEN / 4)) {
475            strcpy(bkpinfo->prefix, tmp);
476            log_msg(1, "Prefix set to %s",bkpinfo->prefix);
477        }
478    }
479
480#ifdef __FreeBSD__
481    if (strstr
482        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
483         "noresize"))
484#else
485    if (strstr
486        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
487         "noresize"))
488#endif
489    {
490        log_msg(1, "Not resizing mountlist.");
491    } else {
492        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
493    }
494    for (done = FALSE; !done;) {
495        iamhere("About to edit mountlist");
496        if (g_text_mode) {
497            save_mountlist_to_disk(mountlist, g_mountlist_fname);
498            sprintf(tmp, "%s %s", find_my_editor(), g_mountlist_fname);
499            res = system(tmp);
500            load_mountlist(mountlist, g_mountlist_fname);
501        } else {
502            res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
503        }
504        iamhere("Finished editing mountlist");
505        if (res) {
506            paranoid_MR_finish(1);
507        }
508        log_msg(2, "Proceeding...");
509        save_mountlist_to_disk(mountlist, g_mountlist_fname);
510        save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
511        mvaddstr_and_log_it(1, 30, "Restoring Interactively");
512        if (bkpinfo->differential) {
513            log_to_screen("Because this is a differential backup, disk");
514            log_to_screen
515                (" partitioning and formatting will not take place.");
516            done = TRUE;
517        } else {
518            if (ask_me_yes_or_no
519                ("Do you want to erase and partition your hard drives?")) {
520                if (partition_table_contains_Compaq_diagnostic_partition
521                    (mountlist)) {
522                    offer_to_abort_because_Compaq_Proliants_suck();
523                    done = TRUE;
524                } else {
525                    twenty_seconds_til_yikes();
526                    g_fprep = fopen("/tmp/prep.sh", "w");
527                    ptn_errs = partition_everything(mountlist);
528                    if (ptn_errs) {
529                        log_to_screen
530                            ("Warning. Errors occurred during disk partitioning.");
531                    }
532
533                    fmt_errs = format_everything(mountlist, FALSE, raidlist);
534                    if (!fmt_errs) {
535                        log_to_screen
536                            ("Errors during disk partitioning were handled OK.");
537                        log_to_screen
538                            ("Partitions were formatted OK despite those errors.");
539                        ptn_errs = 0;
540                    }
541                    if (!ptn_errs && !fmt_errs) {
542                        done = TRUE;
543                    }
544                }
545                paranoid_fclose(g_fprep);
546            } else {
547                mvaddstr_and_log_it(g_currentY++, 0,
548                                    "User opted not to partition the devices");
549                if (ask_me_yes_or_no
550                    ("Do you want to format your hard drives?")) {
551                    fmt_errs = format_everything(mountlist, TRUE, raidlist);
552                    if (!fmt_errs) {
553                        done = TRUE;
554                    }
555                } else {
556                    ptn_errs = fmt_errs = 0;
557                    done = TRUE;
558                }
559            }
560            if (fmt_errs) {
561                mvaddstr_and_log_it(g_currentY++,
562                                    0,
563                                    "Errors occurred. Please repartition and format drives manually.");
564                done = FALSE;
565            }
566            if (ptn_errs & !fmt_errs) {
567                mvaddstr_and_log_it(g_currentY++,
568                                    0,
569                                    "Errors occurred during partitioning. Formatting, however, went OK.");
570                done = TRUE;
571            }
572            if (!done) {
573                if (!ask_me_yes_or_no("Re-edit the mountlist?")) {
574                    retval++;
575                    goto end_of_func;
576                }
577            }
578        }
579    }
580
581    /* mount */
582    if (mount_all_devices(mountlist, TRUE)) {
583        unmount_all_devices(mountlist);
584        retval++;
585        goto end_of_func;
586    }
587    /* restore */
588    if ((restore_all =
589         ask_me_yes_or_no("Do you want me to restore all of your data?")))
590    {
591        log_msg(1, "Restoring all data");
592        retval += restore_everything(NULL);
593    } else
594        if ((restore_all =
595             ask_me_yes_or_no
596             ("Do you want me to restore _some_ of your data?"))) {
597        strcpy(old_restpath, bkpinfo->restore_path);
598        for (done = FALSE; !done;) {
599            unlink("/tmp/filelist.full");
600            filelist = process_filelist_and_biggielist();
601            /* Now you have /tmp/tmpfs/filelist.restore-these and /tmp/tmpfs/biggielist.restore-these;
602               the former is a list of regular files; the latter, biggiefiles and imagedevs.
603             */
604            if (filelist) {
605              gotos_suck:
606                strcpy(tmp, old_restpath);
607// (NB: %s is where your filesystem is mounted now, by default)", MNT_RESTORING);
608                if (popup_and_get_string
609                    ("Restore path", "Restore files to where?", tmp,
610                     MAX_STR_LEN / 4)) {
611                    if (!strcmp(tmp, "/")) {
612                        if (!ask_me_yes_or_no("Are you sure?")) {
613                            goto gotos_suck;
614                        }
615                        tmp[0] = '\0';  // so we restore to [blank]/file/name :)
616                    }
617                    strcpy(bkpinfo->restore_path, tmp);
618                    log_msg(1, "Restoring subset");
619                    retval += restore_everything(filelist);
620                    free_filelist(filelist);
621                } else {
622                    strcpy(bkpinfo->restore_path, old_restpath);
623                    free_filelist(filelist);
624                }
625                if (!ask_me_yes_or_no
626                    ("Restore another subset of your backup?")) {
627                    done = TRUE;
628                }
629            } else {
630                done = TRUE;
631            }
632        }
633        strcpy(old_restpath, bkpinfo->restore_path);
634    } else {
635        mvaddstr_and_log_it(g_currentY++,
636                            0,
637                            "User opted not to restore any data.                                  ");
638    }
639    if (retval) {
640        mvaddstr_and_log_it(g_currentY++,
641                            0,
642                            "Errors occurred during the restore phase.            ");
643    }
644
645    clean_multipathconf();
646    if (ask_me_yes_or_no("Initialize the boot loader?")) {
647        run_boot_loader(TRUE);
648    } else {
649        mvaddstr_and_log_it(g_currentY++,
650                            0,
651                            "User opted not to initialize the boot loader.");
652    }
653
654    clean_blkid();
655    protect_against_braindead_sysadmins();
656    retval += unmount_all_devices(mountlist);
657
658    /*  if (restore_some || restore_all || */
659    if (ask_me_yes_or_no
660        ("Label/Identify your ext2/ext3/ext4 partitions if necessary?")) {
661        mvaddstr_and_log_it(g_currentY, 0,
662                            "Using tune2fs to identify your ext2,3,4 partitions");
663        if (does_file_exist("/tmp/fstab.new")) {
664            strcpy(fstab_fname, "/tmp/fstab.new");
665        } else {
666            strcpy(fstab_fname, "/tmp/fstab");
667        }
668        sprintf(tmp,
669                "label-partitions-as-necessary %s < %s >> %s 2>> %s",
670                g_mountlist_fname, fstab_fname, MONDO_LOGFILE,
671                MONDO_LOGFILE);
672        res = system(tmp);
673        if (res) {
674            log_to_screen
675                ("label-partitions-as-necessary returned an error");
676            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
677        } else {
678            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
679        }
680        retval += res;
681    }
682
683    iamhere("About to leave interactive_mode()");
684    if (retval) {
685        mvaddstr_and_log_it(g_currentY++,
686                            0,
687                            "Warning - errors occurred during the restore phase.");
688    }
689  end_of_func:
690    paranoid_free(tmp);
691    paranoid_free(fstab_fname);
692    paranoid_free(old_restpath);
693    iamhere("Leaving interactive_mode()");
694    return (retval);
695}
696
697/**************************************************************************
698 *END_INTERACTIVE_MODE                                                    *
699 **************************************************************************/
700
701
702
703/**
704 * Run an arbitrary restore mode (prompt the user), but from ISO images
705 * instead of real media.
706 * @param mountlist The mountlist containing information about the user's partitions.
707 * @param raidlist The raidlist that goes with @p mountlist.
708 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
709 * @return 0 for success, or the number of errors encountered.
710 */
711int
712iso_mode(struct mountlist_itself *mountlist,
713         struct raidlist_itself *raidlist, bool nuke_me_please)
714{
715    char c;
716    int retval = 0;
717
718    assert(mountlist != NULL);
719    assert(raidlist != NULL);
720    if (iso_fiddly_bits(nuke_me_please)) {
721        log_msg(1, "iso_mode --- returning w/ error");
722        return (1);
723    } else {
724        c = which_restore_mode();
725        if (c == 'I' || c == 'N' || c == 'C') {
726            interactively_obtain_media_parameters_from_user(FALSE);
727        }
728        if (c == 'I') {
729            retval += interactive_mode(mountlist, raidlist);
730        } else if (c == 'N') {
731            retval += nuke_mode(mountlist, raidlist);
732        } else if (c == 'C') {
733            retval += compare_mode(mountlist, raidlist);
734        } else {
735            log_to_screen("OK, I shan't restore/compare any files.");
736        }
737    }
738    if (is_this_device_mounted(MNT_CDROM)) {
739        paranoid_system("umount " MNT_CDROM);
740    }
741//  if (! already_mounted)
742//    {
743    if (system("umount /tmp/isodir 2> /dev/null")) {
744        log_to_screen
745            ("WARNING - unable to unmount device where the ISO files are stored.");
746    }
747//    }
748    return (retval);
749}
750
751/**************************************************************************
752 *END_ISO_MODE                                                            *
753 **************************************************************************/
754
755
756/*            MONDO - saving your a$$ since Feb 18th, 2000            */
757
758
759
760
761/**
762 * Restore the user's data automatically (no prompts), after a twenty-second
763 * warning period.
764 * @param bkpinfo The backup information structure. Most fields are used.
765 * @param mountlist The mountlist containing information about the user's partitions.
766 * @param raidlist The raidlist that goes with @p mountlist.
767 * @return 0 for success, or the number of errors encountered.
768 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
769 */
770int
771nuke_mode(struct mountlist_itself *mountlist,
772          struct raidlist_itself *raidlist)
773{
774    int retval = 0;
775    int res = 0;
776    bool boot_loader_installed = FALSE;
777  /** malloc **/
778    char tmp[MAX_STR_LEN], tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
779        tmpC[MAX_STR_LEN];
780
781    assert(bkpinfo != NULL);
782    assert(mountlist != NULL);
783    assert(raidlist != NULL);
784
785    log_msg(2, "nuke_mode --- starting");
786
787    get_cfg_file_from_archive_or_bust();
788    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo updated the mountlist
789#ifdef __FreeBSD__
790    if (strstr
791        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
792         "noresize"))
793#else
794    if (strstr
795        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
796         "noresize"))
797#endif
798    {
799        log_msg(2, "Not resizing mountlist.");
800    } else {
801        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
802    }
803    if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
804        sprintf(tmp,
805                "Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?",
806                tmpA, tmpB, tmpC);
807        if (ask_me_yes_or_no(tmp)) {
808            retval = interactive_mode(mountlist, raidlist);
809            goto after_the_nuke;
810        } else {
811            fatal_error("Nuke Mode aborted. ");
812        }
813    }
814    save_mountlist_to_disk(mountlist, g_mountlist_fname);
815    mvaddstr_and_log_it(1, 30, "Restoring Automatically");
816    if (bkpinfo->differential) {
817        log_to_screen("Because this is a differential backup, disk");
818        log_to_screen("partitioning and formatting will not take place.");
819        res = 0;
820    } else {
821        if (partition_table_contains_Compaq_diagnostic_partition
822            (mountlist)) {
823            offer_to_abort_because_Compaq_Proliants_suck();
824        } else {
825            twenty_seconds_til_yikes();
826            g_fprep = fopen("/tmp/prep.sh", "w");
827#ifdef __FreeBSD__
828            if (strstr
829                (call_program_and_get_last_line_of_output
830                 ("cat /tmp/cmdline"), "nopart"))
831#else
832            if (strstr
833                (call_program_and_get_last_line_of_output
834                 ("cat /proc/cmdline"), "nopart"))
835#endif
836            {
837                log_msg(2,
838                        "Not partitioning drives due to 'nopart' option.");
839                res = 0;
840            } else {
841                res = partition_everything(mountlist);
842                if (res) {
843                    log_to_screen
844                        ("Warning. Errors occurred during partitioning.");
845                    res = 0;
846                }
847            }
848            retval += res;
849            if (!res) {
850                log_to_screen("Preparing to format your disk(s)");
851                sleep(1);
852                system("sync");
853                log_to_screen("Please wait. This may take a few minutes.");
854                res += format_everything(mountlist, FALSE, raidlist);
855            }
856            paranoid_fclose(g_fprep);
857        }
858    }
859    retval += res;
860    if (res) {
861        mvaddstr_and_log_it(g_currentY++,
862                            0,
863                            "Failed to partition and/or format your hard drives.");
864
865        if (ask_me_yes_or_no("Try in interactive mode instead?")) {
866            retval = interactive_mode(mountlist, raidlist);
867            goto after_the_nuke;
868        } else
869            if (!ask_me_yes_or_no
870                ("Would you like to try to proceed anyway?")) {
871            return (retval);
872        }
873    }
874    retval = mount_all_devices(mountlist, TRUE);
875    if (retval) {
876        unmount_all_devices(mountlist);
877        log_to_screen
878            ("Unable to mount all partitions. Sorry, I cannot proceed.");
879        return (retval);
880    }
881    iamhere("Restoring everything");
882    retval += restore_everything(NULL);
883    clean_multipathconf();
884    if (!run_boot_loader(FALSE)) {
885        log_msg(1,
886                "Great! Boot loader was installed. No need for msg at end.");
887        boot_loader_installed = TRUE;
888    }
889    clean_blkid();
890    protect_against_braindead_sysadmins();
891    retval += unmount_all_devices(mountlist);
892    mvaddstr_and_log_it(g_currentY,
893                        0,
894                        "Using tune2fs to identify your ext2,3 partitions");
895
896    sprintf(tmp, "label-partitions-as-necessary %s < /tmp/fstab",
897            g_mountlist_fname);
898    res = run_program_and_log_output(tmp, TRUE);
899    if (res) {
900        log_to_screen("label-partitions-as-necessary returned an error");
901        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
902    } else {
903        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
904    }
905    retval += res;
906
907  after_the_nuke:
908    if (retval) {
909        log_to_screen("Errors occurred during the nuke phase.");
910    } else if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "RESTORE")) {
911        log_to_screen
912            ("PC was restored successfully. Thank you for using Mondo Rescue.");
913        log_to_screen
914            ("Please visit our website at http://www.mondorescue.org for more information.");
915    } else {
916        strcpy(tmp,"Mondo has restored your system.\n\nPlease wait for the command prompt. Then remove the backup media and reboot.\n\nPlease visit our website at http://www.mondorescue.org for more information.");
917            popup_and_OK(tmp);
918        log_to_screen
919          ("Mondo has restored your system. Please wait for the command prompt.");
920        log_to_screen
921            ("Then remove the backup media and reboot.");
922        log_to_screen
923            ("Please visit our website at http://www.mondorescue.org for more information.");
924    }
925    g_I_have_just_nuked = TRUE;
926/*
927  if (!boot_loader_installed && !does_file_exist(DO_MBR_PLEASE))
928    {
929      log_to_screen("PLEASE RUN 'mondorestore --mbr' NOW TO INITIALIZE YOUR BOOT SECTOR");
930      write_one_liner_data_file(DO_MBR_PLEASE, "mondorestore --mbr");
931    }
932*/
933    return (retval);
934}
935
936/**************************************************************************
937 *END_NUKE_MODE                                                           *
938 **************************************************************************/
939
940
941
942/**
943 * Restore the user's data (or a subset of it) to the live filesystem.
944 * This should not be called if we're booted from CD!
945 * @param bkpinfo The backup information structure. Most fields are used.
946 * @return 0 for success, or the number of errors encountered.
947 */
948int restore_to_live_filesystem()
949{
950    int retval = 0;
951
952  /** malloc **/
953    char *old_restpath;
954
955    struct mountlist_itself *mountlist = NULL;
956//  static
957    struct raidlist_itself *raidlist = NULL;
958    struct s_node *filelist = NULL;
959
960    log_msg(1, "restore_to_live_filesystem() - starting");
961    assert(bkpinfo != NULL);
962    malloc_string(old_restpath);
963    mountlist = malloc(sizeof(struct mountlist_itself));
964    raidlist = malloc(sizeof(struct raidlist_itself));
965    if (!mountlist || !raidlist) {
966        fatal_error("Cannot malloc() mountlist and/or raidlist");
967    }
968
969    strcpy(bkpinfo->restore_path, "/");
970    if (!g_restoring_live_from_cd && !g_restoring_live_from_nfs) {
971        popup_and_OK
972            ("Please insert tape/CD/USB Key, then hit 'OK' to continue.");
973        sleep(1);
974    }
975    if (!g_restoring_live_from_nfs) {
976        interactively_obtain_media_parameters_from_user(FALSE);
977    }
978    log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
979    if (!bkpinfo->media_device[0]) {
980        log_msg(2, "Warning - failed to find media dev");
981    }
982
983
984    log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
985
986    open_evalcall_form("Thinking...");
987
988    get_cfg_file_from_archive_or_bust();
989    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
990    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
991
992    close_evalcall_form();
993    retval = load_mountlist(mountlist, g_mountlist_fname);
994    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
995
996    if (!g_restoring_live_from_nfs && (filelist = process_filelist_and_biggielist())) {
997        save_filelist(filelist, "/tmp/selected-files.txt");
998        strcpy(old_restpath, bkpinfo->restore_path);
999        if (popup_and_get_string("Restore path",
1000                                 "Restore files to where? )",
1001                                 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
1002            iamhere("Restoring everything");
1003            retval += restore_everything(filelist);
1004            free_filelist(filelist);
1005            strcpy(bkpinfo->restore_path, old_restpath);
1006        } else {
1007            free_filelist(filelist);
1008        }
1009        strcpy(bkpinfo->restore_path, old_restpath);
1010    } else {
1011        if (filelist != NULL) {
1012            retval += restore_everything(NULL);
1013        }
1014    }
1015    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1016        log_msg(2,
1017                "Tape : I don't need to unmount or eject the CD-ROM.");
1018    } else {
1019        run_program_and_log_output("umount " MNT_CDROM, FALSE);
1020        if (!bkpinfo->please_dont_eject) {
1021            eject_device(bkpinfo->media_device);
1022        }
1023    }
1024    run_program_and_log_output("umount " MNT_CDROM, FALSE);
1025    if (!bkpinfo->please_dont_eject) {
1026        eject_device(bkpinfo->media_device);
1027    }
1028    paranoid_free(old_restpath);
1029    free(mountlist);
1030    free(raidlist);
1031    return (retval);
1032}
1033
1034/**************************************************************************
1035 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
1036 **************************************************************************/
1037
1038/* @} - end of restoreGroup */
1039
1040
1041#include <utime.h>
1042/**
1043 * @addtogroup LLrestoreGroup
1044 * @{
1045 */
1046/**
1047 * Restore biggiefile @p bigfileno from the currently mounted CD.
1048 * @param bkpinfo The backup information structure. Fields used:
1049 * - @c bkpinfo->backup_media_type
1050 * - @c bkpinfo->restore_path
1051 * @param bigfileno The biggiefile number (starting from 0) to restore.
1052 * @param filelist The node structure containing the list of files to restore.
1053 * If the biggiefile is not in this list, it will be skipped (return value will
1054 * still indicate success).
1055 * @return 0 for success (or skip), nonzero for failure.
1056 */
1057int
1058restore_a_biggiefile_from_CD(long bigfileno,
1059                             struct s_node *filelist,
1060                             char *pathname_of_last_file_restored)
1061{
1062    FILE *fin;
1063    FILE *fout;
1064    FILE *fbzip2;
1065
1066  /** malloc ***/
1067    char *checksum, *outfile_fname, *tmp, *bzip2_command,
1068        *ntfsprog_command, *suffix, *sz_devfile;
1069    char *bigblk;
1070    char *p;
1071    int retval = 0;
1072    int finished = FALSE;
1073    long sliceno;
1074    long siz;
1075    char ntfsprog_fifo[MAX_STR_LEN];
1076    char *file_to_openout = NULL;
1077    struct s_filename_and_lstat_info biggiestruct;
1078    struct utimbuf the_utime_buf, *ubuf;
1079    bool use_ntfsprog_hack = FALSE;
1080    pid_t pid;
1081    int res = 0;
1082    int old_loglevel;
1083    char sz_msg[MAX_STR_LEN];
1084    struct s_node *node;
1085
1086    old_loglevel = g_loglevel;
1087    ubuf = &the_utime_buf;
1088    assert(bkpinfo != NULL);
1089
1090    malloc_string(checksum);
1091    malloc_string(outfile_fname);
1092    malloc_string(tmp);
1093    malloc_string(bzip2_command);
1094    malloc_string(ntfsprog_command);
1095    malloc_string(suffix);
1096    malloc_string(sz_devfile);
1097
1098    pathname_of_last_file_restored[0] = '\0';
1099    if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
1100        fatal_error("Cannot malloc bigblk");
1101    }
1102
1103    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1104        log_to_screen("Cannot even open bigfile's info file");
1105        return (1);
1106    }
1107
1108    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1109    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1110        sizeof(biggiestruct)) {
1111        log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1112                bigfileno + 1);
1113    }
1114    paranoid_fclose(fin);
1115
1116    strcpy(checksum, biggiestruct.checksum);
1117
1118    if (!checksum[0]) {
1119        sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
1120                bigfileno + 1);
1121        log_msg(3, tmp);
1122        p = checksum;
1123    }
1124
1125    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
1126    {
1127        strcpy(outfile_fname, biggiestruct.filename);
1128    } else {
1129        sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1130                biggiestruct.filename);
1131    }
1132
1133    /* skip file if we have a selective restore subset & it doesn't match */
1134    if (filelist != NULL) {
1135        node = find_string_at_node(filelist, biggiestruct.filename);
1136        if (!node) {
1137            log_msg(0, "Skipping %s (name isn't in filelist)",
1138                    biggiestruct.filename);
1139            pathname_of_last_file_restored[0] = '\0';
1140            return (0);
1141        } else if (!(node->selected)) {
1142            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1143                    biggiestruct.filename);
1144            pathname_of_last_file_restored[0] = '\0';
1145            return (0);
1146        }
1147    }
1148    /* otherwise, continue */
1149
1150    log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1151    if (biggiestruct.use_ntfsprog) {
1152        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1153            log_msg(1,
1154                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1155            log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1156            biggiestruct.use_ntfsprog = FALSE;
1157        }
1158    }
1159
1160    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
1161//  if (!strncmp ( biggiestruct.filename, "/dev/", 5))
1162    {
1163        g_loglevel = 4;
1164        use_ntfsprog_hack = TRUE;
1165        log_msg(2,
1166                "Calling ntfsclone in background because %s is an NTFS /dev entry",
1167                outfile_fname);
1168        sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
1169                (int) (random() % 32768));
1170        mkfifo(sz_devfile, 0x770);
1171        strcpy(ntfsprog_fifo, sz_devfile);
1172        file_to_openout = ntfsprog_fifo;
1173        switch (pid = fork()) {
1174        case -1:
1175            fatal_error("Fork failure");
1176        case 0:
1177            log_msg(3,
1178                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1179                    biggiestruct.filename, ntfsprog_fifo);
1180            res =
1181                feed_outfrom_ntfsprog(biggiestruct.filename,
1182                                       ntfsprog_fifo);
1183//          log_msg(3, "CHILD - fip - exiting");
1184            exit(res);
1185            break;
1186        default:
1187            log_msg(3,
1188                    "feed_into_ntfsprog() called in background --- pid=%ld",
1189                    (long int) (pid));
1190        }
1191    } else {
1192        use_ntfsprog_hack = FALSE;
1193        ntfsprog_fifo[0] = '\0';
1194        file_to_openout = outfile_fname;
1195        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1196        {
1197            make_hole_for_file(outfile_fname);
1198        }
1199    }
1200
1201    sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
1202            outfile_fname);
1203    log_msg(2, tmp);
1204
1205    /*
1206       last slice is zero-length and uncompressed; when we find it, we stop.
1207       We DON'T wait until there are no more slices; if we did that,
1208       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1209     */
1210
1211    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1212            MAX_STR_LEN - 1);
1213    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1214
1215    log_msg(3, "file_to_openout = %s", file_to_openout);
1216    if (!(fout = fopen(file_to_openout, "w"))) {
1217        log_to_screen("Cannot openout outfile_fname - hard disk full?");
1218        return (1);
1219    }
1220    log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1221
1222    for (sliceno = 1, finished = FALSE; !finished;) {
1223        if (!does_file_exist
1224            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1225            &&
1226            !does_file_exist(slice_fname
1227                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1228            &&
1229            !does_file_exist(slice_fname
1230                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1231            &&
1232            !does_file_exist(slice_fname
1233                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1234            log_msg(3,
1235                    "Cannot find a data slice or terminator slice on CD %d",
1236                    g_current_media_number);
1237            g_current_media_number++;
1238            sprintf(tmp,
1239                    "Asking for %s #%d so that I may read slice #%ld\n",
1240                    media_descriptor_string(bkpinfo->backup_media_type),
1241                    g_current_media_number, sliceno);
1242            log_msg(2, tmp);
1243            sprintf(tmp, "Restoring from %s #%d",
1244                    media_descriptor_string(bkpinfo->backup_media_type),
1245                    g_current_media_number);
1246            log_to_screen(tmp);
1247            insist_on_this_cd_number(g_current_media_number);
1248            log_to_screen("Continuing to restore.");
1249        } else {
1250            strcpy(tmp,
1251                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1252            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1253                log_msg(2,
1254                        "End of bigfile # %ld (slice %ld is the terminator)",
1255                        bigfileno + 1, sliceno);
1256                finished = TRUE;
1257                continue;
1258            } else {
1259                if (does_file_exist
1260                    (slice_fname
1261                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1262                    strcpy(bzip2_command, "lzop");
1263                    strcpy(suffix, "lzo");
1264                } else
1265                    if (does_file_exist
1266                        (slice_fname
1267                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1268                    strcpy(bzip2_command, "gzip");
1269                    strcpy(suffix, "gz");
1270                } else
1271                    if (does_file_exist
1272                        (slice_fname
1273                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1274                    strcpy(bzip2_command, "bzip2");
1275                    strcpy(suffix, "bz2");
1276                } else
1277                    if (does_file_exist
1278                        (slice_fname
1279                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1280                    strcpy(bzip2_command, "");
1281                    strcpy(suffix, "");
1282                } else {
1283                    log_to_screen("OK, that's pretty fsck0red...");
1284                    return (1);
1285                }
1286            }
1287            if (bzip2_command[0] != '\0') {
1288                sprintf(bzip2_command + strlen(bzip2_command),
1289                        " -dc %s 2>> %s",
1290                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1291                                    suffix), MONDO_LOGFILE);
1292            } else {
1293                sprintf(bzip2_command, "cat %s 2>> %s",
1294                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1295                                    suffix), MONDO_LOGFILE);
1296            }
1297            sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ",
1298                    media_descriptor_string(bkpinfo->backup_media_type),
1299                    g_current_media_number, bigfileno + 1, sliceno);
1300            log_msg(2, tmp);
1301
1302            if (!g_text_mode) {
1303                newtDrawRootText(0, g_noof_rows - 2, tmp);
1304                newtRefresh();
1305                strip_spaces(tmp);
1306                update_progress_form(tmp);
1307            }
1308            if (!(fbzip2 = popen(bzip2_command, "r"))) {
1309                fatal_error("Can't run popen command");
1310            }
1311            while (!feof(fbzip2)) {
1312                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1313                if (siz > 0) {
1314                    sprintf(sz_msg, "Read %ld from fbzip2", siz);
1315                    siz = fwrite(bigblk, 1, siz, fout);
1316                    sprintf(sz_msg + strlen(sz_msg),
1317                            "; written %ld to fout", siz);
1318//        log_msg(2. sz_msg);
1319                }
1320            }
1321            paranoid_pclose(fbzip2);
1322
1323
1324            sliceno++;
1325            g_current_progress++;
1326        }
1327    }
1328/*
1329  memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
1330  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1331  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1332  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1333  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1334*/
1335    paranoid_fclose(fout);
1336    g_loglevel = old_loglevel;
1337
1338    if (use_ntfsprog_hack) {
1339        log_msg(3, "Waiting for ntfsclone to finish");
1340        sprintf(tmp,
1341                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1342        while (system(tmp) == 0) {
1343            sleep(1);
1344        }
1345        log_it("OK, ntfsclone has really finished");
1346    }
1347
1348    if (strcmp(outfile_fname, "/dev/null")) {
1349        chown(outfile_fname, biggiestruct.properties.st_uid,
1350              biggiestruct.properties.st_gid);
1351        chmod(outfile_fname, biggiestruct.properties.st_mode);
1352        ubuf->actime = biggiestruct.properties.st_atime;
1353        ubuf->modtime = biggiestruct.properties.st_mtime;
1354        utime(outfile_fname, ubuf);
1355    }
1356    paranoid_free(bigblk);
1357    paranoid_free(checksum);
1358    paranoid_free(outfile_fname);
1359    paranoid_free(tmp);
1360    paranoid_free(bzip2_command);
1361    paranoid_free(ntfsprog_command);
1362    paranoid_free(suffix);
1363    paranoid_free(sz_devfile);
1364
1365    return (retval);
1366}
1367
1368/**************************************************************************
1369 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
1370 **************************************************************************/
1371
1372
1373
1374/**
1375 * Restore a biggiefile from the currently opened stream.
1376 * @param bkpinfo The backup information structure. Fields used:
1377 * - @c bkpinfo->restore_path
1378 * - @c bkpinfo->zip_exe
1379 * @param orig_bf_fname The original filename of the biggiefile.
1380 * @param biggiefile_number The number of the biggiefile (starting from 0).
1381 * @param orig_checksum Unused.
1382 * @param biggiefile_size Unused.
1383 * @param filelist The node structure containing the list of files to be restored.
1384 * If @p orig_bf_fname is not in the list, it will be ignored.
1385 * @return 0 for success (or skip), nonzero for failure.
1386 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
1387 */
1388int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
1389                                     long long biggiefile_size, //UNUSED
1390                                     struct s_node *filelist,
1391                                     int use_ntfsprog,
1392                                     char *pathname_of_last_file_restored)
1393{
1394    FILE *pout;
1395    FILE *fin;
1396
1397  /** mallocs ********/
1398    char *tmp;
1399    char *command;
1400    char *outfile_fname;
1401    char *ntfsprog_command;
1402    char *sz_devfile;
1403    char *ntfsprog_fifo;
1404    char *file_to_openout = NULL;
1405
1406    struct s_node *node;
1407
1408    int old_loglevel;
1409    long current_slice_number = 0;
1410    int retval = 0;
1411    int res = 0;
1412    int ctrl_chr = '\0';
1413    long long slice_siz;
1414    bool dummy_restore = FALSE;
1415    bool use_ntfsprog_hack = FALSE;
1416    pid_t pid;
1417    struct s_filename_and_lstat_info biggiestruct;
1418    struct utimbuf the_utime_buf, *ubuf;
1419    ubuf = &the_utime_buf;
1420
1421    malloc_string(tmp);
1422    malloc_string(ntfsprog_fifo);
1423    malloc_string(outfile_fname);
1424    malloc_string(command);
1425    malloc_string(sz_devfile);
1426    malloc_string(ntfsprog_command);
1427    old_loglevel = g_loglevel;
1428    assert(bkpinfo != NULL);
1429    assert(orig_bf_fname != NULL);
1430    assert(orig_checksum != NULL);
1431
1432    pathname_of_last_file_restored[0] = '\0';
1433    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1434        use_ntfsprog = 1;
1435        log_msg(1, "%s --- pih=YES", orig_bf_fname);
1436    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1437        use_ntfsprog = 0;
1438        log_msg(1, "%s --- pih=NO", orig_bf_fname);
1439    } else {
1440        use_ntfsprog = 0;
1441        log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1442    }
1443
1444    strncpy(pathname_of_last_file_restored, orig_bf_fname,
1445            MAX_STR_LEN - 1);
1446    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1447
1448    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1449
1450    if (filelist != NULL) {
1451        node = find_string_at_node(filelist, orig_bf_fname);
1452        if (!node) {
1453            dummy_restore = TRUE;
1454            log_msg(1,
1455                    "Skipping big file %ld (%s) - not in biggielist subset",
1456                    biggiefile_number + 1, orig_bf_fname);
1457            pathname_of_last_file_restored[0] = '\0';
1458        } else if (!(node->selected)) {
1459            dummy_restore = TRUE;
1460            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1461                    orig_bf_fname);
1462            pathname_of_last_file_restored[0] = '\0';
1463        }
1464    }
1465
1466    if (use_ntfsprog) {
1467        if (strncmp(orig_bf_fname, "/dev/", 5)) {
1468            log_msg(1,
1469                    "I was in error when I set use_ntfsprog to TRUE.");
1470            log_msg(1, "%s isn't even in /dev", orig_bf_fname);
1471            use_ntfsprog = FALSE;
1472        }
1473    }
1474
1475    if (use_ntfsprog) {
1476        g_loglevel = 4;
1477        strcpy(outfile_fname, orig_bf_fname);
1478        use_ntfsprog_hack = TRUE;
1479        log_msg(2,
1480                "Calling ntfsclone in background because %s is a /dev entry",
1481                outfile_fname);
1482        sprintf(sz_devfile, "%s/%d.%d.000", 
1483                bkpinfo->tmpdir,
1484                (int) (random() % 32768),
1485                (int) (random() % 32768));
1486        mkfifo(sz_devfile, 0x770);
1487        strcpy(ntfsprog_fifo, sz_devfile);
1488        file_to_openout = ntfsprog_fifo;
1489        switch (pid = fork()) {
1490        case -1:
1491            fatal_error("Fork failure");
1492        case 0:
1493            log_msg(3,
1494                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1495                    outfile_fname, ntfsprog_fifo);
1496            res =
1497                feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1498//          log_msg(3, "CHILD - fip - exiting");
1499            exit(res);
1500            break;
1501        default:
1502            log_msg(3,
1503                    "feed_into_ntfsprog() called in background --- pid=%ld",
1504                    (long int) (pid));
1505        }
1506    } else {
1507        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
1508        {
1509            strcpy(outfile_fname, orig_bf_fname);
1510        } else                  // biggiefile
1511        {
1512            sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1513                    orig_bf_fname);
1514        }
1515        use_ntfsprog_hack = FALSE;
1516        ntfsprog_fifo[0] = '\0';
1517        file_to_openout = outfile_fname;
1518        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1519        {
1520            make_hole_for_file(outfile_fname);
1521        }
1522        sprintf(tmp, "Reassembling big file %ld (%s)",
1523                biggiefile_number + 1, orig_bf_fname);
1524        log_msg(2, tmp);
1525    }
1526
1527    if (dummy_restore) {
1528        sprintf(outfile_fname, "/dev/null");
1529    }
1530
1531    if (!bkpinfo->zip_exe[0]) {
1532        sprintf(command, "cat > \"%s\"", file_to_openout);
1533    } else {
1534        sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1535                file_to_openout, MONDO_LOGFILE);
1536        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
1537            /* Ignore SIGPIPE for gzip as it causes errors on big files
1538             * Cf: http://trac.mondorescue.org/ticket/244
1539             */
1540            signal(SIGPIPE,SIG_IGN);
1541        }
1542    }
1543    sprintf(tmp, "Pipe command = '%s'", command);
1544    log_msg(3, tmp);
1545
1546    /* restore biggiefile, one slice at a time */
1547    if (!(pout = popen(command, "w"))) {
1548        fatal_error("Cannot pipe out");
1549    }
1550    for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1551         ctrl_chr != BLK_STOP_A_BIGGIE;
1552         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
1553        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1554            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1555        }
1556        sprintf(tmp, "Working on file #%ld, slice #%ld    ",
1557                biggiefile_number + 1, current_slice_number);
1558        log_msg(2, tmp);
1559        if (!g_text_mode) {
1560            newtDrawRootText(0, g_noof_rows - 2, tmp);
1561            newtRefresh();
1562        }
1563        strip_spaces(tmp);
1564        update_progress_form(tmp);
1565        if (current_slice_number == 0) {
1566            res =
1567                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
1568                                              slice_siz);
1569            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1570                log_OS_error("blah blah");
1571            } else {
1572                if (fread
1573                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1574                     fin) < sizeof(biggiestruct)) {
1575                    log_msg(2,
1576                            "Warning - unable to get biggiestruct of bigfile #%d",
1577                            biggiefile_number + 1);
1578                }
1579                paranoid_fclose(fin);
1580            }
1581        } else {
1582            res =
1583                read_file_from_stream_to_stream(pout, slice_siz);
1584        }
1585        retval += res;
1586        res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1587        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1588            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1589        }
1590        current_slice_number++;
1591        g_current_progress++;
1592    }
1593    paranoid_pclose(pout);
1594
1595    if (bkpinfo->zip_exe[0]) {
1596        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
1597            /* Re-enable SIGPIPE for gzip
1598             */
1599            signal(SIGPIPE, terminate_daemon);
1600        }
1601    }
1602
1603    log_msg(1, "pathname_of_last_file_restored is now %s",
1604            pathname_of_last_file_restored);
1605
1606    if (use_ntfsprog_hack) {
1607        log_msg(3, "Waiting for ntfsclone to finish");
1608        sprintf(tmp,
1609                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1610        while (system(tmp) == 0) {
1611            sleep(1);
1612        }
1613        log_msg(3, "OK, ntfsclone has really finished");
1614    }
1615
1616    log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1617    log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1618    if (strcmp(outfile_fname, "/dev/null")) {
1619        chmod(outfile_fname, biggiestruct.properties.st_mode);
1620        chown(outfile_fname, biggiestruct.properties.st_uid,
1621              biggiestruct.properties.st_gid);
1622        ubuf->actime = biggiestruct.properties.st_atime;
1623        ubuf->modtime = biggiestruct.properties.st_mtime;
1624        utime(outfile_fname, ubuf);
1625    }
1626
1627    paranoid_free(tmp);
1628    paranoid_free(outfile_fname);
1629    paranoid_free(command);
1630    paranoid_free(ntfsprog_command);
1631    paranoid_free(sz_devfile);
1632    paranoid_free(ntfsprog_fifo);
1633    g_loglevel = old_loglevel;
1634    return (retval);
1635}
1636
1637/**************************************************************************
1638 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
1639 **************************************************************************/
1640
1641
1642
1643/**
1644 * Restore @p tarball_fname from CD.
1645 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1646 * This will be used unmodified.
1647 * @param current_tarball_number The number (starting from 0) of the fileset
1648 * we're restoring now.
1649 * @param filelist The node structure containing the list of files to be
1650 * restored. If no file in the afioball is in this list, afio will still be
1651 * called, but nothing will be written.
1652 * @return 0 for success, nonzero for failure.
1653 */
1654int
1655restore_a_tarball_from_CD(char *tarball_fname,
1656                          long current_tarball_number,
1657                          struct s_node *filelist)
1658{
1659    int retval = 0;
1660    int res;
1661    char *p;
1662
1663  /** malloc **/
1664    char *command;
1665    char *tmp;
1666    char *filelist_name;
1667    char *filelist_subset_fname;
1668    char *executable;
1669    char *temp_log;
1670    char screen_message[100];
1671    long matches = 0;
1672    bool use_star;
1673    char *xattr_fname;
1674    char *acl_fname;
1675//  char files_to_restore_this_time_fname[MAX_STR_LEN];
1676
1677    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1678    malloc_string(command);
1679    malloc_string(tmp);
1680    malloc_string(filelist_name);
1681    malloc_string(filelist_subset_fname);
1682    malloc_string(executable);
1683    malloc_string(temp_log);
1684    malloc_string(xattr_fname);
1685    malloc_string(acl_fname);
1686
1687    log_msg(5, "Entering");
1688    filelist_subset_fname[0] = '\0';
1689    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1690//  sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
1691    sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
1692    run_program_and_log_output(command, 9);
1693    sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1694            (int) (random() % 32768));
1695
1696    sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
1697            current_tarball_number);
1698    if (length_of_file(filelist_name) <= 2) {
1699        log_msg(2, "There are _zero_ files in filelist '%s'",
1700                filelist_name);
1701        log_msg(2,
1702                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1703        log_msg(2,
1704                "but it's non-critical. It's cosmetic. Don't worry about it.");
1705        retval = 0;
1706        goto leave_sub;
1707    }
1708    if (count_lines_in_file(filelist_name) <= 0
1709        || length_of_file(tarball_fname) <= 0) {
1710        log_msg(3, "length_of_file(%s) = %llu", tarball_fname, length_of_file(tarball_fname));
1711        log_msg(3, "count_lines_in_file(%s) = %llu", tarball_fname, count_lines_in_file(tarball_fname));
1712        sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
1713                current_tarball_number);
1714        log_to_screen(tmp);
1715        retval = 1;
1716        goto leave_sub;
1717    }
1718
1719    if (filelist) {
1720        sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1721                current_tarball_number);
1722        if ((matches =
1723             save_filelist_entries_in_common(filelist_name, filelist,
1724                                             filelist_subset_fname,
1725                                             use_star))
1726            <= 0) {
1727            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1728            log_msg(1, tmp);
1729        } else {
1730            log_msg(3, "Saved fileset %ld's subset to %s",
1731                    current_tarball_number, filelist_subset_fname);
1732        }
1733        sprintf(screen_message, "Tarball #%ld --- %ld matches",
1734                current_tarball_number, matches);
1735        log_to_screen(screen_message);
1736    } else {
1737        filelist_subset_fname[0] = '\0';
1738    }
1739
1740    if (filelist == NULL || matches > 0) {
1741        if (g_getfattr) {
1742            sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1743                MNT_CDROM "/archives", current_tarball_number);
1744        }
1745        if (g_getfacl) {
1746            sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1747                current_tarball_number);
1748        }
1749        if (strstr(tarball_fname, ".bz2")) {
1750            strcpy(executable, "bzip2");
1751        } else if (strstr(tarball_fname, ".gz")) {
1752            strcpy(executable, "gzip");
1753        } else if (strstr(tarball_fname, ".lzo")) {
1754            strcpy(executable, "lzop");
1755        } else {
1756            executable[0] = '\0';
1757        }
1758        if (executable[0]) {
1759            sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
1760            if (run_program_and_log_output(tmp, FALSE)) {
1761                log_to_screen
1762                    ("(compare_a_tarball) Compression program %s not found - oh no!", executable);
1763                paranoid_MR_finish(1);
1764            }
1765            strcpy(tmp, executable);
1766            sprintf(executable, "-P %s -Z", tmp);
1767        }
1768#ifdef __FreeBSD__
1769#define BUFSIZE 512
1770#else
1771#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1772#endif
1773
1774//      if (strstr(tarball_fname, ".star."))
1775        if (use_star) {
1776            sprintf(command,
1777                    "star -x -force-remove -U " STAR_ACL_SZ
1778                    " errctl= file=%s", tarball_fname);
1779            if (strstr(tarball_fname, ".bz2")) {
1780                strcat(command, " -bz");
1781            }
1782        } else {
1783            if (filelist_subset_fname[0] != '\0') {
1784                sprintf(command,
1785                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1786                        TAPE_BLOCK_SIZE,
1787                        BUFSIZE, executable, filelist_subset_fname,
1788//             files_to_restore_this_time_fname,
1789                        tarball_fname);
1790            } else {
1791                sprintf(command,
1792                        "afio -i -b %ld -c %ld -M 8m %s %s",
1793                        TAPE_BLOCK_SIZE,
1794                        BUFSIZE, executable, tarball_fname);
1795            }
1796        }
1797#undef BUFSIZE
1798        sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
1799                temp_log);
1800        log_msg(1, "command = '%s'", command);
1801        unlink(temp_log);
1802        res = system(command);
1803        if (res) {
1804            p = strstr(command, "-acl ");
1805            if (p) {
1806                p[0] = p[1] = p[2] = p[3] = ' ';
1807                log_msg(1, "new command = '%s'", command);
1808                res = system(command);
1809            }
1810        }
1811        if (res && length_of_file(temp_log) < 5) {
1812            res = 0;
1813        }
1814
1815        if (g_getfattr) {
1816            log_msg(1, "Setting fattr list %s", xattr_fname);
1817            if (length_of_file(xattr_fname) > 0) {
1818                res = set_fattr_list(filelist_subset_fname, xattr_fname);
1819                if (res) {
1820                    log_to_screen
1821                        ("Errors occurred while setting extended attributes");
1822                } else {
1823                    log_msg(1, "I set xattr OK");
1824                }
1825                retval += res;
1826            }
1827        }
1828        if (g_getfacl) {
1829            log_msg(1, "Setting acl list %s", acl_fname);
1830            if (length_of_file(acl_fname) > 0) {
1831                res = set_acl_list(filelist_subset_fname, acl_fname);
1832                if (res) {
1833                    log_to_screen
1834                        ("Errors occurred while setting access control lists");
1835                } else {
1836                    log_msg(1, "I set ACL OK");
1837                }
1838                retval += res;
1839            }
1840        }
1841        if (retval) {
1842            sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1843            system(command);
1844            log_msg(2, "Errors occurred while processing fileset #%d",
1845                    current_tarball_number);
1846        } else {
1847            log_msg(2, "Fileset #%d processed OK", current_tarball_number);
1848        }
1849    }
1850    if (does_file_exist("/PAUSE")) {
1851        popup_and_OK
1852            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
1853    }
1854    unlink(filelist_subset_fname);
1855    unlink(xattr_fname);
1856    unlink(acl_fname);
1857    unlink(temp_log);
1858
1859  leave_sub:
1860    paranoid_free(command);
1861    paranoid_free(tmp);
1862    paranoid_free(filelist_name);
1863    paranoid_free(filelist_subset_fname);
1864    paranoid_free(executable);
1865    paranoid_free(temp_log);
1866    paranoid_free(xattr_fname);
1867    paranoid_free(acl_fname);
1868    log_msg(5, "Leaving");
1869    return (retval);
1870}
1871
1872/**************************************************************************
1873 *END_RESTORE_A_TARBALL_FROM_CD                                           *
1874 **************************************************************************/
1875
1876
1877/**
1878 * Restore a tarball from the currently opened stream.
1879 * @param bkpinfo The backup information structure. Fields used:
1880 * - @c bkpinfo->backup_media_type
1881 * - @c bkpinfo->media_device
1882 * - @c bkpinfo->zip_exe
1883 * @param tarball_fname The filename of the afioball to restore.
1884 * @param current_tarball_number The number (starting from 0) of the fileset
1885 * we're restoring now.
1886 * @param filelist The node structure containing the list of files to be
1887 * restored. If no file in the afioball is in this list, afio will still be
1888 * called, but nothing will be written.
1889 * @param size The size (in @b bytes) of the afioball.
1890 * @return 0 for success, nonzero for failure.
1891 */
1892int
1893restore_a_tarball_from_stream(char *tarball_fname,
1894                              long current_tarball_number,
1895                              struct s_node *filelist,
1896                              long long size, char *xattr_fname,
1897                              char *acl_fname)
1898{
1899    int retval = 0;
1900    int res = 0;
1901
1902  /** malloc add ***/
1903    char *tmp;
1904    char *command;
1905    char *afio_fname;
1906    char *filelist_fname;
1907    char *filelist_subset_fname;
1908    char *executable;
1909    long matches = 0;
1910    bool restore_this_fileset = FALSE;
1911    bool use_star;
1912
1913    assert(bkpinfo != NULL);
1914    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1915    malloc_string(filelist_subset_fname);
1916    malloc_string(filelist_fname);
1917    malloc_string(afio_fname);
1918    malloc_string(executable);
1919    malloc_string(command);
1920    malloc_string(tmp);
1921    filelist_subset_fname[0] = '\0';
1922    /* to do it with a file... */
1923    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1924    sprintf(tmp,
1925            "Restoring from fileset #%ld (%ld KB) on %s #%d",
1926            current_tarball_number, (long) size >> 10,
1927            media_descriptor_string(bkpinfo->backup_media_type),
1928            g_current_media_number);
1929    log_msg(2, tmp);
1930    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1931
1932  /****************************************************************************
1933   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
1934   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
1935   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
1936   ****************************************************************************/
1937    filelist_fname[0] = filelist_subset_fname[0] = '\0';
1938    sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1939            current_tarball_number);
1940    sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1941            current_tarball_number);
1942    sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1943            bkpinfo->tmpdir, current_tarball_number);
1944//  sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
1945    res = read_file_from_stream_to_file(afio_fname, size);
1946    if (strstr(tarball_fname, ".star")) {
1947        bkpinfo->use_star = TRUE;
1948    }
1949    if (res) {
1950        log_msg(1, "Warning - error reading afioball from tape");
1951    }
1952    if (bkpinfo->compression_level == 0) {
1953        executable[0] = '\0';
1954    } else {
1955        if (bkpinfo->use_star) {
1956            strcpy(executable, " -bz");
1957        } else {
1958            sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
1959        }
1960    }
1961
1962    if (!filelist)              // if unconditional restore then restore entire fileset
1963    {
1964        restore_this_fileset = TRUE;
1965    } else                      // If restoring selectively then get TOC from tarball
1966    {
1967        if (strstr(tarball_fname, ".star.")) {
1968            use_star = TRUE;
1969            sprintf(command, "star -t file=%s %s", afio_fname, executable);
1970        } else {
1971            use_star = FALSE;
1972            sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1973                    executable, afio_fname);
1974        }
1975        sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
1976                MONDO_LOGFILE);
1977        log_msg(1, "command = %s", command);
1978        if (system(command)) {
1979            log_msg(4, "Warning - error occurred while retrieving TOC");
1980        }
1981        if ((matches =
1982             save_filelist_entries_in_common(filelist_fname, filelist,
1983                                             filelist_subset_fname,
1984                                             use_star))
1985            <= 0 || length_of_file(filelist_subset_fname) < 2) {
1986            if (length_of_file(filelist_subset_fname) < 2) {
1987                log_msg(1, "No matches found in fileset %ld",
1988                        current_tarball_number);
1989            }
1990            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1991            log_msg(2, tmp);
1992            restore_this_fileset = FALSE;
1993        } else {
1994            log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1995                    matches, current_tarball_number,
1996                    filelist_subset_fname);
1997            restore_this_fileset = TRUE;
1998        }
1999    }
2000
2001// Concoct the call to star/afio to restore files
2002    if (strstr(tarball_fname, ".star."))    // star
2003    {
2004        sprintf(command, "star -x file=%s %s", afio_fname, executable);
2005        if (filelist) {
2006            sprintf(command + strlen(command), " list=%s",
2007                    filelist_subset_fname);
2008        }
2009    } else                      // afio
2010    {
2011        sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
2012                executable);
2013        if (filelist) {
2014            sprintf(command + strlen(command), " -w %s",
2015                    filelist_subset_fname);
2016        }
2017        sprintf(command + strlen(command), " %s", afio_fname);
2018    }
2019    sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
2020
2021// Call if IF there are files to restore (selectively/unconditionally)
2022    if (restore_this_fileset) {
2023        log_msg(1, "Calling command='%s'", command);
2024        paranoid_system(command);
2025
2026        if (g_getfattr) {
2027            iamhere("Restoring xattr stuff");
2028            res = set_fattr_list(filelist_subset_fname, xattr_fname);
2029            if (res) {
2030                log_msg(1, "Errors occurred while setting xattr");
2031            } else {
2032                log_msg(1, "I set xattr OK");
2033            }
2034            retval += res;
2035        }
2036
2037        if (g_getfacl) {
2038            iamhere("Restoring acl stuff");
2039            res = set_acl_list(filelist_subset_fname, acl_fname);
2040            if (res) {
2041                log_msg(1, "Errors occurred while setting ACL");
2042            } else {
2043                log_msg(1, "I set ACL OK");
2044            }
2045            retval += res;
2046        }
2047
2048    } else {
2049        log_msg(1, "NOT CALLING '%s'", command);
2050    }
2051
2052    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
2053        log_to_screen("Paused after set %ld", current_tarball_number);
2054        popup_and_OK("Pausing. Press ENTER to continue.");
2055    }
2056
2057    unlink(filelist_subset_fname);
2058    unlink(filelist_fname);
2059    unlink(afio_fname);
2060
2061    paranoid_free(filelist_subset_fname);
2062    paranoid_free(filelist_fname);
2063    paranoid_free(afio_fname);
2064    paranoid_free(command);
2065    paranoid_free(tmp);
2066    return (retval);
2067}
2068
2069/**************************************************************************
2070 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
2071 **************************************************************************/
2072
2073
2074
2075
2076/**
2077 * Restore all biggiefiles from all media in this CD backup.
2078 * The CD with the last afioball should be currently mounted.
2079 * @param bkpinfo The backup information structure. @c backup_media_type is the
2080 * only field used in this function.
2081 * @param filelist The node structure containing the list of files to be
2082 * restored. If a prospective biggiefile is not in this list, it will be ignored.
2083 * @return 0 for success, nonzero for failure.
2084 */
2085int
2086restore_all_biggiefiles_from_CD(struct s_node *filelist)
2087{
2088    int retval = 0;
2089    int res = 0;
2090    long noof_biggiefiles, bigfileno = 0, total_slices;
2091  /** malloc **/
2092    char *tmp;
2093    bool just_changed_cds = FALSE;
2094    char *xattr_fname;
2095    char *acl_fname;
2096    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
2097    char *pathname_of_last_biggie_restored;
2098    FILE *fbw = NULL;
2099
2100    malloc_string(xattr_fname);
2101    malloc_string(acl_fname);
2102    malloc_string(tmp);
2103    malloc_string(biggies_whose_EXATs_we_should_set);
2104    malloc_string(pathname_of_last_biggie_restored);
2105    assert(bkpinfo != NULL);
2106
2107    sprintf(biggies_whose_EXATs_we_should_set,
2108            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2109    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2110        log_msg(1, "Warning - cannot openout %s",
2111                biggies_whose_EXATs_we_should_set);
2112    }
2113
2114    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2115    total_slices = atol(tmp);
2116    sprintf(tmp, "Reassembling large files      ");
2117    mvaddstr_and_log_it(g_currentY, 0, tmp);
2118    if (length_of_file(BIGGIELIST) < 6) {
2119        log_msg(1, "OK, no biggielist; not restoring biggiefiles");
2120        return (0);
2121    }
2122    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
2123    if (noof_biggiefiles <= 0) {
2124        log_msg(2,
2125                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
2126        return (0);
2127    }
2128    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2129            noof_biggiefiles);
2130    log_msg(2, tmp);
2131
2132    open_progress_form("Reassembling large files",
2133                       "I am now reassembling all the large files.",
2134                       "Please wait. This may take some time.",
2135                       "", total_slices);
2136    for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
2137        log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
2138        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
2139            log_msg(3,
2140                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
2141            log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
2142                    bigfileno + 1,
2143                    media_descriptor_string(bkpinfo->backup_media_type),
2144                    g_current_media_number);
2145            log_msg(3, "Slicename would have been %s",
2146                    slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
2147            // I'm not positive 'just_changed_cds' is even necessary...
2148            if (just_changed_cds) {
2149                just_changed_cds = FALSE;
2150                log_msg(3,
2151                        "I'll continue to scan this CD for bigfiles to be restored.");
2152            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2153                insist_on_this_cd_number(++g_current_media_number);
2154                sprintf(tmp, "Restoring from %s #%d",
2155                        media_descriptor_string(bkpinfo->backup_media_type),
2156                        g_current_media_number);
2157                log_to_screen(tmp);
2158                just_changed_cds = TRUE;
2159            } else {
2160                /* That big file doesn't exist, but the followings may */
2161                /* So we need to continue looping */
2162                log_msg(2, "There was no bigfile #%ld. That's OK.",
2163                    bigfileno + 1);
2164                log_msg(2, "I'm going to stop restoring bigfiles now.");
2165                retval++;
2166                bigfileno++;
2167            }
2168        } else {
2169            just_changed_cds = FALSE;
2170            sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
2171            update_progress_form(tmp);
2172            res =
2173                restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
2174            iamhere(pathname_of_last_biggie_restored);
2175            if (fbw && pathname_of_last_biggie_restored[0]) {
2176                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2177            }
2178            retval += res;
2179            bigfileno++;
2180
2181        }
2182    }
2183
2184    if (fbw) {
2185        fclose(fbw);
2186        if (g_getfattr) {
2187            sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2188            if (length_of_file(xattr_fname) > 0) {
2189                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2190            }
2191        }
2192        if (g_getfacl) {
2193            sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2194            if (length_of_file(acl_fname) > 0) {
2195                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2196            }
2197        }
2198    }
2199    if (does_file_exist("/PAUSE")) {
2200        popup_and_OK
2201            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2202    }
2203    close_progress_form();
2204    if (retval) {
2205        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2206    } else {
2207        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2208    }
2209    paranoid_free(xattr_fname);
2210    paranoid_free(acl_fname);
2211    paranoid_free(tmp);
2212    paranoid_free(biggies_whose_EXATs_we_should_set);
2213    paranoid_free(pathname_of_last_biggie_restored);
2214    return (retval);
2215}
2216
2217/**************************************************************************
2218 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2219 **************************************************************************/
2220
2221
2222
2223/**
2224 * Restore all afioballs from all CDs in the backup.
2225 * The first CD should be inserted (if not, it will be asked for).
2226 * @param bkpinfo The backup information structure. @c backup_media_type is the
2227 * only field used in @e this function.
2228 * @param filelist The node structure containing the list of files to be
2229 * restored. If no file in some particular afioball is in this list, afio will
2230 * still be called for that fileset, but nothing will be written.
2231 * @return 0 for success, or the number of filesets that failed.
2232 */
2233int
2234restore_all_tarballs_from_CD(struct s_node *filelist)
2235{
2236    int retval = 0;
2237    int res;
2238    int attempts;
2239    long current_tarball_number = 0;
2240    long max_val;
2241  /**malloc ***/
2242    char *tmp;
2243    char *tarball_fname;
2244    char *progress_str;
2245    char *comment;
2246
2247    malloc_string(tmp);
2248    malloc_string(tarball_fname);
2249    malloc_string(progress_str);
2250    malloc_string(comment);
2251
2252    assert(bkpinfo != NULL);
2253
2254    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2255    log_msg(2,
2256            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2257    if (g_current_media_number != 1) {
2258        log_msg(3, "OK, that's jacked up.");
2259        g_current_media_number = 1;
2260    }
2261    insist_on_this_cd_number(g_current_media_number);
2262    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2263    max_val = atol(tmp) + 1;
2264    sprintf(progress_str, "Restoring from %s #%d",
2265            media_descriptor_string(bkpinfo->backup_media_type),
2266            g_current_media_number);
2267    log_to_screen(progress_str);
2268    open_progress_form("Restoring from archives",
2269                       "Restoring data from the archives.",
2270                       "Please wait. This may take some time.",
2271                       progress_str, max_val);
2272    for (;;) {
2273        insist_on_this_cd_number(g_current_media_number);
2274        update_progress_form(progress_str);
2275        sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2276                current_tarball_number);
2277        if (!does_file_exist(tarball_fname)) {
2278            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2279                current_tarball_number);
2280        }
2281        if (!does_file_exist(tarball_fname)) {
2282            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2283                    current_tarball_number);
2284        }
2285        if (!does_file_exist(tarball_fname)) {
2286            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2287                    current_tarball_number);
2288        }
2289        if (!does_file_exist(tarball_fname)) {
2290            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2291                    current_tarball_number);
2292        }
2293        if (!does_file_exist(tarball_fname)) {
2294            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
2295                    current_tarball_number);
2296        }
2297        if (!does_file_exist(tarball_fname)) {
2298            if (current_tarball_number == 0) {
2299                log_to_screen
2300                    ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
2301                return (0);
2302            }
2303            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2304                || system("find " MNT_CDROM
2305                          "/archives/slice* > /dev/null 2> /dev/null") ==
2306                0) {
2307                break;
2308            }
2309            g_current_media_number++;
2310            sprintf(progress_str, "Restoring from %s #%d",
2311                    media_descriptor_string(bkpinfo->backup_media_type),
2312                    g_current_media_number);
2313            log_to_screen(progress_str);
2314        } else {
2315            sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2316                    current_tarball_number,
2317                    media_descriptor_string(bkpinfo->backup_media_type),
2318                    g_current_media_number);
2319//    log_msg(3, "progress_str = %s", progress_str);
2320            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2321                 attempts++) {
2322                res =
2323                    restore_a_tarball_from_CD(tarball_fname,
2324                                              current_tarball_number,
2325                                              filelist);
2326            }
2327            sprintf(tmp, "%s #%d, fileset #%ld - restore ",
2328                    media_descriptor_string(bkpinfo->backup_media_type),
2329                    g_current_media_number, current_tarball_number);
2330            if (res) {
2331                strcat(tmp, "reported errors");
2332            } else if (attempts > 1) {
2333                strcat(tmp, "succeeded");
2334            } else {
2335                strcat(tmp, "succeeded");
2336            }
2337            if (attempts > 1) {
2338                sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
2339                        attempts);
2340            }
2341            strcpy(comment, tmp);
2342            if (attempts > 1) {
2343                log_to_screen(comment);
2344            }
2345
2346            retval += res;
2347            current_tarball_number++;
2348            g_current_progress++;
2349        }
2350    }
2351    close_progress_form();
2352    if (retval) {
2353        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2354    } else {
2355        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2356    }
2357    paranoid_free(tmp);
2358    paranoid_free(tarball_fname);
2359    paranoid_free(progress_str);
2360    paranoid_free(comment);
2361
2362    return (retval);
2363}
2364
2365/**************************************************************************
2366 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2367 **************************************************************************/
2368
2369
2370
2371/**
2372 * Restore all biggiefiles from the currently opened stream.
2373 * @param bkpinfo The backup information structure. Passed to other functions.
2374 * @param filelist The node structure containing the list of files to be
2375 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2376 * @return 0 for success, or the number of biggiefiles that failed.
2377 */
2378int
2379restore_all_biggiefiles_from_stream(struct s_node *filelist)
2380{
2381    long noof_biggiefiles;
2382    long current_bigfile_number = 0;
2383    long total_slices;
2384
2385    int retval = 0;
2386    int res = 0;
2387    int ctrl_chr;
2388
2389  /** malloc add ****/
2390    char *tmp;
2391    char *biggie_fname;
2392    char *biggie_cksum;
2393    char *xattr_fname;
2394    char *acl_fname;
2395    char *p;
2396    char *pathname_of_last_biggie_restored;
2397    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
2398    long long biggie_size;
2399    FILE *fbw = NULL;
2400
2401    malloc_string(tmp);
2402    malloc_string(biggie_fname);
2403    malloc_string(biggie_cksum);
2404    malloc_string(xattr_fname);
2405    malloc_string(acl_fname);
2406    malloc_string(biggies_whose_EXATs_we_should_set);
2407    malloc_string(pathname_of_last_biggie_restored);
2408    assert(bkpinfo != NULL);
2409
2410    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2411
2412    total_slices = atol(tmp);
2413    sprintf(tmp, "Reassembling large files      ");
2414    if (g_getfattr) {
2415        sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2416    }
2417    if (g_getfacl) {
2418        sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2419    }
2420    mvaddstr_and_log_it(g_currentY, 0, tmp);
2421    sprintf(biggies_whose_EXATs_we_should_set,
2422            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2423    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2424        log_msg(1, "Warning - cannot openout %s",
2425                biggies_whose_EXATs_we_should_set);
2426    }
2427// get xattr and acl files if they're there
2428    res =
2429        read_header_block_from_stream(&biggie_size, biggie_fname,
2430                                      &ctrl_chr);
2431    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2432        res =
2433            read_EXAT_files_from_tape(&biggie_size, biggie_fname,
2434                                      &ctrl_chr, xattr_fname, acl_fname);
2435    }
2436
2437    noof_biggiefiles = atol(biggie_fname);
2438    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2439            noof_biggiefiles);
2440    log_msg(2, tmp);
2441    open_progress_form("Reassembling large files",
2442                       "I am now reassembling all the large files.",
2443                       "Please wait. This may take some time.",
2444                       "", total_slices);
2445
2446    for (res =
2447         read_header_block_from_stream(&biggie_size, biggie_fname,
2448                                       &ctrl_chr);
2449         ctrl_chr != BLK_STOP_BIGGIEFILES;
2450         res =
2451         read_header_block_from_stream(&biggie_size, biggie_fname,
2452                                       &ctrl_chr)) {
2453        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2454            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2455            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2456        }
2457        p = strrchr(biggie_fname, '/');
2458        if (!p) {
2459            p = biggie_fname;
2460        } else {
2461            p++;
2462        }
2463        sprintf(tmp, "Restoring big file %ld (%lld K)",
2464                current_bigfile_number + 1, biggie_size / 1024);
2465        update_progress_form(tmp);
2466        res = restore_a_biggiefile_from_stream(biggie_fname,
2467                                               current_bigfile_number,
2468                                               biggie_cksum,
2469                                               biggie_size,
2470                                               filelist, ctrl_chr,
2471                                               pathname_of_last_biggie_restored);
2472        log_msg(1, "I believe I have restored %s",
2473                pathname_of_last_biggie_restored);
2474        if (fbw && pathname_of_last_biggie_restored[0]) {
2475            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2476        }
2477        retval += res;
2478        current_bigfile_number++;
2479
2480    }
2481    if (current_bigfile_number != noof_biggiefiles
2482        && noof_biggiefiles != 0) {
2483        sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2484                current_bigfile_number, noof_biggiefiles);
2485    } else {
2486        sprintf(tmp,
2487                "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2488                noof_biggiefiles, current_bigfile_number);
2489    }
2490    log_msg(1, tmp);
2491
2492    if (fbw) {
2493        fclose(fbw);
2494        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2495            iamhere("Setting biggie-EXATs");
2496            if (g_getfattr) {
2497                if (length_of_file(xattr_fname) > 0) {
2498                    log_msg(1, "set_fattr_List(%s,%s)",
2499                        biggies_whose_EXATs_we_should_set, xattr_fname);
2500                    set_fattr_list(biggies_whose_EXATs_we_should_set,
2501                               xattr_fname);
2502                }
2503            }
2504            if (g_getfacl) {
2505                if (length_of_file(acl_fname) > 0) {
2506                    log_msg(1, "set_acl_list(%s,%s)",
2507                            biggies_whose_EXATs_we_should_set, acl_fname);
2508                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2509                }
2510            }
2511        } else {
2512            iamhere
2513                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2514        }
2515    }
2516    if (does_file_exist("/PAUSE")) {
2517        popup_and_OK
2518            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2519    }
2520
2521    close_progress_form();
2522    if (retval) {
2523        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2524    } else {
2525        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2526    }
2527    paranoid_free(biggies_whose_EXATs_we_should_set);
2528    paranoid_free(pathname_of_last_biggie_restored);
2529    paranoid_free(biggie_fname);
2530    paranoid_free(biggie_cksum);
2531    paranoid_free(xattr_fname);
2532    paranoid_free(acl_fname);
2533    paranoid_free(tmp);
2534    return (retval);
2535}
2536
2537/**************************************************************************
2538 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2539 **************************************************************************/
2540
2541
2542
2543
2544
2545
2546/**
2547 * Restore all afioballs from the currently opened tape stream.
2548 * @param bkpinfo The backup information structure. Fields used:
2549 * - @c bkpinfo->backup_media_type
2550 * - @c bkpinfo->restore_path
2551 * @param filelist The node structure containing the list of files to be
2552 * restored. If no file in an afioball is in this list, afio will still be
2553 * called for that fileset, but nothing will be written.
2554 * @return 0 for success, or the number of filesets that failed.
2555 */
2556int
2557restore_all_tarballs_from_stream(struct s_node *filelist)
2558{
2559    int retval = 0;
2560    int res;
2561    long current_afioball_number = 0;
2562    int ctrl_chr;
2563    long max_val /*, total_noof_files */ ;
2564
2565  /** malloc **/
2566    char *tmp;
2567    char *progress_str;
2568    char *tmp_fname;
2569    char *xattr_fname;
2570    char *acl_fname;
2571
2572    long long tmp_size;
2573
2574    malloc_string(tmp);
2575    malloc_string(progress_str);
2576    malloc_string(tmp_fname);
2577    assert(bkpinfo != NULL);
2578    malloc_string(xattr_fname);
2579    malloc_string(acl_fname);
2580    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2581    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2582    max_val = atol(tmp) + 1;
2583
2584    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2585
2586    run_program_and_log_output("pwd", 5);
2587
2588    sprintf(progress_str, "Restoring from media #%d",
2589            g_current_media_number);
2590    log_to_screen(progress_str);
2591    open_progress_form("Restoring from archives",
2592                       "Restoring data from the archives.",
2593                       "Please wait. This may take some time.",
2594                       progress_str, max_val);
2595
2596    log_msg(3, "hey");
2597
2598    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2599    if (res) {
2600        log_msg(2, "Warning - error reading afioball from tape");
2601    }
2602    retval += res;
2603    if (ctrl_chr != BLK_START_AFIOBALLS) {
2604        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2605    }
2606    log_msg(2, "ho");
2607    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2608    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2609        update_progress_form(progress_str);
2610        if (g_getfattr) {
2611            sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2612                current_afioball_number);
2613            unlink(xattr_fname);
2614        }
2615        if (g_getfacl) {
2616            sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2617                current_afioball_number);
2618            unlink(acl_fname);
2619        }
2620        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2621            iamhere("Reading EXAT files from tape");
2622            res =
2623                read_EXAT_files_from_tape(&tmp_size, tmp_fname,
2624                                          &ctrl_chr, xattr_fname,
2625                                          acl_fname);
2626        }
2627        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2628            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2629        }
2630        sprintf(tmp,
2631                "Restoring from fileset #%ld (name=%s, size=%ld K)",
2632                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2633        res =
2634            restore_a_tarball_from_stream(tmp_fname,
2635                                          current_afioball_number,
2636                                          filelist, tmp_size, xattr_fname,
2637                                          acl_fname);
2638        retval += res;
2639        if (res) {
2640            sprintf(tmp, "Fileset %ld - errors occurred",
2641                    current_afioball_number);
2642            log_to_screen(tmp);
2643        }
2644        res =
2645            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2646        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2647            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2648        }
2649
2650        current_afioball_number++;
2651        g_current_progress++;
2652        sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2653                current_afioball_number,
2654                media_descriptor_string(bkpinfo->backup_media_type),
2655                g_current_media_number);
2656        res =
2657            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2658        if (g_getfattr) {
2659            unlink(xattr_fname);
2660        }
2661        if (g_getfacl) {
2662            unlink(acl_fname);
2663        }
2664    }                           // next
2665    log_msg(1, "All done with afioballs");
2666    close_progress_form();
2667    if (retval) {
2668        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2669    } else {
2670        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2671    }
2672    paranoid_free(tmp);
2673    paranoid_free(progress_str);
2674    paranoid_free(tmp_fname);
2675    paranoid_free(xattr_fname);
2676    paranoid_free(acl_fname);
2677    return (retval);
2678}
2679
2680/**************************************************************************
2681 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2682 **************************************************************************/
2683
2684/* @} - end of LLrestoreGroup */
2685
2686
2687/**
2688 * Restore all files in @p filelist.
2689 * @param bkpinfo The backup information structure. Most fields are used.
2690 * @param filelist The node structure containing the list of files to be
2691 * restored.
2692 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2693 * @ingroup restoreGroup
2694 */
2695int restore_everything(struct s_node *filelist)
2696{
2697    int resA;
2698    int resB;
2699
2700  /** mallco ***/
2701    char *cwd;
2702    char *newpath;
2703    char *tmp;
2704    assert(bkpinfo != NULL);
2705
2706    malloc_string(cwd);
2707    malloc_string(newpath);
2708    malloc_string(tmp);
2709    log_msg(2, "restore_everything() --- starting");
2710    g_current_media_number = 1;
2711    getcwd(cwd, MAX_STR_LEN - 1);
2712    sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
2713    run_program_and_log_output(tmp, FALSE);
2714    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2715    chdir(bkpinfo->restore_path);
2716    getcwd(newpath, MAX_STR_LEN - 1);
2717    log_msg(1, "path is now %s", newpath);
2718    log_msg(1, "restoring everything");
2719    if (!find_home_of_exe("petris") && !g_text_mode) {
2720        newtDrawRootText(0, g_noof_rows - 2,
2721                         "Press ALT-<left cursor> twice to play Petris :-) ");
2722        newtRefresh();
2723    }
2724    mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
2725    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2726        mount_media();
2727        mvaddstr_and_log_it(g_currentY++, 0,
2728                            "Restoring OS and data from streaming media");
2729        if (bkpinfo->backup_media_type == cdstream) {
2730            openin_cdstream();
2731        } else {
2732            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
2733            openin_tape();
2734        }
2735        resA = restore_all_tarballs_from_stream(filelist);
2736        resB = restore_all_biggiefiles_from_stream(filelist);
2737        if (bkpinfo->backup_media_type == cdstream) {
2738            closein_cdstream();
2739        } else {
2740            closein_tape();
2741        }
2742    } else {
2743        mvaddstr_and_log_it(g_currentY++, 0,
2744                            "Restoring OS and data from CD/USB   ");
2745        mount_media();
2746        resA = restore_all_tarballs_from_CD(filelist);
2747        resB = restore_all_biggiefiles_from_CD(filelist);
2748    }
2749    chdir(cwd);
2750    if (resA + resB) {
2751        log_to_screen("Errors occurred while data was being restored.");
2752    }
2753    if (length_of_file("/etc/raidtab") > 0) {
2754        log_msg(2, "Copying local raidtab to restored filesystem");
2755        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2756                                   "/etc/raidtab", FALSE);
2757    }
2758    kill_petris();
2759    log_msg(2, "restore_everything() --- leaving");
2760    paranoid_free(cwd);
2761    paranoid_free(newpath);
2762    paranoid_free(tmp);
2763    return (resA + resB);
2764}
2765
2766/**************************************************************************
2767 *END_RESTORE_EVERYTHING                                                  *
2768 **************************************************************************/
2769
2770
2771extern void wait_until_software_raids_are_prepped(char *, int);
2772
2773
2774char which_restore_mode(void);
2775
2776
2777/**
2778 * Log a "don't panic" message to the logfile.
2779 */
2780void welcome_to_mondorestore()
2781{
2782    log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2783    log_msg(0,
2784            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2785    log_msg(0,
2786            "don't break out in a cold sweat just because you see a few  ");
2787    log_msg(0,
2788            "error messages in the log. Read them; analyze them; see if  ");
2789    log_msg(0,
2790            "they are significant; above all, verify your backups! Please");
2791    log_msg(0,
2792            "attach a compressed copy of this log to any e-mail you send ");
2793    log_msg(0,
2794            "to the Mondo mailing list when you are seeking technical    ");
2795    log_msg(0,
2796            "support. Without it, we can't help you.            - DevTeam");
2797    log_msg(0,
2798            "------------------------------------------------------------");
2799    log_msg(0,
2800            "BTW, despite (or perhaps because of) the wealth of messages,");
2801    log_msg(0,
2802            "some users are inclined to stop reading this log.  If Mondo ");
2803    log_msg(0,
2804            "stopped for some reason, chances are it's detailed here.    ");
2805    log_msg(0,
2806            "More than likely there's a message at the very end of this  ");
2807    log_msg(0,
2808            "log that will tell you what is wrong.  Please read it!      ");
2809    log_msg(0,
2810            "------------------------------------------------------------");
2811}
2812
2813
2814
2815/**
2816 * Restore the user's data.
2817 * What did you think it did, anyway? :-)
2818 */
2819int main(int argc, char *argv[])
2820{
2821    FILE *fin;
2822    FILE *fout;
2823    int retval = 0;
2824    int res;
2825//  int c;
2826    char *tmp;
2827
2828    struct mountlist_itself *mountlist;
2829    struct raidlist_itself *raidlist;
2830    struct s_node *filelist;
2831    char *a, *b;
2832    bool run_postnuke = FALSE;
2833
2834    if (getuid() != 0) {
2835        fprintf(stderr, "Please run as root.\r\n");
2836        exit(127);
2837    }
2838    if (!
2839        (bkpinfo = malloc(sizeof(struct s_bkpinfo)))) {
2840        fatal_error("Cannot malloc bkpinfo");
2841    }
2842    reset_bkpinfo();
2843
2844    g_loglevel = DEFAULT_MR_LOGLEVEL;
2845    malloc_string(tmp);
2846
2847/* Configure global variables */
2848#ifdef __FreeBSD__
2849    if (strstr
2850        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2851         "textonly"))
2852#else
2853    if (strstr
2854        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2855         "textonly"))
2856#endif
2857    {
2858        g_text_mode = TRUE;
2859        log_msg(1, "TEXTONLY MODE");
2860    } else {
2861        g_text_mode = FALSE;
2862    }                           // newt :-)
2863    if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
2864        fatal_error("Cannot malloc mountlist");
2865    }
2866    if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
2867        fatal_error("Cannot malloc raidlist");
2868    }
2869
2870    malloc_libmondo_global_strings();
2871
2872    strcpy(g_mondo_home,
2873           call_program_and_get_last_line_of_output("which mondorestore"));
2874    /*
2875    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2876    make_hole_for_dir(g_tmpfs_mountpt);
2877    */
2878    g_current_media_number = 1; // precaution
2879
2880    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2881
2882    malloc_string(tmp);
2883    malloc_string(a);
2884    malloc_string(b);
2885    setup_MR_global_filenames();    // malloc() and set globals, using bkpinfo->tmpdir etc.
2886    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2887    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2888    if (am_I_in_disaster_recovery_mode()) {
2889        run_program_and_log_output("mount / -o remount,rw", 2);
2890    }                           // for b0rken distros
2891    g_main_pid = getpid();
2892    srandom((int) (time(NULL)));
2893    set_signals(TRUE);
2894    g_kernel_version = get_kernel_version();
2895
2896    log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2897    if (strlen(g_mountlist_fname) < 3) {
2898        fatal_error
2899            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2900    }
2901    mkdir(MNT_CDROM, 0x770);
2902    make_hole_for_dir(MONDO_CACHE);
2903
2904    /* Backup original mountlist.txt */
2905    sprintf(tmp, "%s.orig", g_mountlist_fname);
2906    if (!does_file_exist(g_mountlist_fname)) {
2907        log_msg(2,
2908                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2909                __LINE__, g_mountlist_fname);
2910    } else if (!does_file_exist(tmp)) {
2911        sprintf(tmp, "cp -f %s %s.orig", g_mountlist_fname,
2912                g_mountlist_fname);
2913        run_program_and_log_output(tmp, FALSE);
2914    }
2915
2916    /* Init directories */
2917    make_hole_for_dir("/var/log");
2918    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
2919    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2920    /*
2921    run_program_and_log_output("ln -sf /var/log/mondo-archive.log /tmp/mondorestore.log",
2922         FALSE);
2923         */
2924
2925    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2926
2927    /* Init GUI */
2928    malloc_libmondo_global_strings();
2929    setup_newt_stuff();         /* call newtInit and setup screen log */
2930    welcome_to_mondorestore();
2931    if (bkpinfo->disaster_recovery) {
2932        log_msg(1, "I am in disaster recovery mode");
2933    } else {
2934        log_msg(1, "I am in normal, live mode");
2935    }
2936
2937    iamhere("what time is it");
2938
2939    /* Process command-line parameters */
2940    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
2941#ifdef __FreeBSD__
2942        system("mv -f /tmp/raidconf.txt /etc/raidtab");
2943        if (!does_file_exist("/etc/raidtab"))
2944            system("vinum printconfig > /etc/raidtab");
2945#endif
2946        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2947        if (!does_file_exist(g_mountlist_fname)) {
2948            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2949        }
2950        res = let_user_edit_the_mountlist(mountlist, raidlist);
2951#ifdef __FreeBSD__
2952        system("mv -f /etc/raidtab /tmp/raidconf.txt");
2953#endif
2954        paranoid_MR_finish(res);
2955    }
2956
2957    g_loglevel = DEFAULT_MR_LOGLEVEL;
2958    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
2959        fout = fopen("/tmp/out.txt", "w");
2960        fput_string_one_char_at_a_time(stderr, argv[2]);
2961        finish(0);
2962    }
2963
2964    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
2965        make_grub_install_scriptlet(argv[2]);
2966        finish(0);
2967    }
2968
2969    if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
2970        if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
2971            system("mount " MNT_CDROM);
2972        }
2973        bkpinfo->compression_level = 1;
2974        g_current_media_number = 2;
2975        strcpy(bkpinfo->restore_path, "/tmp/TESTING");
2976        bkpinfo->backup_media_type = dvd;
2977        open_progress_form("Reassembling /dev/hda1",
2978                           "Shark is a bit of a silly person.",
2979                           "Please wait. This may take some time.",
2980                           "", 1999);
2981        system("rm -Rf /tmp/*pih*");
2982
2983        restore_a_biggiefile_from_CD(42, NULL, tmp);
2984    }
2985
2986    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
2987        g_loglevel = 6;
2988        filelist = load_filelist(argv[2]);
2989        if (!filelist) {
2990            fatal_error("Failed to load filelist");
2991        }
2992        toggle_node_selection(filelist, FALSE);
2993        toggle_all_root_dirs_on(filelist);
2994        // BERLIOS: /usr/lib ???
2995        toggle_path_selection(filelist, "/usr/share", TRUE);
2996//      show_filelist(filelist);
2997        save_filelist(filelist, "/tmp/out.txt");
2998//      finish(0);
2999//      toggle_path_selection (filelist, "/root/stuff", TRUE);
3000        strcpy(a, argv[3]);
3001        strcpy(b, argv[4]);
3002
3003        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
3004        free_filelist(filelist);
3005        printf("res = %d", res);
3006        finish(0);
3007    }
3008
3009    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
3010        popup_changelist_from_file(argv[2]);
3011        paranoid_MR_finish(0);
3012    }
3013
3014    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
3015        log_msg(1, "SCORE");
3016        g_loglevel = 10;
3017        if (strstr(argv[2], "save")) {
3018            log_msg(1, "Saving from %s to %s", argv[3], argv[4]);
3019            fin = fopen(argv[3], "r");
3020            fout = fopen(argv[4], "w");
3021            copy_from_src_to_dest(fin, fout, 'w');
3022            fclose(fin);
3023            fin = fopen(argv[3], "r");
3024            copy_from_src_to_dest(fin, fout, 'w');
3025            fclose(fout);
3026            fclose(fin);
3027        } else if (strstr(argv[2], "restore")) {
3028            fout = fopen(argv[3], "w");
3029            fin = fopen(argv[4], "r");
3030            copy_from_src_to_dest(fout, fin, 'r');
3031            fclose(fin);
3032            fin = fopen(argv[4], "r");
3033            copy_from_src_to_dest(fout, fin, 'r');
3034            fclose(fout);
3035            fclose(fin);
3036        } else {
3037            fatal_error("Unknown additional param");
3038        }
3039        finish(0);
3040    }
3041
3042    if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
3043        wait_until_software_raids_are_prepped(argv[2], 100);
3044        finish(0);
3045    }
3046
3047    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
3048        finish(create_raidtab_from_mdstat(argv[2]));
3049    }
3050
3051    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
3052        retval = run_grub(FALSE, "/dev/hda");
3053        if (retval) {
3054            log_to_screen("Failed to write Master Boot Record");
3055        }
3056        paranoid_MR_finish(0);
3057    }
3058    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
3059        g_current_media_number = atoi(argv[2]);
3060        pause_and_ask_for_cdr(5, NULL);
3061        paranoid_MR_finish(0);
3062    }
3063    if ((argc == 2 && strcmp(argv[1], "--partition-only") == 0) && (bkpinfo->disaster_recovery)) {
3064        log_msg(0, "Partitioning only.");
3065        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3066        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3067        load_mountlist(mountlist, g_mountlist_fname);
3068        res = partition_everything(mountlist);
3069        finish(res);
3070    }
3071
3072    if ((argc == 2 && strcmp(argv[1], "--format-only") == 0) && (bkpinfo->disaster_recovery)) {
3073        log_msg(0, "Formatting only.");
3074        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3075        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3076        load_mountlist(mountlist, g_mountlist_fname);
3077        res = format_everything(mountlist, FALSE, raidlist);
3078        finish(res);
3079    }
3080
3081    if ((argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) && (bkpinfo->disaster_recovery)) {
3082        log_msg(0, "Stopping LVM and RAID");
3083        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3084        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3085        load_mountlist(mountlist, g_mountlist_fname);
3086        res = do_my_funky_lvm_stuff(TRUE, FALSE);
3087        res += stop_all_raid_devices(mountlist);
3088        finish(res);
3089    }
3090
3091    if ((argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) && (!bkpinfo->disaster_recovery)) {
3092        g_restoring_live_from_cd = TRUE;
3093    }
3094
3095    // Handle params here first
3096    handle_incoming_parameters(argc,argv);
3097
3098    if (!bkpinfo->disaster_recovery) {  // live!
3099        log_msg(1, "I am in normal, live mode.");
3100        log_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
3101        mount_boot_if_necessary();  /* for Gentoo users */
3102        log_msg(2, "Still here.");
3103        if (bkpinfo->backup_media_type == nfs) {
3104            g_restoring_live_from_nfs = TRUE;
3105        }
3106        log_msg(2, "Calling restore_to_live_filesystem()");
3107        retval = restore_to_live_filesystem();
3108
3109        log_msg(2, "Still here. Yay.");
3110        if ((strlen(bkpinfo->tmpdir) > 0) && (strstr(bkpinfo->tmpdir,"mondo.tmp.") != NULL)) {
3111            sprintf(tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3112            run_program_and_log_output(tmp, FALSE);
3113        }
3114        unmount_boot_if_necessary();    /* for Gentoo users */
3115        paranoid_MR_finish(retval);
3116    } else {
3117        /* Disaster recovery mode (must be) */
3118        log_msg(1, "I must be in disaster recovery mode.");
3119        log_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3120
3121        iamhere("About to call load_mountlist and load_raidtab");
3122        strcpy(bkpinfo->restore_path, MNT_RESTORING);
3123        read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
3124        retval = load_mountlist(mountlist, g_mountlist_fname);
3125        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3126        iamhere
3127            ("Returned from calling load_mountlist and load_raidtab successfully");
3128
3129        // BCO:To be reviewed
3130        if ((bkpinfo->restore_mode == compare) || (bkpinfo->restore_mode == nuke)) {
3131            if (bkpinfo->backup_media_type == nfs
3132                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3133                log_msg(1, "Mounting nfs dir");
3134                sprintf(bkpinfo->isodir, "/tmp/isodir");
3135                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3136                sprintf(tmp, "mount %s -t nfs -o nolock,ro /tmp/isodir",
3137                        bkpinfo->nfs_mount);
3138                run_program_and_log_output(tmp, 1);
3139            }
3140        }
3141
3142        if (retval) {
3143            log_to_screen
3144                ("Warning - load_raidtab_into_raidlist returned an error");
3145        }
3146
3147        log_msg(1, "Send in the clowns.");
3148
3149
3150        if (bkpinfo->restore_mode == nuke) {
3151            iamhere("nuking");
3152            retval += nuke_mode(mountlist, raidlist);
3153        } else if (bkpinfo->restore_mode == interactive) {
3154            iamhere("catchall");
3155            retval += catchall_mode(mountlist, raidlist);
3156        } else if (bkpinfo->restore_mode == compare) {
3157            iamhere("compare");
3158            retval += compare_mode(mountlist, raidlist);
3159        } else if (bkpinfo->restore_mode == isoonly) {
3160            iamhere("iso");
3161            retval = iso_mode(mountlist, raidlist, FALSE);
3162        } else if (bkpinfo->restore_mode == mbr) {
3163            iamhere("mbr");
3164            retval = mount_all_devices(mountlist, TRUE);
3165            if (!retval) {
3166                retval += run_boot_loader(FALSE);
3167                retval += unmount_all_devices(mountlist);
3168            }
3169            if (retval) {
3170                log_to_screen("Failed to write Master Boot Record");
3171            }
3172        } else if (bkpinfo->restore_mode == isonuke) {
3173            iamhere("isonuke");
3174            retval = iso_mode(mountlist, raidlist, TRUE);
3175        } else {
3176            iamhere("catchall (no mode specified in command-line call");
3177            retval += catchall_mode(mountlist, raidlist);
3178        }
3179    }
3180
3181    /* clean up at the end */
3182    if (retval) {
3183        if (does_file_exist(MONDO_CACHE"/changed.files")) {
3184            log_to_screen
3185                ("See "MONDO_CACHE"/changed.files for list of files that have changed.");
3186        }
3187        mvaddstr_and_log_it(g_currentY++,
3188                            0,
3189                            "Run complete. Errors were reported. Please review the logfile.");
3190    } else {
3191        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3192            mvaddstr_and_log_it(g_currentY++,
3193                                0,
3194                                "Run complete. Please remove media and reboot.");
3195        } else {
3196            run_program_and_log_output("sync", FALSE);
3197            if (is_this_device_mounted(MNT_CDROM)) {
3198                run_program_and_log_output("umount " MNT_CDROM, FALSE);
3199            }
3200
3201            if (!bkpinfo->please_dont_eject) {
3202                (void)eject_device("/dev/cdrom");
3203            }
3204            mvaddstr_and_log_it(g_currentY++,
3205                                0,
3206                                "Run complete. Please remove media and reboot.");
3207        }
3208    }
3209
3210// g_I_have_just_nuked is set true by nuke_mode() just before it returns
3211    if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3212      log_msg(1, "post-nuke found; find out whether we should run it...");
3213      if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3214        run_postnuke = TRUE;
3215        log_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3216      } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3217        run_postnuke = TRUE;
3218        log_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3219      } else {
3220        run_postnuke = FALSE;
3221        log_msg(1, "No, will not run post-nuke.");
3222      }
3223    } else {
3224      log_msg(1, "No post-nuke found.");
3225    }
3226    if (run_postnuke) {
3227      log_to_screen("Running post-nuke...");
3228      if (mount_all_devices(mountlist, TRUE)) {
3229        log_to_screen
3230          ("Unable to re-mount partitions for post-nuke stuff");
3231      } else {
3232        log_msg(1, "Re-mounted partitions for post-nuke stuff");
3233        sprintf(tmp, "post-nuke %s %d", bkpinfo->restore_path,
3234            retval);
3235        log_msg(2, "Calling '%s'", tmp);
3236        if ((res = run_program_and_log_output(tmp, 0))) {
3237          log_OS_error(tmp);
3238        }
3239        log_msg(1, "post-nuke returned w/ res=%d", res);
3240      }
3241      unmount_all_devices(mountlist);
3242      log_to_screen("I've finished post-nuking.");
3243    }
3244
3245/* 
3246  log_to_screen("If you are REALLY in a hurry, hit Ctrl-Alt-Del now.");
3247  log_to_screen("Otherwise, please wait until the RAID disks are done.");
3248  wait_until_software_raids_are_prepped("/proc/mdstat", 100);
3249  log_to_screen("Thank you.");
3250*/
3251    unlink("/tmp/mondo-run-prog.tmp");
3252    set_signals(FALSE);
3253    log_to_screen("Restore log (%s) copied to /var/log on your hard disk", MONDO_LOGFILE);
3254    sprintf(tmp,
3255            "Mondo-restore is exiting (retval=%d)                                      ",
3256            retval);
3257    log_to_screen(tmp);
3258    sprintf(tmp, "umount %s", bkpinfo->isodir);
3259    run_program_and_log_output(tmp, 5);
3260    paranoid_free(mountlist);
3261    paranoid_free(raidlist);
3262    if (am_I_in_disaster_recovery_mode()) {
3263        run_program_and_log_output("mount / -o remount,rw", 2);
3264    }                           // for b0rken distros
3265    if (strstr(bkpinfo->tmpdir,"mondo.tmp.") != NULL) {
3266        sprintf(tmp, "rm -Rf %s", bkpinfo->tmpdir);
3267        system(tmp);
3268    }
3269    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3270    free_libmondo_global_strings(); // it's fine to have this here :) really :)
3271    paranoid_free(a);
3272    paranoid_free(b);
3273    paranoid_free(tmp);
3274
3275    unlink("/tmp/filelist.full");
3276    unlink("/tmp/filelist.full.gz");
3277
3278    exit(retval);
3279}
3280
3281/**************************************************************************
3282 *END_MAIN                                                                *
3283 **************************************************************************/
3284
3285
3286
3287
3288
3289/**************************************************************************
3290 *END_MONDO-RESTORE.C                                                     *
3291 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.