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

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