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

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