Ignore:
Timestamp:
May 17, 2008, 1:29:54 AM (16 years ago)
Author:
Bruno Cornec
Message:

svn merge -r 1923:1938 $SVN_M/branches/2.2.6

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mondo/src/mondorestore/mondorestore.c

    r1924 r1939  
    32753275 *END_MONDO-RESTORE.C                                                     *
    32763276 **************************************************************************/
     3277=======
     3278/***************************************************************************
     3279$Id$
     3280restores mondoarchive data
     3281***************************************************************************/
     3282
     3283/**
     3284 * @file
     3285 * The main file for mondorestore.
     3286 */
     3287
     3288/**************************************************************************
     3289 * #include statements                                                    *
     3290 **************************************************************************/
     3291#include <pthread.h>
     3292#include "my-stuff.h"
     3293#include "../common/mondostructures.h"
     3294#include "../common/libmondo.h"
     3295#include "mr-externs.h"
     3296#include "mondo-restore.h"
     3297#include "mondorestore.h"
     3298#include "mondo-rstr-compare-EXT.h"
     3299#include "mondo-rstr-tools-EXT.h"
     3300
     3301extern void twenty_seconds_til_yikes(void);
     3302
     3303/* Reference to global bkpinfo */
     3304struct s_bkpinfo *bkpinfo;
     3305
     3306
     3307/* For use in other programs (ex. XMondo) */
     3308#ifdef MONDORESTORE_MODULE
     3309#define main __mondorestore_main
     3310#define g_ISO_restore_mode __mondorestore_g_ISO_restore_mode
     3311#endif
     3312
     3313//static char cvsid[] = "$Id$";
     3314
     3315/**************************************************************************
     3316 * Globals                                                                *
     3317 **************************************************************************/
     3318extern char *g_tmpfs_mountpt;   // declared in libmondo-tools.c
     3319extern bool g_text_mode;
     3320extern FILE *g_fprep;
     3321extern double g_kernel_version;
     3322extern int g_partition_table_locked_up;
     3323extern int g_noof_rows;
     3324
     3325extern int partition_everything(struct mountlist_itself *mountlist);
     3326
     3327
     3328/**
     3329 * @name Restore-Time Globals
     3330 * @ingroup globalGroup
     3331 * @{
     3332 */
     3333
     3334/**
     3335 * If TRUE, then we're restoring from ISOs or an NFS server.
     3336 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
     3337 */
     3338bool g_ISO_restore_mode = FALSE;    /* are we in Iso Mode? */
     3339
     3340/**
     3341 * If TRUE, then we have had a successful "nuke" restore.
     3342 */
     3343bool g_I_have_just_nuked = FALSE;
     3344
     3345/**
     3346 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
     3347 */
     3348char *g_isodir_device;
     3349
     3350/**
     3351 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
     3352 */
     3353char *g_isodir_format;
     3354
     3355/**
     3356 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
     3357 */
     3358char *g_biggielist_txt;
     3359
     3360/**
     3361 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
     3362 * the current archive set.
     3363 */
     3364char *g_filelist_full;
     3365
     3366/**
     3367 * The location of a file containing a list of the devices that were archived
     3368 * as images, not as individual files.
     3369 */
     3370char *g_filelist_imagedevs;
     3371
     3372/**
     3373 * The location of a file containing a list of imagedevs to actually restore.
     3374 * @see g_filelist_imagedevs
     3375 */
     3376char *g_imagedevs_restthese;
     3377
     3378/**
     3379 * The location of 'mondo-restore.cfg', containing the metadata
     3380 * information for this backup.
     3381 */
     3382char *g_mondo_cfg_file;
     3383
     3384/**
     3385 * The location of 'mountlist.txt', containing the information on the
     3386 * user's partitions and hard drives.
     3387 */
     3388char *g_mountlist_fname;
     3389
     3390/**
     3391 * Mondo's home directory during backup. Unused in mondorestore; included
     3392 * to avoid link errors.
     3393 */
     3394char *g_mondo_home;
     3395
     3396extern char *g_getfacl;
     3397extern char *g_getfattr;
     3398
     3399/* @} - end of "Restore-Time Globals" in globalGroup */
     3400
     3401
     3402
     3403extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
     3404                                 char direction);
     3405
     3406
     3407
     3408/**************************************************************************
     3409 * COMPAQ PROLIANT Stuff:  needs some special help                        *
     3410**************************************************************************/
     3411
     3412/**
     3413 * The message to display if we detect that the user is using a Compaq Proliant.
     3414 */
     3415#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."
     3416
     3417
     3418
     3419
     3420/**
     3421 * Allow the user to modify the mountlist before we partition & format their drives.
     3422 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
     3423 * @param mountlist The mountlist to let the user modify.
     3424 * @param raidlist The raidlist that goes with @p mountlist.
     3425 * @return 0 for success, nonzero for failure.
     3426 * @ingroup restoreGuiGroup
     3427 */
     3428int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
     3429                                struct raidlist_itself *raidlist)
     3430{
     3431    int retval = 0, res = 0;
     3432
     3433    log_msg(2, "let_user_edit_the_mountlist() --- starting");
     3434
     3435    assert(bkpinfo != NULL);
     3436    assert(mountlist != NULL);
     3437    assert(raidlist != NULL);
     3438    if (!bkpinfo->disaster_recovery) {
     3439        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     3440        log_msg(2, "I guess you're testing edit_mountlist()");
     3441    }
     3442    if (!does_file_exist(g_mountlist_fname)) {
     3443        log_to_screen(g_mountlist_fname);
     3444        log_to_screen("does not exist");
     3445        return (1);
     3446    }
     3447
     3448    retval = load_mountlist(mountlist, g_mountlist_fname);
     3449    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     3450    if (retval) {
     3451        log_to_screen
     3452            ("Warning - load_raidtab_into_raidlist returned an error");
     3453    }
     3454    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
     3455    if (res) {
     3456        return (1);
     3457    }
     3458
     3459    save_mountlist_to_disk(mountlist, g_mountlist_fname);
     3460    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
     3461
     3462    log_to_screen("I have finished editing the mountlist for you.");
     3463
     3464    return (retval);
     3465}
     3466
     3467
     3468
     3469
     3470
     3471/**
     3472 * Determine whether @p mountlist contains a Compaq diagnostic partition.
     3473 * @param mountlist The mountlist to examine.
     3474 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
     3475 * @ingroup restoreUtilityGroup
     3476 */
     3477bool
     3478partition_table_contains_Compaq_diagnostic_partition(struct
     3479                                                     mountlist_itself *
     3480                                                     mountlist)
     3481{
     3482    int i;
     3483
     3484    assert(mountlist != NULL);
     3485
     3486    for (i = 0; i < mountlist->entries; i++) {
     3487        if (strstr(mountlist->el[i].format, "ompaq")) {
     3488            log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
     3489                    i, mountlist->el[i].device, mountlist->el[i].format);
     3490
     3491            return (TRUE);
     3492        }
     3493    }
     3494    return (FALSE);
     3495}
     3496
     3497/**************************************************************************
     3498 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION                *
     3499 **************************************************************************/
     3500
     3501
     3502/**
     3503 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
     3504 * @note This function does not actually check for the presence of a Compaq partition.
     3505 * @ingroup restoreUtilityGroup
     3506 */
     3507void offer_to_abort_because_Compaq_Proliants_suck(void)
     3508{
     3509    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
     3510    if (ask_me_yes_or_no
     3511        ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
     3512    {
     3513        fatal_error
     3514            ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
     3515    }
     3516}
     3517
     3518/**************************************************************************
     3519 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK                        *
     3520 **************************************************************************/
     3521
     3522
     3523
     3524/**
     3525 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
     3526 * @param bkpinfo The backup information structure. Most fields are used.
     3527 * @param mountlist The mountlist containing information about the user's partitions.
     3528 * @param raidlist The raidlist to go with @p mountlist.
     3529 * @return The return code from the mode function called.
     3530 * @ingroup restoreGroup
     3531 */
     3532int
     3533catchall_mode(struct mountlist_itself *mountlist,
     3534              struct raidlist_itself *raidlist)
     3535{
     3536    char c, *tmp;
     3537    int retval = 0;
     3538
     3539    iamhere("inside catchall");
     3540    assert(bkpinfo != NULL);
     3541    assert(mountlist != NULL);
     3542    assert(raidlist != NULL);
     3543    malloc_string(tmp);
     3544    iamhere("pre wrm");
     3545    c = which_restore_mode();
     3546    iamhere("post wrm");
     3547    if (c == 'I' || c == 'N' || c == 'C') {
     3548        interactively_obtain_media_parameters_from_user(FALSE);
     3549    } else {
     3550        popup_and_OK("No restoring or comparing will take place today.");
     3551        if (is_this_device_mounted("/mnt/cdrom")) {
     3552            run_program_and_log_output("umount /mnt/cdrom", FALSE);
     3553        }
     3554        if (g_ISO_restore_mode) {
     3555            sprintf(tmp, "umount %s", bkpinfo->isodir);
     3556            run_program_and_log_output(tmp, FALSE);
     3557        }
     3558        paranoid_MR_finish(0);
     3559    }
     3560
     3561    iamhere("post int");
     3562
     3563    if (bkpinfo->backup_media_type == iso) {
     3564        if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
     3565            log_msg(2,
     3566                    "catchall_mode --- iso_fiddly_bits returned w/ error");
     3567            return (1);
     3568        } else {
     3569            log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
     3570        }
     3571    }
     3572
     3573    if (c == 'I') {
     3574        log_msg(2, "IM selected");
     3575        retval += interactive_mode(mountlist, raidlist);
     3576    } else if (c == 'N') {
     3577        log_msg(2, "NM selected");
     3578        retval += nuke_mode(mountlist, raidlist);
     3579    } else if (c == 'C') {
     3580        log_msg(2, "CM selected");
     3581        retval += compare_mode(mountlist, raidlist);
     3582    }
     3583    paranoid_free(tmp);
     3584    return (retval);
     3585}
     3586
     3587/**************************************************************************
     3588 *END_CATCHALL_MODE                                                      *
     3589 **************************************************************************/
     3590
     3591/**************************************************************************
     3592 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
     3593 **************************************************************************/
     3594
     3595
     3596/**
     3597 * Locate an executable in the directory structure rooted at @p restg.
     3598 * @param out_path Where to put the executable.
     3599 * @param fname The basename of the executable.
     3600 * @param restg The directory structure to look in.
     3601 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
     3602 * @ingroup restoreUtilityGroup
     3603 */
     3604void
     3605find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
     3606                                                    char *fname,
     3607                                                    char *restg)
     3608{
     3609    assert(out_path != NULL);
     3610    assert_string_is_neither_NULL_nor_zerolength(fname);
     3611
     3612    sprintf(out_path, "%s/sbin/%s", restg, fname);
     3613    if (does_file_exist(out_path)) {
     3614        sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
     3615        if (does_file_exist(out_path)) {
     3616            sprintf(out_path, "%s/bin/%s", restg, fname);
     3617            if (does_file_exist(out_path)) {
     3618                sprintf(out_path, "%s/usr/bin/%s", restg, fname);
     3619                if (does_file_exist(out_path)) {
     3620                    strcpy(out_path, fname);
     3621                }
     3622            }
     3623        }
     3624    }
     3625}
     3626
     3627/**************************************************************************
     3628 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
     3629 **************************************************************************/
     3630
     3631static void clean_blkid() {
     3632
     3633    char *tmp1 = NULL;
     3634
     3635    /* Clean up blkid cache file if they exist */
     3636    asprintf(&tmp1,"%s/etc/blkid.tab",bkpinfo->restore_path);
     3637    (void)unlink(tmp1);
     3638    paranoid_free(tmp1);
     3639    asprintf(&tmp1,"%s/etc/blkid.tab.old",bkpinfo->restore_path);
     3640    (void)unlink(tmp1);
     3641    paranoid_free(tmp1);
     3642}
     3643
     3644
     3645
     3646
     3647/**
     3648 * @addtogroup restoreGroup
     3649 * @{
     3650 */
     3651/**
     3652 * Restore the user's data, in a disaster recovery situation, prompting the
     3653 * user about whether or not to do every step.
     3654 * The user can edit the mountlist, choose files to restore, etc.
     3655 * @param bkpinfo The backup information structure. Most fields are used.
     3656 * @param mountlist The mountlist containing information about the user's partitions.
     3657 * @param raidlist The raidlist to go with @p mountlist.
     3658 * @return 0 for success, or the number of errors encountered.
     3659 */
     3660int
     3661interactive_mode(struct mountlist_itself *mountlist,
     3662                 struct raidlist_itself *raidlist)
     3663{
     3664    int retval = 0;
     3665    int res;
     3666    int ptn_errs = 0;
     3667    int fmt_errs = 0;
     3668
     3669    bool done;
     3670    bool restore_all;
     3671
     3672  /** needs malloc **********/
     3673    char *tmp;
     3674    char *fstab_fname;
     3675    char *old_restpath;
     3676
     3677    struct s_node *filelist;
     3678
     3679    /* try to partition and format */
     3680
     3681    log_msg(2, "interactive_mode --- starting (great, assertions OK)");
     3682
     3683    malloc_string(tmp);
     3684    malloc_string(fstab_fname);
     3685    malloc_string(old_restpath);
     3686    assert(bkpinfo != NULL);
     3687    assert(mountlist != NULL);
     3688    assert(raidlist != NULL);
     3689
     3690    log_msg(2, "interactive_mode --- assertions OK");
     3691
     3692    if (g_text_mode) {
     3693        if (!ask_me_yes_or_no
     3694            ("Interactive Mode + textonly = experimental! Proceed anyway?"))
     3695        {
     3696            fatal_error("Wise move.");
     3697        }
     3698    }
     3699
     3700    iamhere("About to load config file");
     3701    get_cfg_file_from_archive_or_bust();
     3702    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
     3703    iamhere("Done loading config file; resizing ML");
     3704    if (bkpinfo->backup_media_type == nfs) {
     3705        strcpy(tmp, bkpinfo->prefix);
     3706        if (popup_and_get_string
     3707            ("Prefix", "Prefix of your ISO images ?", tmp, MAX_STR_LEN / 4)) {
     3708            strcpy(bkpinfo->prefix, tmp);
     3709            log_msg(1, "Prefix set to %s",bkpinfo->prefix);
     3710        }
     3711    }
     3712   
     3713#ifdef __FreeBSD__
     3714    if (strstr
     3715        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
     3716         "noresize"))
     3717#else
     3718    if (strstr
     3719        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
     3720         "noresize"))
     3721#endif
     3722    {
     3723        log_msg(1, "Not resizing mountlist.");
     3724    } else {
     3725        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
     3726    }
     3727    for (done = FALSE; !done;) {
     3728        iamhere("About to edit mountlist");
     3729        if (g_text_mode) {
     3730            save_mountlist_to_disk(mountlist, g_mountlist_fname);
     3731            sprintf(tmp, "%s %s", find_my_editor(), g_mountlist_fname);
     3732            res = system(tmp);
     3733            load_mountlist(mountlist, g_mountlist_fname);
     3734        } else {
     3735            res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
     3736        }
     3737        iamhere("Finished editing mountlist");
     3738        if (res) {
     3739            paranoid_MR_finish(1);
     3740        }
     3741        log_msg(2, "Proceeding...");
     3742        save_mountlist_to_disk(mountlist, g_mountlist_fname);
     3743        save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
     3744        mvaddstr_and_log_it(1, 30, "Restoring Interactively");
     3745        if (bkpinfo->differential) {
     3746            log_to_screen("Because this is a differential backup, disk");
     3747            log_to_screen
     3748                (" partitioning and formatting will not take place.");
     3749            done = TRUE;
     3750        } else {
     3751            if (ask_me_yes_or_no
     3752                ("Do you want to erase and partition your hard drives?")) {
     3753                if (partition_table_contains_Compaq_diagnostic_partition
     3754                    (mountlist)) {
     3755                    offer_to_abort_because_Compaq_Proliants_suck();
     3756                    done = TRUE;
     3757                } else {
     3758                    twenty_seconds_til_yikes();
     3759                    g_fprep = fopen("/tmp/prep.sh", "w");
     3760                    ptn_errs = partition_everything(mountlist);
     3761                    if (ptn_errs) {
     3762                        log_to_screen
     3763                            ("Warning. Errors occurred during disk partitioning.");
     3764                    }
     3765
     3766                    fmt_errs = format_everything(mountlist, FALSE, raidlist);
     3767                    if (!fmt_errs) {
     3768                        log_to_screen
     3769                            ("Errors during disk partitioning were handled OK.");
     3770                        log_to_screen
     3771                            ("Partitions were formatted OK despite those errors.");
     3772                        ptn_errs = 0;
     3773                    }
     3774                    if (!ptn_errs && !fmt_errs) {
     3775                        done = TRUE;
     3776                    }
     3777                }
     3778                paranoid_fclose(g_fprep);
     3779            } else {
     3780                mvaddstr_and_log_it(g_currentY++, 0,
     3781                                    "User opted not to partition the devices");
     3782                if (ask_me_yes_or_no
     3783                    ("Do you want to format your hard drives?")) {
     3784                    fmt_errs = format_everything(mountlist, TRUE, raidlist);
     3785                    if (!fmt_errs) {
     3786                        done = TRUE;
     3787                    }
     3788                } else {
     3789                    ptn_errs = fmt_errs = 0;
     3790                    done = TRUE;
     3791                }
     3792            }
     3793            if (fmt_errs) {
     3794                mvaddstr_and_log_it(g_currentY++,
     3795                                    0,
     3796                                    "Errors occurred. Please repartition and format drives manually.");
     3797                done = FALSE;
     3798            }
     3799            if (ptn_errs & !fmt_errs) {
     3800                mvaddstr_and_log_it(g_currentY++,
     3801                                    0,
     3802                                    "Errors occurred during partitioning. Formatting, however, went OK.");
     3803                done = TRUE;
     3804            }
     3805            if (!done) {
     3806                if (!ask_me_yes_or_no("Re-edit the mountlist?")) {
     3807                    retval++;
     3808                    goto end_of_func;
     3809                }
     3810            }
     3811        }
     3812    }
     3813
     3814    /* mount */
     3815    if (mount_all_devices(mountlist, TRUE)) {
     3816        unmount_all_devices(mountlist);
     3817        retval++;
     3818        goto end_of_func;
     3819    }
     3820    /* restore */
     3821    if ((restore_all =
     3822         ask_me_yes_or_no("Do you want me to restore all of your data?")))
     3823    {
     3824        log_msg(1, "Restoring all data");
     3825        retval += restore_everything(NULL);
     3826    } else
     3827        if ((restore_all =
     3828             ask_me_yes_or_no
     3829             ("Do you want me to restore _some_ of your data?"))) {
     3830        strcpy(old_restpath, bkpinfo->restore_path);
     3831        for (done = FALSE; !done;) {
     3832            unlink("/tmp/filelist.full");
     3833            filelist = process_filelist_and_biggielist();
     3834            /* Now you have /tmp/tmpfs/filelist.restore-these and /tmp/tmpfs/biggielist.restore-these;
     3835               the former is a list of regular files; the latter, biggiefiles and imagedevs.
     3836             */
     3837            if (filelist) {
     3838              gotos_suck:
     3839                strcpy(tmp, old_restpath);
     3840// (NB: %s is where your filesystem is mounted now, by default)", MNT_RESTORING);
     3841                if (popup_and_get_string
     3842                    ("Restore path", "Restore files to where?", tmp,
     3843                     MAX_STR_LEN / 4)) {
     3844                    if (!strcmp(tmp, "/")) {
     3845                        if (!ask_me_yes_or_no("Are you sure?")) {
     3846                            goto gotos_suck;
     3847                        }
     3848                        tmp[0] = '\0';  // so we restore to [blank]/file/name :)
     3849                    }
     3850                    strcpy(bkpinfo->restore_path, tmp);
     3851                    log_msg(1, "Restoring subset");
     3852                    retval += restore_everything(filelist);
     3853                    free_filelist(filelist);
     3854                } else {
     3855                    strcpy(bkpinfo->restore_path, old_restpath);
     3856                    free_filelist(filelist);
     3857                }
     3858                if (!ask_me_yes_or_no
     3859                    ("Restore another subset of your backup?")) {
     3860                    done = TRUE;
     3861                }
     3862            } else {
     3863                done = TRUE;
     3864            }
     3865        }
     3866        strcpy(old_restpath, bkpinfo->restore_path);
     3867    } else {
     3868        mvaddstr_and_log_it(g_currentY++,
     3869                            0,
     3870                            "User opted not to restore any data.                                  ");
     3871    }
     3872    if (retval) {
     3873        mvaddstr_and_log_it(g_currentY++,
     3874                            0,
     3875                            "Errors occurred during the restore phase.            ");
     3876    }
     3877
     3878    if (ask_me_yes_or_no("Initialize the boot loader?")) {
     3879        run_boot_loader(TRUE);
     3880    } else {
     3881        mvaddstr_and_log_it(g_currentY++,
     3882                            0,
     3883                            "User opted not to initialize the boot loader.");
     3884    }
     3885
     3886    clean_blkid();
     3887    protect_against_braindead_sysadmins();
     3888    retval += unmount_all_devices(mountlist);
     3889    /*  if (restore_some || restore_all || */
     3890    if (ask_me_yes_or_no
     3891        ("Label/Identify your ext2 and ext3 partitions if necessary?")) {
     3892        mvaddstr_and_log_it(g_currentY, 0,
     3893                            "Using tune2fs to identify your ext2,3 partitions");
     3894        if (does_file_exist("/tmp/fstab.new")) {
     3895            strcpy(fstab_fname, "/tmp/fstab.new");
     3896        } else {
     3897            strcpy(fstab_fname, "/tmp/fstab");
     3898        }
     3899        sprintf(tmp,
     3900                "label-partitions-as-necessary %s < %s >> %s 2>> %s",
     3901                g_mountlist_fname, fstab_fname, MONDO_LOGFILE,
     3902                MONDO_LOGFILE);
     3903        res = system(tmp);
     3904        if (res) {
     3905            log_to_screen
     3906                ("label-partitions-as-necessary returned an error");
     3907            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     3908        } else {
     3909            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     3910        }
     3911        retval += res;
     3912    }
     3913
     3914    iamhere("About to leave interactive_mode()");
     3915    if (retval) {
     3916        mvaddstr_and_log_it(g_currentY++,
     3917                            0,
     3918                            "Warning - errors occurred during the restore phase.");
     3919    }
     3920  end_of_func:
     3921    paranoid_free(tmp);
     3922    paranoid_free(fstab_fname);
     3923    paranoid_free(old_restpath);
     3924    iamhere("Leaving interactive_mode()");
     3925    return (retval);
     3926}
     3927
     3928/**************************************************************************
     3929 *END_INTERACTIVE_MODE                                                    *
     3930 **************************************************************************/
     3931
     3932
     3933
     3934/**
     3935 * Run an arbitrary restore mode (prompt the user), but from ISO images
     3936 * instead of real media.
     3937 * @param mountlist The mountlist containing information about the user's partitions.
     3938 * @param raidlist The raidlist that goes with @p mountlist.
     3939 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
     3940 * @return 0 for success, or the number of errors encountered.
     3941 */
     3942int
     3943iso_mode(struct mountlist_itself *mountlist,
     3944         struct raidlist_itself *raidlist, bool nuke_me_please)
     3945{
     3946    char c;
     3947    int retval = 0;
     3948
     3949    assert(mountlist != NULL);
     3950    assert(raidlist != NULL);
     3951    if (iso_fiddly_bits(nuke_me_please)) {
     3952        log_msg(1, "iso_mode --- returning w/ error");
     3953        return (1);
     3954    } else {
     3955        c = which_restore_mode();
     3956        if (c == 'I' || c == 'N' || c == 'C') {
     3957            interactively_obtain_media_parameters_from_user(FALSE);
     3958        }
     3959        if (c == 'I') {
     3960            retval += interactive_mode(mountlist, raidlist);
     3961        } else if (c == 'N') {
     3962            retval += nuke_mode(mountlist, raidlist);
     3963        } else if (c == 'C') {
     3964            retval += compare_mode(mountlist, raidlist);
     3965        } else {
     3966            log_to_screen("OK, I shan't restore/compare any files.");
     3967        }
     3968    }
     3969    if (is_this_device_mounted(MNT_CDROM)) {
     3970        paranoid_system("umount " MNT_CDROM);
     3971    }
     3972//  if (! already_mounted)
     3973//    {
     3974    if (system("umount /tmp/isodir 2> /dev/null")) {
     3975        log_to_screen
     3976            ("WARNING - unable to unmount device where the ISO files are stored.");
     3977    }
     3978//    }
     3979    return (retval);
     3980}
     3981
     3982/**************************************************************************
     3983 *END_ISO_MODE                                                            *
     3984 **************************************************************************/
     3985
     3986
     3987/*            MONDO - saving your a$$ since Feb 18th, 2000            */
     3988
     3989
     3990
     3991
     3992/**
     3993 * Restore the user's data automatically (no prompts), after a twenty-second
     3994 * warning period.
     3995 * @param bkpinfo The backup information structure. Most fields are used.
     3996 * @param mountlist The mountlist containing information about the user's partitions.
     3997 * @param raidlist The raidlist that goes with @p mountlist.
     3998 * @return 0 for success, or the number of errors encountered.
     3999 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
     4000 */
     4001int
     4002nuke_mode(struct mountlist_itself *mountlist,
     4003          struct raidlist_itself *raidlist)
     4004{
     4005    int retval = 0;
     4006    int res = 0;
     4007    bool boot_loader_installed = FALSE;
     4008  /** malloc **/
     4009    char tmp[MAX_STR_LEN], tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
     4010        tmpC[MAX_STR_LEN];
     4011
     4012    assert(bkpinfo != NULL);
     4013    assert(mountlist != NULL);
     4014    assert(raidlist != NULL);
     4015
     4016    log_msg(2, "nuke_mode --- starting");
     4017
     4018    get_cfg_file_from_archive_or_bust();
     4019    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo updated the mountlist
     4020#ifdef __FreeBSD__
     4021    if (strstr
     4022        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
     4023         "noresize"))
     4024#else
     4025    if (strstr
     4026        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
     4027         "noresize"))
     4028#endif
     4029    {
     4030        log_msg(2, "Not resizing mountlist.");
     4031    } else {
     4032        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
     4033    }
     4034    if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
     4035        sprintf(tmp,
     4036                "Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?",
     4037                tmpA, tmpB, tmpC);
     4038        if (ask_me_yes_or_no(tmp)) {
     4039            retval = interactive_mode(mountlist, raidlist);
     4040            goto after_the_nuke;
     4041        } else {
     4042            fatal_error("Nuke Mode aborted. ");
     4043        }
     4044    }
     4045    save_mountlist_to_disk(mountlist, g_mountlist_fname);
     4046    mvaddstr_and_log_it(1, 30, "Restoring Automatically");
     4047    if (bkpinfo->differential) {
     4048        log_to_screen("Because this is a differential backup, disk");
     4049        log_to_screen("partitioning and formatting will not take place.");
     4050        res = 0;
     4051    } else {
     4052        if (partition_table_contains_Compaq_diagnostic_partition
     4053            (mountlist)) {
     4054            offer_to_abort_because_Compaq_Proliants_suck();
     4055        } else {
     4056            twenty_seconds_til_yikes();
     4057            g_fprep = fopen("/tmp/prep.sh", "w");
     4058#ifdef __FreeBSD__
     4059            if (strstr
     4060                (call_program_and_get_last_line_of_output
     4061                 ("cat /tmp/cmdline"), "nopart"))
     4062#else
     4063            if (strstr
     4064                (call_program_and_get_last_line_of_output
     4065                 ("cat /proc/cmdline"), "nopart"))
     4066#endif
     4067            {
     4068                log_msg(2,
     4069                        "Not partitioning drives due to 'nopart' option.");
     4070                res = 0;
     4071            } else {
     4072                res = partition_everything(mountlist);
     4073                if (res) {
     4074                    log_to_screen
     4075                        ("Warning. Errors occurred during partitioning.");
     4076                    res = 0;
     4077                }
     4078            }
     4079            retval += res;
     4080            if (!res) {
     4081                log_to_screen("Preparing to format your disk(s)");
     4082                sleep(1);
     4083                system("sync");
     4084                log_to_screen("Please wait. This may take a few minutes.");
     4085                res += format_everything(mountlist, FALSE, raidlist);
     4086            }
     4087            paranoid_fclose(g_fprep);
     4088        }
     4089    }
     4090    retval += res;
     4091    if (res) {
     4092        mvaddstr_and_log_it(g_currentY++,
     4093                            0,
     4094                            "Failed to partition and/or format your hard drives.");
     4095
     4096        if (ask_me_yes_or_no("Try in interactive mode instead?")) {
     4097            retval = interactive_mode(mountlist, raidlist);
     4098            goto after_the_nuke;
     4099        } else
     4100            if (!ask_me_yes_or_no
     4101                ("Would you like to try to proceed anyway?")) {
     4102            return (retval);
     4103        }
     4104    }
     4105    retval = mount_all_devices(mountlist, TRUE);
     4106    if (retval) {
     4107        unmount_all_devices(mountlist);
     4108        log_to_screen
     4109            ("Unable to mount all partitions. Sorry, I cannot proceed.");
     4110        return (retval);
     4111    }
     4112    iamhere("Restoring everything");
     4113    retval += restore_everything(NULL);
     4114    if (!run_boot_loader(FALSE)) {
     4115        log_msg(1,
     4116                "Great! Boot loader was installed. No need for msg at end.");
     4117        boot_loader_installed = TRUE;
     4118    }
     4119    clean_blkid();
     4120    protect_against_braindead_sysadmins();
     4121    retval += unmount_all_devices(mountlist);
     4122    mvaddstr_and_log_it(g_currentY,
     4123                        0,
     4124                        "Using tune2fs to identify your ext2,3 partitions");
     4125
     4126    sprintf(tmp, "label-partitions-as-necessary %s < /tmp/fstab",
     4127            g_mountlist_fname);
     4128    res = run_program_and_log_output(tmp, TRUE);
     4129    if (res) {
     4130        log_to_screen("label-partitions-as-necessary returned an error");
     4131        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     4132    } else {
     4133        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     4134    }
     4135    retval += res;
     4136
     4137  after_the_nuke:
     4138    if (retval) {
     4139        log_to_screen("Errors occurred during the nuke phase.");
     4140    } else if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "RESTORE")) {
     4141        log_to_screen
     4142            ("PC was restored successfully. Thank you for using Mondo Rescue.");
     4143        log_to_screen
     4144            ("Please visit our website at http://www.mondorescue.org for more information.");
     4145    } else {
     4146        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.");
     4147            popup_and_OK(tmp);
     4148        log_to_screen
     4149          ("Mondo has restored your system. Please wait for the command prompt.");
     4150        log_to_screen
     4151            ("Then remove the backup media and reboot.");
     4152        log_to_screen
     4153            ("Please visit our website at http://www.mondorescue.org for more information.");
     4154    }
     4155    g_I_have_just_nuked = TRUE;
     4156/*
     4157  if (!boot_loader_installed && !does_file_exist(DO_MBR_PLEASE))
     4158    {
     4159      log_to_screen("PLEASE RUN 'mondorestore --mbr' NOW TO INITIALIZE YOUR BOOT SECTOR");
     4160      write_one_liner_data_file(DO_MBR_PLEASE, "mondorestore --mbr");
     4161    }
     4162*/
     4163    return (retval);
     4164}
     4165
     4166/**************************************************************************
     4167 *END_NUKE_MODE                                                           *
     4168 **************************************************************************/
     4169
     4170
     4171
     4172/**
     4173 * Restore the user's data (or a subset of it) to the live filesystem.
     4174 * This should not be called if we're booted from CD!
     4175 * @param bkpinfo The backup information structure. Most fields are used.
     4176 * @return 0 for success, or the number of errors encountered.
     4177 */
     4178int restore_to_live_filesystem()
     4179{
     4180    int retval = 0;
     4181
     4182  /** malloc **/
     4183    char *old_restpath;
     4184
     4185    struct mountlist_itself *mountlist;
     4186//  static
     4187    struct raidlist_itself *raidlist;
     4188    struct s_node *filelist;
     4189
     4190    log_msg(1, "restore_to_live_filesystem() - starting");
     4191    assert(bkpinfo != NULL);
     4192    malloc_string(old_restpath);
     4193    mountlist = malloc(sizeof(struct mountlist_itself));
     4194    raidlist = malloc(sizeof(struct raidlist_itself));
     4195    if (!mountlist || !raidlist) {
     4196        fatal_error("Cannot malloc() mountlist and/or raidlist");
     4197    }
     4198
     4199    strcpy(bkpinfo->restore_path, "/");
     4200    if (!g_restoring_live_from_cd && !g_restoring_live_from_nfs) {
     4201        popup_and_OK
     4202            ("Please insert tape/CD/USB Key, then hit 'OK' to continue.");
     4203        sleep(1);
     4204    }
     4205    if (!g_restoring_live_from_nfs) {
     4206        interactively_obtain_media_parameters_from_user(FALSE);
     4207    }
     4208    log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
     4209    if (!bkpinfo->media_device[0]) {
     4210        log_msg(2, "Warning - failed to find media dev");
     4211    }
     4212
     4213
     4214    log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
     4215
     4216    open_evalcall_form("Thinking...");
     4217
     4218    get_cfg_file_from_archive_or_bust();
     4219    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
     4220    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
     4221
     4222    close_evalcall_form();
     4223    retval = load_mountlist(mountlist, g_mountlist_fname);
     4224    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     4225
     4226    if (!g_restoring_live_from_nfs && (filelist = process_filelist_and_biggielist())) {
     4227        save_filelist(filelist, "/tmp/selected-files.txt");
     4228        strcpy(old_restpath, bkpinfo->restore_path);
     4229        if (popup_and_get_string("Restore path",
     4230                                 "Restore files to where? )",
     4231                                 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
     4232            iamhere("Restoring everything");
     4233            retval += restore_everything(filelist);
     4234            free_filelist(filelist);
     4235            strcpy(bkpinfo->restore_path, old_restpath);
     4236        } else {
     4237            free_filelist(filelist);
     4238        }
     4239        strcpy(bkpinfo->restore_path, old_restpath);
     4240    } else {
     4241        retval += restore_everything(NULL);
     4242    }
     4243    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     4244        log_msg(2,
     4245                "Tape : I don't need to unmount or eject the CD-ROM.");
     4246    } else {
     4247        run_program_and_log_output("umount " MNT_CDROM, FALSE);
     4248        if (!bkpinfo->please_dont_eject) {
     4249            eject_device(bkpinfo->media_device);
     4250        }
     4251    }
     4252    run_program_and_log_output("umount " MNT_CDROM, FALSE);
     4253    if (!bkpinfo->please_dont_eject) {
     4254        eject_device(bkpinfo->media_device);
     4255    }
     4256    paranoid_free(old_restpath);
     4257    free(mountlist);
     4258    free(raidlist);
     4259    return (retval);
     4260}
     4261
     4262/**************************************************************************
     4263 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
     4264 **************************************************************************/
     4265
     4266/* @} - end of restoreGroup */
     4267
     4268
     4269#include <utime.h>
     4270/**
     4271 * @addtogroup LLrestoreGroup
     4272 * @{
     4273 */
     4274/**
     4275 * Restore biggiefile @p bigfileno from the currently mounted CD.
     4276 * @param bkpinfo The backup information structure. Fields used:
     4277 * - @c bkpinfo->backup_media_type
     4278 * - @c bkpinfo->restore_path
     4279 * @param bigfileno The biggiefile number (starting from 0) to restore.
     4280 * @param filelist The node structure containing the list of files to restore.
     4281 * If the biggiefile is not in this list, it will be skipped (return value will
     4282 * still indicate success).
     4283 * @return 0 for success (or skip), nonzero for failure.
     4284 */
     4285int
     4286restore_a_biggiefile_from_CD(long bigfileno,
     4287                             struct s_node *filelist,
     4288                             char *pathname_of_last_file_restored)
     4289{
     4290    FILE *fin;
     4291    FILE *fout;
     4292    FILE *fbzip2;
     4293
     4294  /** malloc ***/
     4295    char *checksum, *outfile_fname, *tmp, *bzip2_command,
     4296        *ntfsprog_command, *suffix, *sz_devfile;
     4297    char *bigblk;
     4298    char *p;
     4299    int retval = 0;
     4300    int finished = FALSE;
     4301    long sliceno;
     4302    long siz;
     4303    char ntfsprog_fifo[MAX_STR_LEN];
     4304    char *file_to_openout = NULL;
     4305    struct s_filename_and_lstat_info biggiestruct;
     4306    struct utimbuf the_utime_buf, *ubuf;
     4307    bool use_ntfsprog_hack = FALSE;
     4308    pid_t pid;
     4309    int res = 0;
     4310    int old_loglevel;
     4311    char sz_msg[MAX_STR_LEN];
     4312    struct s_node *node;
     4313
     4314    old_loglevel = g_loglevel;
     4315    ubuf = &the_utime_buf;
     4316    assert(bkpinfo != NULL);
     4317
     4318    malloc_string(checksum);
     4319    malloc_string(outfile_fname);
     4320    malloc_string(tmp);
     4321    malloc_string(bzip2_command);
     4322    malloc_string(ntfsprog_command);
     4323    malloc_string(suffix);
     4324    malloc_string(sz_devfile);
     4325
     4326    pathname_of_last_file_restored[0] = '\0';
     4327    if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
     4328        fatal_error("Cannot malloc bigblk");
     4329    }
     4330
     4331    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
     4332        log_to_screen("Cannot even open bigfile's info file");
     4333        return (1);
     4334    }
     4335
     4336    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
     4337    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
     4338        sizeof(biggiestruct)) {
     4339        log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
     4340                bigfileno + 1);
     4341    }
     4342    paranoid_fclose(fin);
     4343
     4344    strcpy(checksum, biggiestruct.checksum);
     4345
     4346    if (!checksum[0]) {
     4347        sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
     4348                bigfileno + 1);
     4349        log_msg(3, tmp);
     4350        p = checksum;
     4351    }
     4352
     4353    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
     4354    {
     4355        strcpy(outfile_fname, biggiestruct.filename);
     4356    } else {
     4357        sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
     4358                biggiestruct.filename);
     4359    }
     4360
     4361    /* skip file if we have a selective restore subset & it doesn't match */
     4362    if (filelist != NULL) {
     4363        node = find_string_at_node(filelist, biggiestruct.filename);
     4364        if (!node) {
     4365            log_msg(0, "Skipping %s (name isn't in filelist)",
     4366                    biggiestruct.filename);
     4367            pathname_of_last_file_restored[0] = '\0';
     4368            return (0);
     4369        } else if (!(node->selected)) {
     4370            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
     4371                    biggiestruct.filename);
     4372            pathname_of_last_file_restored[0] = '\0';
     4373            return (0);
     4374        }
     4375    }
     4376    /* otherwise, continue */
     4377
     4378    log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
     4379    if (biggiestruct.use_ntfsprog) {
     4380        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
     4381            log_msg(1,
     4382                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
     4383            log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
     4384            biggiestruct.use_ntfsprog = FALSE;
     4385        }
     4386    }
     4387
     4388    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
     4389//  if (!strncmp ( biggiestruct.filename, "/dev/", 5))
     4390    {
     4391        g_loglevel = 4;
     4392        use_ntfsprog_hack = TRUE;
     4393        log_msg(2,
     4394                "Calling ntfsclone in background because %s is an NTFS /dev entry",
     4395                outfile_fname);
     4396        sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
     4397                (int) (random() % 32768));
     4398        mkfifo(sz_devfile, 0x770);
     4399        strcpy(ntfsprog_fifo, sz_devfile);
     4400        file_to_openout = ntfsprog_fifo;
     4401        switch (pid = fork()) {
     4402        case -1:
     4403            fatal_error("Fork failure");
     4404        case 0:
     4405            log_msg(3,
     4406                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
     4407                    biggiestruct.filename, ntfsprog_fifo);
     4408            res =
     4409                feed_outfrom_ntfsprog(biggiestruct.filename,
     4410                                       ntfsprog_fifo);
     4411//          log_msg(3, "CHILD - fip - exiting");
     4412            exit(res);
     4413            break;
     4414        default:
     4415            log_msg(3,
     4416                    "feed_into_ntfsprog() called in background --- pid=%ld",
     4417                    (long int) (pid));
     4418        }
     4419    } else {
     4420        use_ntfsprog_hack = FALSE;
     4421        ntfsprog_fifo[0] = '\0';
     4422        file_to_openout = outfile_fname;
     4423        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
     4424        {
     4425            make_hole_for_file(outfile_fname);
     4426        }
     4427    }
     4428
     4429    sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
     4430            outfile_fname);
     4431    log_msg(2, tmp);
     4432
     4433    /*
     4434       last slice is zero-length and uncompressed; when we find it, we stop.
     4435       We DON'T wait until there are no more slices; if we did that,
     4436       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
     4437     */
     4438
     4439    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
     4440            MAX_STR_LEN - 1);
     4441    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
     4442
     4443    log_msg(3, "file_to_openout = %s", file_to_openout);
     4444    if (!(fout = fopen(file_to_openout, "w"))) {
     4445        log_to_screen("Cannot openout outfile_fname - hard disk full?");
     4446        return (1);
     4447    }
     4448    log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
     4449
     4450    for (sliceno = 1, finished = FALSE; !finished;) {
     4451        if (!does_file_exist
     4452            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
     4453            &&
     4454            !does_file_exist(slice_fname
     4455                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
     4456            &&
     4457            !does_file_exist(slice_fname
     4458                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
     4459            &&
     4460            !does_file_exist(slice_fname
     4461                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
     4462            log_msg(3,
     4463                    "Cannot find a data slice or terminator slice on CD %d",
     4464                    g_current_media_number);
     4465            g_current_media_number++;
     4466            sprintf(tmp,
     4467                    "Asking for %s #%d so that I may read slice #%ld\n",
     4468                    media_descriptor_string(bkpinfo->backup_media_type),
     4469                    g_current_media_number, sliceno);
     4470            log_msg(2, tmp);
     4471            sprintf(tmp, "Restoring from %s #%d",
     4472                    media_descriptor_string(bkpinfo->backup_media_type),
     4473                    g_current_media_number);
     4474            log_to_screen(tmp);
     4475            insist_on_this_cd_number(g_current_media_number);
     4476            log_to_screen("Continuing to restore.");
     4477        } else {
     4478            strcpy(tmp,
     4479                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
     4480            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
     4481                log_msg(2,
     4482                        "End of bigfile # %ld (slice %ld is the terminator)",
     4483                        bigfileno + 1, sliceno);
     4484                finished = TRUE;
     4485                continue;
     4486            } else {
     4487                if (does_file_exist
     4488                    (slice_fname
     4489                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
     4490                    strcpy(bzip2_command, "lzop");
     4491                    strcpy(suffix, "lzo");
     4492                } else
     4493                    if (does_file_exist
     4494                        (slice_fname
     4495                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
     4496                    strcpy(bzip2_command, "gzip");
     4497                    strcpy(suffix, "gz");
     4498                } else
     4499                    if (does_file_exist
     4500                        (slice_fname
     4501                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
     4502                    strcpy(bzip2_command, "bzip2");
     4503                    strcpy(suffix, "bz2");
     4504                } else
     4505                    if (does_file_exist
     4506                        (slice_fname
     4507                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
     4508                    strcpy(bzip2_command, "");
     4509                    strcpy(suffix, "");
     4510                } else {
     4511                    log_to_screen("OK, that's pretty fsck0red...");
     4512                    return (1);
     4513                }
     4514            }
     4515            if (bzip2_command[0] != '\0') {
     4516                sprintf(bzip2_command + strlen(bzip2_command),
     4517                        " -dc %s 2>> %s",
     4518                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
     4519                                    suffix), MONDO_LOGFILE);
     4520            } else {
     4521                sprintf(bzip2_command, "cat %s 2>> %s",
     4522                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
     4523                                    suffix), MONDO_LOGFILE);
     4524            }
     4525            sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ",
     4526                    media_descriptor_string(bkpinfo->backup_media_type),
     4527                    g_current_media_number, bigfileno + 1, sliceno);
     4528            log_msg(2, tmp);
     4529
     4530            if (!g_text_mode) {
     4531                newtDrawRootText(0, g_noof_rows - 2, tmp);
     4532                newtRefresh();
     4533                strip_spaces(tmp);
     4534                update_progress_form(tmp);
     4535            }
     4536            if (!(fbzip2 = popen(bzip2_command, "r"))) {
     4537                fatal_error("Can't run popen command");
     4538            }
     4539            while (!feof(fbzip2)) {
     4540                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
     4541                if (siz > 0) {
     4542                    sprintf(sz_msg, "Read %ld from fbzip2", siz);
     4543                    siz = fwrite(bigblk, 1, siz, fout);
     4544                    sprintf(sz_msg + strlen(sz_msg),
     4545                            "; written %ld to fout", siz);
     4546//        log_msg(2. sz_msg);
     4547                }
     4548            }
     4549            paranoid_pclose(fbzip2);
     4550
     4551
     4552            sliceno++;
     4553            g_current_progress++;
     4554        }
     4555    }
     4556/*
     4557  memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
     4558  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
     4559  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
     4560  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
     4561  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
     4562*/
     4563    paranoid_fclose(fout);
     4564    g_loglevel = old_loglevel;
     4565
     4566    if (use_ntfsprog_hack) {
     4567        log_msg(3, "Waiting for ntfsclone to finish");
     4568        sprintf(tmp,
     4569                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
     4570        while (system(tmp) == 0) {
     4571            sleep(1);
     4572        }
     4573        log_it("OK, ntfsclone has really finished");
     4574    }
     4575
     4576    if (strcmp(outfile_fname, "/dev/null")) {
     4577        chown(outfile_fname, biggiestruct.properties.st_uid,
     4578              biggiestruct.properties.st_gid);
     4579        chmod(outfile_fname, biggiestruct.properties.st_mode);
     4580        ubuf->actime = biggiestruct.properties.st_atime;
     4581        ubuf->modtime = biggiestruct.properties.st_mtime;
     4582        utime(outfile_fname, ubuf);
     4583    }
     4584    paranoid_free(bigblk);
     4585    paranoid_free(checksum);
     4586    paranoid_free(outfile_fname);
     4587    paranoid_free(tmp);
     4588    paranoid_free(bzip2_command);
     4589    paranoid_free(ntfsprog_command);
     4590    paranoid_free(suffix);
     4591    paranoid_free(sz_devfile);
     4592
     4593    return (retval);
     4594}
     4595
     4596/**************************************************************************
     4597 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
     4598 **************************************************************************/
     4599
     4600
     4601
     4602/**
     4603 * Restore a biggiefile from the currently opened stream.
     4604 * @param bkpinfo The backup information structure. Fields used:
     4605 * - @c bkpinfo->restore_path
     4606 * - @c bkpinfo->zip_exe
     4607 * @param orig_bf_fname The original filename of the biggiefile.
     4608 * @param biggiefile_number The number of the biggiefile (starting from 0).
     4609 * @param orig_checksum Unused.
     4610 * @param biggiefile_size Unused.
     4611 * @param filelist The node structure containing the list of files to be restored.
     4612 * If @p orig_bf_fname is not in the list, it will be ignored.
     4613 * @return 0 for success (or skip), nonzero for failure.
     4614 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
     4615 */
     4616int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
     4617                                     long long biggiefile_size, //UNUSED
     4618                                     struct s_node *filelist,
     4619                                     int use_ntfsprog,
     4620                                     char *pathname_of_last_file_restored)
     4621{
     4622    FILE *pout;
     4623    FILE *fin;
     4624
     4625  /** mallocs ********/
     4626    char *tmp;
     4627    char *command;
     4628    char *outfile_fname;
     4629    char *ntfsprog_command;
     4630    char *sz_devfile;
     4631    char *ntfsprog_fifo;
     4632    char *file_to_openout = NULL;
     4633
     4634    struct s_node *node;
     4635
     4636    int old_loglevel;
     4637    long current_slice_number = 0;
     4638    int retval = 0;
     4639    int res = 0;
     4640    int ctrl_chr = '\0';
     4641    long long slice_siz;
     4642    bool dummy_restore = FALSE;
     4643    bool use_ntfsprog_hack = FALSE;
     4644    pid_t pid;
     4645    struct s_filename_and_lstat_info biggiestruct;
     4646    struct utimbuf the_utime_buf, *ubuf;
     4647    ubuf = &the_utime_buf;
     4648
     4649    malloc_string(tmp);
     4650    malloc_string(ntfsprog_fifo);
     4651    malloc_string(outfile_fname);
     4652    malloc_string(command);
     4653    malloc_string(sz_devfile);
     4654    malloc_string(ntfsprog_command);
     4655    old_loglevel = g_loglevel;
     4656    assert(bkpinfo != NULL);
     4657    assert(orig_bf_fname != NULL);
     4658    assert(orig_checksum != NULL);
     4659
     4660    pathname_of_last_file_restored[0] = '\0';
     4661    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
     4662        use_ntfsprog = 1;
     4663        log_msg(1, "%s --- pih=YES", orig_bf_fname);
     4664    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
     4665        use_ntfsprog = 0;
     4666        log_msg(1, "%s --- pih=NO", orig_bf_fname);
     4667    } else {
     4668        use_ntfsprog = 0;
     4669        log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
     4670    }
     4671
     4672    strncpy(pathname_of_last_file_restored, orig_bf_fname,
     4673            MAX_STR_LEN - 1);
     4674    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
     4675
     4676    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
     4677
     4678    if (filelist != NULL) {
     4679        node = find_string_at_node(filelist, orig_bf_fname);
     4680        if (!node) {
     4681            dummy_restore = TRUE;
     4682            log_msg(1,
     4683                    "Skipping big file %ld (%s) - not in biggielist subset",
     4684                    biggiefile_number + 1, orig_bf_fname);
     4685            pathname_of_last_file_restored[0] = '\0';
     4686        } else if (!(node->selected)) {
     4687            dummy_restore = TRUE;
     4688            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
     4689                    orig_bf_fname);
     4690            pathname_of_last_file_restored[0] = '\0';
     4691        }
     4692    }
     4693
     4694    if (use_ntfsprog) {
     4695        if (strncmp(orig_bf_fname, "/dev/", 5)) {
     4696            log_msg(1,
     4697                    "I was in error when I set use_ntfsprog to TRUE.");
     4698            log_msg(1, "%s isn't even in /dev", orig_bf_fname);
     4699            use_ntfsprog = FALSE;
     4700        }
     4701    }
     4702
     4703    if (use_ntfsprog) {
     4704        g_loglevel = 4;
     4705        strcpy(outfile_fname, orig_bf_fname);
     4706        use_ntfsprog_hack = TRUE;
     4707        log_msg(2,
     4708                "Calling ntfsclone in background because %s is a /dev entry",
     4709                outfile_fname);
     4710        sprintf(sz_devfile, "%s/%d.%d.000",
     4711                bkpinfo->tmpdir,
     4712                (int) (random() % 32768),
     4713                (int) (random() % 32768));
     4714        mkfifo(sz_devfile, 0x770);
     4715        strcpy(ntfsprog_fifo, sz_devfile);
     4716        file_to_openout = ntfsprog_fifo;
     4717        switch (pid = fork()) {
     4718        case -1:
     4719            fatal_error("Fork failure");
     4720        case 0:
     4721            log_msg(3,
     4722                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
     4723                    outfile_fname, ntfsprog_fifo);
     4724            res =
     4725                feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
     4726//          log_msg(3, "CHILD - fip - exiting");
     4727            exit(res);
     4728            break;
     4729        default:
     4730            log_msg(3,
     4731                    "feed_into_ntfsprog() called in background --- pid=%ld",
     4732                    (long int) (pid));
     4733        }
     4734    } else {
     4735        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
     4736        {
     4737            strcpy(outfile_fname, orig_bf_fname);
     4738        } else                  // biggiefile
     4739        {
     4740            sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
     4741                    orig_bf_fname);
     4742        }
     4743        use_ntfsprog_hack = FALSE;
     4744        ntfsprog_fifo[0] = '\0';
     4745        file_to_openout = outfile_fname;
     4746        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
     4747        {
     4748            make_hole_for_file(outfile_fname);
     4749        }
     4750        sprintf(tmp, "Reassembling big file %ld (%s)",
     4751                biggiefile_number + 1, orig_bf_fname);
     4752        log_msg(2, tmp);
     4753    }
     4754
     4755    if (dummy_restore) {
     4756        sprintf(outfile_fname, "/dev/null");
     4757    }
     4758
     4759    if (!bkpinfo->zip_exe[0]) {
     4760        sprintf(command, "cat > \"%s\"", file_to_openout);
     4761    } else {
     4762        sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
     4763                file_to_openout, MONDO_LOGFILE);
     4764        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
     4765            /* Ignore SIGPIPE for gzip as it causes errors on big files
     4766             * Cf: http://trac.mondorescue.org/ticket/244
     4767             */
     4768            signal(SIGPIPE,SIG_IGN);
     4769        }
     4770    }
     4771    sprintf(tmp, "Pipe command = '%s'", command);
     4772    log_msg(3, tmp);
     4773
     4774    /* restore biggiefile, one slice at a time */
     4775    if (!(pout = popen(command, "w"))) {
     4776        fatal_error("Cannot pipe out");
     4777    }
     4778    for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
     4779         ctrl_chr != BLK_STOP_A_BIGGIE;
     4780         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
     4781        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     4782            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     4783        }
     4784        sprintf(tmp, "Working on file #%ld, slice #%ld    ",
     4785                biggiefile_number + 1, current_slice_number);
     4786        log_msg(2, tmp);
     4787        if (!g_text_mode) {
     4788            newtDrawRootText(0, g_noof_rows - 2, tmp);
     4789            newtRefresh();
     4790        }
     4791        strip_spaces(tmp);
     4792        update_progress_form(tmp);
     4793        if (current_slice_number == 0) {
     4794            res =
     4795                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
     4796                                              slice_siz);
     4797            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
     4798                log_OS_error("blah blah");
     4799            } else {
     4800                if (fread
     4801                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
     4802                     fin) < sizeof(biggiestruct)) {
     4803                    log_msg(2,
     4804                            "Warning - unable to get biggiestruct of bigfile #%d",
     4805                            biggiefile_number + 1);
     4806                }
     4807                paranoid_fclose(fin);
     4808            }
     4809        } else {
     4810            res =
     4811                read_file_from_stream_to_stream(pout, slice_siz);
     4812        }
     4813        retval += res;
     4814        res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
     4815        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
     4816            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
     4817        }
     4818        current_slice_number++;
     4819        g_current_progress++;
     4820    }
     4821    paranoid_pclose(pout);
     4822
     4823    if (bkpinfo->zip_exe[0]) {
     4824        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
     4825            /* Re-enable SIGPIPE for gzip
     4826             */
     4827            signal(SIGPIPE, terminate_daemon);
     4828        }
     4829    }
     4830
     4831    log_msg(1, "pathname_of_last_file_restored is now %s",
     4832            pathname_of_last_file_restored);
     4833
     4834    if (use_ntfsprog_hack) {
     4835        log_msg(3, "Waiting for ntfsclone to finish");
     4836        sprintf(tmp,
     4837                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
     4838        while (system(tmp) == 0) {
     4839            sleep(1);
     4840        }
     4841        log_msg(3, "OK, ntfsclone has really finished");
     4842    }
     4843
     4844    log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
     4845    log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
     4846    if (strcmp(outfile_fname, "/dev/null")) {
     4847        chmod(outfile_fname, biggiestruct.properties.st_mode);
     4848        chown(outfile_fname, biggiestruct.properties.st_uid,
     4849              biggiestruct.properties.st_gid);
     4850        ubuf->actime = biggiestruct.properties.st_atime;
     4851        ubuf->modtime = biggiestruct.properties.st_mtime;
     4852        utime(outfile_fname, ubuf);
     4853    }
     4854
     4855    paranoid_free(tmp);
     4856    paranoid_free(outfile_fname);
     4857    paranoid_free(command);
     4858    paranoid_free(ntfsprog_command);
     4859    paranoid_free(sz_devfile);
     4860    paranoid_free(ntfsprog_fifo);
     4861    g_loglevel = old_loglevel;
     4862    return (retval);
     4863}
     4864
     4865/**************************************************************************
     4866 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
     4867 **************************************************************************/
     4868
     4869
     4870
     4871/**
     4872 * Restore @p tarball_fname from CD.
     4873 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
     4874 * This will be used unmodified.
     4875 * @param current_tarball_number The number (starting from 0) of the fileset
     4876 * we're restoring now.
     4877 * @param filelist The node structure containing the list of files to be
     4878 * restored. If no file in the afioball is in this list, afio will still be
     4879 * called, but nothing will be written.
     4880 * @return 0 for success, nonzero for failure.
     4881 */
     4882int
     4883restore_a_tarball_from_CD(char *tarball_fname,
     4884                          long current_tarball_number,
     4885                          struct s_node *filelist)
     4886{
     4887    int retval = 0;
     4888    int res;
     4889    char *p;
     4890
     4891  /** malloc **/
     4892    char *command;
     4893    char *tmp;
     4894    char *filelist_name;
     4895    char *filelist_subset_fname;
     4896    char *executable;
     4897    char *temp_log;
     4898    char screen_message[100];
     4899    long matches = 0;
     4900    bool use_star;
     4901    char *xattr_fname;
     4902    char *acl_fname;
     4903//  char files_to_restore_this_time_fname[MAX_STR_LEN];
     4904
     4905    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
     4906    malloc_string(command);
     4907    malloc_string(tmp);
     4908    malloc_string(filelist_name);
     4909    malloc_string(filelist_subset_fname);
     4910    malloc_string(executable);
     4911    malloc_string(temp_log);
     4912    malloc_string(xattr_fname);
     4913    malloc_string(acl_fname);
     4914
     4915    log_msg(5, "Entering");
     4916    filelist_subset_fname[0] = '\0';
     4917    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
     4918//  sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
     4919    sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
     4920    run_program_and_log_output(command, 9);
     4921    sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
     4922            (int) (random() % 32768));
     4923
     4924    sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
     4925            current_tarball_number);
     4926    if (length_of_file(filelist_name) <= 2) {
     4927        log_msg(2, "There are _zero_ files in filelist '%s'",
     4928                filelist_name);
     4929        log_msg(2,
     4930                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
     4931        log_msg(2,
     4932                "but it's non-critical. It's cosmetic. Don't worry about it.");
     4933        retval = 0;
     4934        goto leave_sub;
     4935    }
     4936    if (count_lines_in_file(filelist_name) <= 0
     4937        || length_of_file(tarball_fname) <= 0) {
     4938        log_msg(3, "length_of_file(%s) = %llu", tarball_fname,
     4939                length_of_file(tarball_fname));
     4940        sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
     4941                current_tarball_number);
     4942        log_to_screen(tmp);
     4943        retval = 1;
     4944        goto leave_sub;
     4945    }
     4946
     4947    if (filelist) {
     4948        sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
     4949                current_tarball_number);
     4950        if ((matches =
     4951             save_filelist_entries_in_common(filelist_name, filelist,
     4952                                             filelist_subset_fname,
     4953                                             use_star))
     4954            <= 0) {
     4955            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
     4956            log_msg(1, tmp);
     4957        } else {
     4958            log_msg(3, "Saved fileset %ld's subset to %s",
     4959                    current_tarball_number, filelist_subset_fname);
     4960        }
     4961        sprintf(screen_message, "Tarball #%ld --- %ld matches",
     4962                current_tarball_number, matches);
     4963        log_to_screen(screen_message);
     4964    } else {
     4965        filelist_subset_fname[0] = '\0';
     4966    }
     4967
     4968    if (filelist == NULL || matches > 0) {
     4969        if (g_getfattr) {
     4970            sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
     4971                MNT_CDROM "/archives", current_tarball_number);
     4972        }
     4973        if (g_getfacl) {
     4974            sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
     4975                current_tarball_number);
     4976        }
     4977        if (strstr(tarball_fname, ".bz2")) {
     4978            strcpy(executable, "bzip2");
     4979        } else if (strstr(tarball_fname, ".gz")) {
     4980            strcpy(executable, "gzip");
     4981        } else if (strstr(tarball_fname, ".lzo")) {
     4982            strcpy(executable, "lzop");
     4983        } else {
     4984            executable[0] = '\0';
     4985        }
     4986        if (executable[0]) {
     4987            sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
     4988            if (run_program_and_log_output(tmp, FALSE)) {
     4989                log_to_screen
     4990                    ("(compare_a_tarball) Compression program not found - oh no!");
     4991                paranoid_MR_finish(1);
     4992            }
     4993            strcpy(tmp, executable);
     4994            sprintf(executable, "-P %s -Z", tmp);
     4995        }
     4996#ifdef __FreeBSD__
     4997#define BUFSIZE 512
     4998#else
     4999#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
     5000#endif
     5001
     5002//      if (strstr(tarball_fname, ".star."))
     5003        if (use_star) {
     5004            sprintf(command,
     5005                    "star -x -force-remove -U " STAR_ACL_SZ
     5006                    " errctl= file=%s", tarball_fname);
     5007            if (strstr(tarball_fname, ".bz2")) {
     5008                strcat(command, " -bz");
     5009            }
     5010        } else {
     5011            if (filelist_subset_fname[0] != '\0') {
     5012                sprintf(command,
     5013                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
     5014                        TAPE_BLOCK_SIZE,
     5015                        BUFSIZE, executable, filelist_subset_fname,
     5016//             files_to_restore_this_time_fname,
     5017                        tarball_fname);
     5018            } else {
     5019                sprintf(command,
     5020                        "afio -i -b %ld -c %ld -M 8m %s %s",
     5021                        TAPE_BLOCK_SIZE,
     5022                        BUFSIZE, executable, tarball_fname);
     5023            }
     5024        }
     5025#undef BUFSIZE
     5026        sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
     5027                temp_log);
     5028        log_msg(1, "command = '%s'", command);
     5029        unlink(temp_log);
     5030        res = system(command);
     5031        if (res) {
     5032            p = strstr(command, "-acl ");
     5033            if (p) {
     5034                p[0] = p[1] = p[2] = p[3] = ' ';
     5035                log_msg(1, "new command = '%s'", command);
     5036                res = system(command);
     5037            }
     5038        }
     5039        if (res && length_of_file(temp_log) < 5) {
     5040            res = 0;
     5041        }
     5042
     5043        if (g_getfattr) {
     5044            log_msg(1, "Setting fattr list %s", xattr_fname);
     5045            if (length_of_file(xattr_fname) > 0) {
     5046                res = set_fattr_list(filelist_subset_fname, xattr_fname);
     5047                if (res) {
     5048                    log_to_screen
     5049                        ("Errors occurred while setting extended attributes");
     5050                } else {
     5051                    log_msg(1, "I set xattr OK");
     5052                }
     5053                retval += res;
     5054            }
     5055        }
     5056        if (g_getfacl) {
     5057            log_msg(1, "Setting acl list %s", acl_fname);
     5058            if (length_of_file(acl_fname) > 0) {
     5059                res = set_acl_list(filelist_subset_fname, acl_fname);
     5060                if (res) {
     5061                    log_to_screen
     5062                        ("Errors occurred while setting access control lists");
     5063                } else {
     5064                    log_msg(1, "I set ACL OK");
     5065                }
     5066                retval += res;
     5067            }
     5068        }
     5069        if (retval) {
     5070            sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
     5071            system(command);
     5072            log_msg(2, "Errors occurred while processing fileset #%d",
     5073                    current_tarball_number);
     5074        } else {
     5075            log_msg(2, "Fileset #%d processed OK", current_tarball_number);
     5076        }
     5077    }
     5078    if (does_file_exist("/PAUSE")) {
     5079        popup_and_OK
     5080            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     5081    }
     5082    unlink(filelist_subset_fname);
     5083    unlink(xattr_fname);
     5084    unlink(acl_fname);
     5085    unlink(temp_log);
     5086
     5087  leave_sub:
     5088    paranoid_free(command);
     5089    paranoid_free(tmp);
     5090    paranoid_free(filelist_name);
     5091    paranoid_free(filelist_subset_fname);
     5092    paranoid_free(executable);
     5093    paranoid_free(temp_log);
     5094    paranoid_free(xattr_fname);
     5095    paranoid_free(acl_fname);
     5096    log_msg(5, "Leaving");
     5097    return (retval);
     5098}
     5099
     5100/**************************************************************************
     5101 *END_RESTORE_A_TARBALL_FROM_CD                                           *
     5102 **************************************************************************/
     5103
     5104
     5105/**
     5106 * Restore a tarball from the currently opened stream.
     5107 * @param bkpinfo The backup information structure. Fields used:
     5108 * - @c bkpinfo->backup_media_type
     5109 * - @c bkpinfo->media_device
     5110 * - @c bkpinfo->zip_exe
     5111 * @param tarball_fname The filename of the afioball to restore.
     5112 * @param current_tarball_number The number (starting from 0) of the fileset
     5113 * we're restoring now.
     5114 * @param filelist The node structure containing the list of files to be
     5115 * restored. If no file in the afioball is in this list, afio will still be
     5116 * called, but nothing will be written.
     5117 * @param size The size (in @b bytes) of the afioball.
     5118 * @return 0 for success, nonzero for failure.
     5119 */
     5120int
     5121restore_a_tarball_from_stream(char *tarball_fname,
     5122                              long current_tarball_number,
     5123                              struct s_node *filelist,
     5124                              long long size, char *xattr_fname,
     5125                              char *acl_fname)
     5126{
     5127    int retval = 0;
     5128    int res = 0;
     5129
     5130  /** malloc add ***/
     5131    char *tmp;
     5132    char *command;
     5133    char *afio_fname;
     5134    char *filelist_fname;
     5135    char *filelist_subset_fname;
     5136    char *executable;
     5137    long matches = 0;
     5138    bool restore_this_fileset = FALSE;
     5139    bool use_star;
     5140
     5141    assert(bkpinfo != NULL);
     5142    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
     5143    malloc_string(filelist_subset_fname);
     5144    malloc_string(filelist_fname);
     5145    malloc_string(afio_fname);
     5146    malloc_string(executable);
     5147    malloc_string(command);
     5148    malloc_string(tmp);
     5149    filelist_subset_fname[0] = '\0';
     5150    /* to do it with a file... */
     5151    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
     5152    sprintf(tmp,
     5153            "Restoring from fileset #%ld (%ld KB) on %s #%d",
     5154            current_tarball_number, (long) size >> 10,
     5155            media_descriptor_string(bkpinfo->backup_media_type),
     5156            g_current_media_number);
     5157    log_msg(2, tmp);
     5158    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
     5159
     5160  /****************************************************************************
     5161   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
     5162   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
     5163   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
     5164   ****************************************************************************/
     5165    filelist_fname[0] = filelist_subset_fname[0] = '\0';
     5166    sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
     5167            current_tarball_number);
     5168    sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
     5169            current_tarball_number);
     5170    sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
     5171            bkpinfo->tmpdir, current_tarball_number);
     5172//  sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
     5173    res = read_file_from_stream_to_file(afio_fname, size);
     5174    if (strstr(tarball_fname, ".star")) {
     5175        bkpinfo->use_star = TRUE;
     5176    }
     5177    if (res) {
     5178        log_msg(1, "Warning - error reading afioball from tape");
     5179    }
     5180    if (bkpinfo->compression_level == 0) {
     5181        executable[0] = '\0';
     5182    } else {
     5183        if (bkpinfo->use_star) {
     5184            strcpy(executable, " -bz");
     5185        } else {
     5186            sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
     5187        }
     5188    }
     5189
     5190    if (!filelist)              // if unconditional restore then restore entire fileset
     5191    {
     5192        restore_this_fileset = TRUE;
     5193    } else                      // If restoring selectively then get TOC from tarball
     5194    {
     5195        if (strstr(tarball_fname, ".star.")) {
     5196            use_star = TRUE;
     5197            sprintf(command, "star -t file=%s %s", afio_fname, executable);
     5198        } else {
     5199            use_star = FALSE;
     5200            sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
     5201                    executable, afio_fname);
     5202        }
     5203        sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
     5204                MONDO_LOGFILE);
     5205        log_msg(1, "command = %s", command);
     5206        if (system(command)) {
     5207            log_msg(4, "Warning - error occurred while retrieving TOC");
     5208        }
     5209        if ((matches =
     5210             save_filelist_entries_in_common(filelist_fname, filelist,
     5211                                             filelist_subset_fname,
     5212                                             use_star))
     5213            <= 0 || length_of_file(filelist_subset_fname) < 2) {
     5214            if (length_of_file(filelist_subset_fname) < 2) {
     5215                log_msg(1, "No matches found in fileset %ld",
     5216                        current_tarball_number);
     5217            }
     5218            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
     5219            log_msg(2, tmp);
     5220            restore_this_fileset = FALSE;
     5221        } else {
     5222            log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
     5223                    matches, current_tarball_number,
     5224                    filelist_subset_fname);
     5225            restore_this_fileset = TRUE;
     5226        }
     5227    }
     5228
     5229// Concoct the call to star/afio to restore files
     5230    if (strstr(tarball_fname, ".star."))    // star
     5231    {
     5232        sprintf(command, "star -x file=%s %s", afio_fname, executable);
     5233        if (filelist) {
     5234            sprintf(command + strlen(command), " list=%s",
     5235                    filelist_subset_fname);
     5236        }
     5237    } else                      // afio
     5238    {
     5239        sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
     5240                executable);
     5241        if (filelist) {
     5242            sprintf(command + strlen(command), " -w %s",
     5243                    filelist_subset_fname);
     5244        }
     5245        sprintf(command + strlen(command), " %s", afio_fname);
     5246    }
     5247    sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
     5248
     5249// Call if IF there are files to restore (selectively/unconditionally)
     5250    if (restore_this_fileset) {
     5251        log_msg(1, "Calling command='%s'", command);
     5252        paranoid_system(command);
     5253
     5254        if (g_getfattr) {
     5255            iamhere("Restoring xattr stuff");
     5256            res = set_fattr_list(filelist_subset_fname, xattr_fname);
     5257            if (res) {
     5258                log_msg(1, "Errors occurred while setting xattr");
     5259            } else {
     5260                log_msg(1, "I set xattr OK");
     5261            }
     5262            retval += res;
     5263        }
     5264
     5265        if (g_getfacl) {
     5266            iamhere("Restoring acl stuff");
     5267            res = set_acl_list(filelist_subset_fname, acl_fname);
     5268            if (res) {
     5269                log_msg(1, "Errors occurred while setting ACL");
     5270            } else {
     5271                log_msg(1, "I set ACL OK");
     5272            }
     5273            retval += res;
     5274        }
     5275
     5276    } else {
     5277        log_msg(1, "NOT CALLING '%s'", command);
     5278    }
     5279
     5280    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
     5281        log_to_screen("Paused after set %ld", current_tarball_number);
     5282        popup_and_OK("Pausing. Press ENTER to continue.");
     5283    }
     5284
     5285    unlink(filelist_subset_fname);
     5286    unlink(filelist_fname);
     5287    unlink(afio_fname);
     5288
     5289    paranoid_free(filelist_subset_fname);
     5290    paranoid_free(filelist_fname);
     5291    paranoid_free(afio_fname);
     5292    paranoid_free(command);
     5293    paranoid_free(tmp);
     5294    return (retval);
     5295}
     5296
     5297/**************************************************************************
     5298 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
     5299 **************************************************************************/
     5300
     5301
     5302
     5303
     5304/**
     5305 * Restore all biggiefiles from all media in this CD backup.
     5306 * The CD with the last afioball should be currently mounted.
     5307 * @param bkpinfo The backup information structure. @c backup_media_type is the
     5308 * only field used in this function.
     5309 * @param filelist The node structure containing the list of files to be
     5310 * restored. If a prospective biggiefile is not in this list, it will be ignored.
     5311 * @return 0 for success, nonzero for failure.
     5312 */
     5313int
     5314restore_all_biggiefiles_from_CD(struct s_node *filelist)
     5315{
     5316    int retval = 0;
     5317    int res = 0;
     5318    long noof_biggiefiles, bigfileno = 0, total_slices;
     5319  /** malloc **/
     5320    char *tmp;
     5321    bool just_changed_cds = FALSE;
     5322    char *xattr_fname;
     5323    char *acl_fname;
     5324    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
     5325    char *pathname_of_last_biggie_restored;
     5326    FILE *fbw = NULL;
     5327
     5328    malloc_string(xattr_fname);
     5329    malloc_string(acl_fname);
     5330    malloc_string(tmp);
     5331    malloc_string(biggies_whose_EXATs_we_should_set);
     5332    malloc_string(pathname_of_last_biggie_restored);
     5333    assert(bkpinfo != NULL);
     5334
     5335    sprintf(biggies_whose_EXATs_we_should_set,
     5336            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
     5337    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
     5338        log_msg(1, "Warning - cannot openout %s",
     5339                biggies_whose_EXATs_we_should_set);
     5340    }
     5341
     5342    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
     5343    total_slices = atol(tmp);
     5344    sprintf(tmp, "Reassembling large files      ");
     5345    mvaddstr_and_log_it(g_currentY, 0, tmp);
     5346    if (length_of_file(BIGGIELIST) < 6) {
     5347        log_msg(1, "OK, no biggielist; not restoring biggiefiles");
     5348        return (0);
     5349    }
     5350    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
     5351    if (noof_biggiefiles <= 0) {
     5352        log_msg(2,
     5353                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
     5354        return (0);
     5355    }
     5356    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
     5357            noof_biggiefiles);
     5358    log_msg(2, tmp);
     5359
     5360    open_progress_form("Reassembling large files",
     5361                       "I am now reassembling all the large files.",
     5362                       "Please wait. This may take some time.",
     5363                       "", total_slices);
     5364    for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
     5365        log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
     5366        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
     5367            log_msg(3,
     5368                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
     5369            log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
     5370                    bigfileno + 1,
     5371                    media_descriptor_string(bkpinfo->backup_media_type),
     5372                    g_current_media_number);
     5373            log_msg(3, "Slicename would have been %s",
     5374                    slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
     5375            // I'm not positive 'just_changed_cds' is even necessary...
     5376            if (just_changed_cds) {
     5377                just_changed_cds = FALSE;
     5378                log_msg(3,
     5379                        "I'll continue to scan this CD for bigfiles to be restored.");
     5380            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
     5381                insist_on_this_cd_number(++g_current_media_number);
     5382                sprintf(tmp, "Restoring from %s #%d",
     5383                        media_descriptor_string(bkpinfo->backup_media_type),
     5384                        g_current_media_number);
     5385                log_to_screen(tmp);
     5386                just_changed_cds = TRUE;
     5387            } else {
     5388                /* That big file doesn't exist, but the followings may */
     5389                /* So we need to continue looping */
     5390                log_msg(2, "There was no bigfile #%ld. That's OK.",
     5391                    bigfileno + 1);
     5392                log_msg(2, "I'm going to stop restoring bigfiles now.");
     5393                retval++;
     5394                bigfileno++;
     5395            }
     5396        } else {
     5397            just_changed_cds = FALSE;
     5398            sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
     5399            update_progress_form(tmp);
     5400            res =
     5401                restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
     5402            iamhere(pathname_of_last_biggie_restored);
     5403            if (fbw && pathname_of_last_biggie_restored[0]) {
     5404                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
     5405            }
     5406            retval += res;
     5407            bigfileno++;
     5408
     5409        }
     5410    }
     5411
     5412    if (fbw) {
     5413        fclose(fbw);
     5414        if (g_getfattr) {
     5415            sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
     5416            if (length_of_file(xattr_fname) > 0) {
     5417                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
     5418            }
     5419        }
     5420        if (g_getfacl) {
     5421            sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
     5422            if (length_of_file(acl_fname) > 0) {
     5423                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
     5424            }
     5425        }
     5426    }
     5427    if (does_file_exist("/PAUSE")) {
     5428        popup_and_OK
     5429            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     5430    }
     5431    close_progress_form();
     5432    if (retval) {
     5433        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     5434    } else {
     5435        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     5436    }
     5437    paranoid_free(xattr_fname);
     5438    paranoid_free(acl_fname);
     5439    paranoid_free(tmp);
     5440    paranoid_free(biggies_whose_EXATs_we_should_set);
     5441    paranoid_free(pathname_of_last_biggie_restored);
     5442    return (retval);
     5443}
     5444
     5445/**************************************************************************
     5446 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
     5447 **************************************************************************/
     5448
     5449
     5450
     5451/**
     5452 * Restore all afioballs from all CDs in the backup.
     5453 * The first CD should be inserted (if not, it will be asked for).
     5454 * @param bkpinfo The backup information structure. @c backup_media_type is the
     5455 * only field used in @e this function.
     5456 * @param filelist The node structure containing the list of files to be
     5457 * restored. If no file in some particular afioball is in this list, afio will
     5458 * still be called for that fileset, but nothing will be written.
     5459 * @return 0 for success, or the number of filesets that failed.
     5460 */
     5461int
     5462restore_all_tarballs_from_CD(struct s_node *filelist)
     5463{
     5464    int retval = 0;
     5465    int res;
     5466    int attempts;
     5467    long current_tarball_number = 0;
     5468    long max_val;
     5469  /**malloc ***/
     5470    char *tmp;
     5471    char *tarball_fname;
     5472    char *progress_str;
     5473    char *comment;
     5474
     5475    malloc_string(tmp);
     5476    malloc_string(tarball_fname);
     5477    malloc_string(progress_str);
     5478    malloc_string(comment);
     5479
     5480    assert(bkpinfo != NULL);
     5481
     5482    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
     5483    log_msg(2,
     5484            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
     5485    if (g_current_media_number != 1) {
     5486        log_msg(3, "OK, that's jacked up.");
     5487        g_current_media_number = 1;
     5488    }
     5489    insist_on_this_cd_number(g_current_media_number);
     5490    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
     5491    max_val = atol(tmp) + 1;
     5492    sprintf(progress_str, "Restoring from %s #%d",
     5493            media_descriptor_string(bkpinfo->backup_media_type),
     5494            g_current_media_number);
     5495    log_to_screen(progress_str);
     5496    open_progress_form("Restoring from archives",
     5497                       "Restoring data from the archives.",
     5498                       "Please wait. This may take some time.",
     5499                       progress_str, max_val);
     5500    for (;;) {
     5501        insist_on_this_cd_number(g_current_media_number);
     5502        update_progress_form(progress_str);
     5503        sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
     5504                current_tarball_number);
     5505        if (!does_file_exist(tarball_fname)) {
     5506            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
     5507                current_tarball_number);
     5508        }
     5509        if (!does_file_exist(tarball_fname)) {
     5510            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
     5511                    current_tarball_number);
     5512        }
     5513        if (!does_file_exist(tarball_fname)) {
     5514            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
     5515                    current_tarball_number);
     5516        }
     5517        if (!does_file_exist(tarball_fname)) {
     5518            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
     5519                    current_tarball_number);
     5520        }
     5521        if (!does_file_exist(tarball_fname)) {
     5522            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
     5523                    current_tarball_number);
     5524        }
     5525        if (!does_file_exist(tarball_fname)) {
     5526            if (current_tarball_number == 0) {
     5527                log_to_screen
     5528                    ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
     5529                return (0);
     5530            }
     5531            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
     5532                || system("find " MNT_CDROM
     5533                          "/archives/slice* > /dev/null 2> /dev/null") ==
     5534                0) {
     5535                break;
     5536            }
     5537            g_current_media_number++;
     5538            sprintf(progress_str, "Restoring from %s #%d",
     5539                    media_descriptor_string(bkpinfo->backup_media_type),
     5540                    g_current_media_number);
     5541            log_to_screen(progress_str);
     5542        } else {
     5543            sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
     5544                    current_tarball_number,
     5545                    media_descriptor_string(bkpinfo->backup_media_type),
     5546                    g_current_media_number);
     5547//    log_msg(3, "progress_str = %s", progress_str);
     5548            for (res = 999, attempts = 0; attempts < 3 && res != 0;
     5549                 attempts++) {
     5550                res =
     5551                    restore_a_tarball_from_CD(tarball_fname,
     5552                                              current_tarball_number,
     5553                                              filelist);
     5554            }
     5555            sprintf(tmp, "%s #%d, fileset #%ld - restore ",
     5556                    media_descriptor_string(bkpinfo->backup_media_type),
     5557                    g_current_media_number, current_tarball_number);
     5558            if (res) {
     5559                strcat(tmp, "reported errors");
     5560            } else if (attempts > 1) {
     5561                strcat(tmp, "succeeded");
     5562            } else {
     5563                strcat(tmp, "succeeded");
     5564            }
     5565            if (attempts > 1) {
     5566                sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
     5567                        attempts);
     5568            }
     5569            strcpy(comment, tmp);
     5570            if (attempts > 1) {
     5571                log_to_screen(comment);
     5572            }
     5573
     5574            retval += res;
     5575            current_tarball_number++;
     5576            g_current_progress++;
     5577        }
     5578    }
     5579    close_progress_form();
     5580    if (retval) {
     5581        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     5582    } else {
     5583        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     5584    }
     5585    paranoid_free(tmp);
     5586    paranoid_free(tarball_fname);
     5587    paranoid_free(progress_str);
     5588    paranoid_free(comment);
     5589
     5590    return (retval);
     5591}
     5592
     5593/**************************************************************************
     5594 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
     5595 **************************************************************************/
     5596
     5597
     5598
     5599/**
     5600 * Restore all biggiefiles from the currently opened stream.
     5601 * @param bkpinfo The backup information structure. Passed to other functions.
     5602 * @param filelist The node structure containing the list of files to be
     5603 * restored. If a prospective biggiefile is not in the list, it will be ignored.
     5604 * @return 0 for success, or the number of biggiefiles that failed.
     5605 */
     5606int
     5607restore_all_biggiefiles_from_stream(struct s_node *filelist)
     5608{
     5609    long noof_biggiefiles;
     5610    long current_bigfile_number = 0;
     5611    long total_slices;
     5612
     5613    int retval = 0;
     5614    int res = 0;
     5615    int ctrl_chr;
     5616
     5617  /** malloc add ****/
     5618    char *tmp;
     5619    char *biggie_fname;
     5620    char *biggie_cksum;
     5621    char *xattr_fname;
     5622    char *acl_fname;
     5623    char *p;
     5624    char *pathname_of_last_biggie_restored;
     5625    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
     5626    long long biggie_size;
     5627    FILE *fbw = NULL;
     5628
     5629    malloc_string(tmp);
     5630    malloc_string(biggie_fname);
     5631    malloc_string(biggie_cksum);
     5632    malloc_string(xattr_fname);
     5633    malloc_string(acl_fname);
     5634    malloc_string(biggies_whose_EXATs_we_should_set);
     5635    malloc_string(pathname_of_last_biggie_restored);
     5636    assert(bkpinfo != NULL);
     5637
     5638    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
     5639
     5640    total_slices = atol(tmp);
     5641    sprintf(tmp, "Reassembling large files      ");
     5642    if (g_getfattr) {
     5643        sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     5644    }
     5645    if (g_getfacl) {
     5646        sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     5647    }
     5648    mvaddstr_and_log_it(g_currentY, 0, tmp);
     5649    sprintf(biggies_whose_EXATs_we_should_set,
     5650            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
     5651    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
     5652        log_msg(1, "Warning - cannot openout %s",
     5653                biggies_whose_EXATs_we_should_set);
     5654    }
     5655// get xattr and acl files if they're there
     5656    res =
     5657        read_header_block_from_stream(&biggie_size, biggie_fname,
     5658                                      &ctrl_chr);
     5659    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
     5660        res =
     5661            read_EXAT_files_from_tape(&biggie_size, biggie_fname,
     5662                                      &ctrl_chr, xattr_fname, acl_fname);
     5663    }
     5664
     5665    noof_biggiefiles = atol(biggie_fname);
     5666    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
     5667            noof_biggiefiles);
     5668    log_msg(2, tmp);
     5669    open_progress_form("Reassembling large files",
     5670                       "I am now reassembling all the large files.",
     5671                       "Please wait. This may take some time.",
     5672                       "", total_slices);
     5673
     5674    for (res =
     5675         read_header_block_from_stream(&biggie_size, biggie_fname,
     5676                                       &ctrl_chr);
     5677         ctrl_chr != BLK_STOP_BIGGIEFILES;
     5678         res =
     5679         read_header_block_from_stream(&biggie_size, biggie_fname,
     5680                                       &ctrl_chr)) {
     5681        if (ctrl_chr != BLK_START_A_NORMBIGGIE
     5682            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
     5683            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
     5684        }
     5685        p = strrchr(biggie_fname, '/');
     5686        if (!p) {
     5687            p = biggie_fname;
     5688        } else {
     5689            p++;
     5690        }
     5691        sprintf(tmp, "Restoring big file %ld (%lld K)",
     5692                current_bigfile_number + 1, biggie_size / 1024);
     5693        update_progress_form(tmp);
     5694        res = restore_a_biggiefile_from_stream(biggie_fname,
     5695                                               current_bigfile_number,
     5696                                               biggie_cksum,
     5697                                               biggie_size,
     5698                                               filelist, ctrl_chr,
     5699                                               pathname_of_last_biggie_restored);
     5700        log_msg(1, "I believe I have restored %s",
     5701                pathname_of_last_biggie_restored);
     5702        if (fbw && pathname_of_last_biggie_restored[0]) {
     5703            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
     5704        }
     5705        retval += res;
     5706        current_bigfile_number++;
     5707
     5708    }
     5709    if (current_bigfile_number != noof_biggiefiles
     5710        && noof_biggiefiles != 0) {
     5711        sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
     5712                current_bigfile_number, noof_biggiefiles);
     5713    } else {
     5714        sprintf(tmp,
     5715                "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
     5716                noof_biggiefiles, current_bigfile_number);
     5717    }
     5718    log_msg(1, tmp);
     5719
     5720    if (fbw) {
     5721        fclose(fbw);
     5722        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
     5723            iamhere("Setting biggie-EXATs");
     5724            if (g_getfattr) {
     5725                if (length_of_file(xattr_fname) > 0) {
     5726                    log_msg(1, "set_fattr_List(%s,%s)",
     5727                        biggies_whose_EXATs_we_should_set, xattr_fname);
     5728                    set_fattr_list(biggies_whose_EXATs_we_should_set,
     5729                               xattr_fname);
     5730                }
     5731            }
     5732            if (g_getfacl) {
     5733                if (length_of_file(acl_fname) > 0) {
     5734                    log_msg(1, "set_acl_list(%s,%s)",
     5735                            biggies_whose_EXATs_we_should_set, acl_fname);
     5736                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
     5737                }
     5738            }
     5739        } else {
     5740            iamhere
     5741                ("No biggiefiles selected. So, no biggie-EXATs to set.");
     5742        }
     5743    }
     5744    if (does_file_exist("/PAUSE")) {
     5745        popup_and_OK
     5746            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     5747    }
     5748
     5749    close_progress_form();
     5750    if (retval) {
     5751        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     5752    } else {
     5753        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     5754    }
     5755    paranoid_free(biggies_whose_EXATs_we_should_set);
     5756    paranoid_free(pathname_of_last_biggie_restored);
     5757    paranoid_free(biggie_fname);
     5758    paranoid_free(biggie_cksum);
     5759    paranoid_free(xattr_fname);
     5760    paranoid_free(acl_fname);
     5761    paranoid_free(tmp);
     5762    return (retval);
     5763}
     5764
     5765/**************************************************************************
     5766 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
     5767 **************************************************************************/
     5768
     5769
     5770
     5771
     5772
     5773
     5774/**
     5775 * Restore all afioballs from the currently opened tape stream.
     5776 * @param bkpinfo The backup information structure. Fields used:
     5777 * - @c bkpinfo->backup_media_type
     5778 * - @c bkpinfo->restore_path
     5779 * @param filelist The node structure containing the list of files to be
     5780 * restored. If no file in an afioball is in this list, afio will still be
     5781 * called for that fileset, but nothing will be written.
     5782 * @return 0 for success, or the number of filesets that failed.
     5783 */
     5784int
     5785restore_all_tarballs_from_stream(struct s_node *filelist)
     5786{
     5787    int retval = 0;
     5788    int res;
     5789    long current_afioball_number = 0;
     5790    int ctrl_chr;
     5791    long max_val /*, total_noof_files */ ;
     5792
     5793  /** malloc **/
     5794    char *tmp;
     5795    char *progress_str;
     5796    char *tmp_fname;
     5797    char *xattr_fname;
     5798    char *acl_fname;
     5799
     5800    long long tmp_size;
     5801
     5802    malloc_string(tmp);
     5803    malloc_string(progress_str);
     5804    malloc_string(tmp_fname);
     5805    assert(bkpinfo != NULL);
     5806    malloc_string(xattr_fname);
     5807    malloc_string(acl_fname);
     5808    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
     5809    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
     5810    max_val = atol(tmp) + 1;
     5811
     5812    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
     5813
     5814    run_program_and_log_output("pwd", 5);
     5815
     5816    sprintf(progress_str, "Restoring from media #%d",
     5817            g_current_media_number);
     5818    log_to_screen(progress_str);
     5819    open_progress_form("Restoring from archives",
     5820                       "Restoring data from the archives.",
     5821                       "Please wait. This may take some time.",
     5822                       progress_str, max_val);
     5823
     5824    log_msg(3, "hey");
     5825
     5826    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     5827    if (res) {
     5828        log_msg(2, "Warning - error reading afioball from tape");
     5829    }
     5830    retval += res;
     5831    if (ctrl_chr != BLK_START_AFIOBALLS) {
     5832        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
     5833    }
     5834    log_msg(2, "ho");
     5835    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     5836    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
     5837        update_progress_form(progress_str);
     5838        if (g_getfattr) {
     5839            sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
     5840                current_afioball_number);
     5841            unlink(xattr_fname);
     5842        }
     5843        if (g_getfacl) {
     5844            sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
     5845                current_afioball_number);
     5846            unlink(acl_fname);
     5847        }
     5848        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
     5849            iamhere("Reading EXAT files from tape");
     5850            res =
     5851                read_EXAT_files_from_tape(&tmp_size, tmp_fname,
     5852                                          &ctrl_chr, xattr_fname,
     5853                                          acl_fname);
     5854        }
     5855        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     5856            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     5857        }
     5858        sprintf(tmp,
     5859                "Restoring from fileset #%ld (name=%s, size=%ld K)",
     5860                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
     5861        res =
     5862            restore_a_tarball_from_stream(tmp_fname,
     5863                                          current_afioball_number,
     5864                                          filelist, tmp_size, xattr_fname,
     5865                                          acl_fname);
     5866        retval += res;
     5867        if (res) {
     5868            sprintf(tmp, "Fileset %ld - errors occurred",
     5869                    current_afioball_number);
     5870            log_to_screen(tmp);
     5871        }
     5872        res =
     5873            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     5874        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
     5875            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
     5876        }
     5877
     5878        current_afioball_number++;
     5879        g_current_progress++;
     5880        sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
     5881                current_afioball_number,
     5882                media_descriptor_string(bkpinfo->backup_media_type),
     5883                g_current_media_number);
     5884        res =
     5885            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     5886        if (g_getfattr) {
     5887            unlink(xattr_fname);
     5888        }
     5889        if (g_getfacl) {
     5890            unlink(acl_fname);
     5891        }
     5892    }                           // next
     5893    log_msg(1, "All done with afioballs");
     5894    close_progress_form();
     5895    if (retval) {
     5896        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     5897    } else {
     5898        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     5899    }
     5900    paranoid_free(tmp);
     5901    paranoid_free(progress_str);
     5902    paranoid_free(tmp_fname);
     5903    paranoid_free(xattr_fname);
     5904    paranoid_free(acl_fname);
     5905    return (retval);
     5906}
     5907
     5908/**************************************************************************
     5909 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
     5910 **************************************************************************/
     5911
     5912/* @} - end of LLrestoreGroup */
     5913
     5914
     5915/**
     5916 * Restore all files in @p filelist.
     5917 * @param bkpinfo The backup information structure. Most fields are used.
     5918 * @param filelist The node structure containing the list of files to be
     5919 * restored.
     5920 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
     5921 * @ingroup restoreGroup
     5922 */
     5923int restore_everything(struct s_node *filelist)
     5924{
     5925    int resA;
     5926    int resB;
     5927
     5928  /** mallco ***/
     5929    char *cwd;
     5930    char *newpath;
     5931    char *tmp;
     5932    assert(bkpinfo != NULL);
     5933
     5934    malloc_string(cwd);
     5935    malloc_string(newpath);
     5936    malloc_string(tmp);
     5937    log_msg(2, "restore_everything() --- starting");
     5938    g_current_media_number = 1;
     5939    getcwd(cwd, MAX_STR_LEN - 1);
     5940    sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
     5941    run_program_and_log_output(tmp, FALSE);
     5942    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
     5943    chdir(bkpinfo->restore_path);
     5944    getcwd(newpath, MAX_STR_LEN - 1);
     5945    log_msg(1, "path is now %s", newpath);
     5946    log_msg(1, "restoring everything");
     5947    if (!find_home_of_exe("petris") && !g_text_mode) {
     5948        newtDrawRootText(0, g_noof_rows - 2,
     5949                         "Press ALT-<left cursor> twice to play Petris :-) ");
     5950        newtRefresh();
     5951    }
     5952    mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
     5953    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     5954        mount_media();
     5955        mvaddstr_and_log_it(g_currentY++, 0,
     5956                            "Restoring OS and data from streaming media");
     5957        if (bkpinfo->backup_media_type == cdstream) {
     5958            openin_cdstream();
     5959        } else {
     5960            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
     5961            openin_tape();
     5962        }
     5963        resA = restore_all_tarballs_from_stream(filelist);
     5964        resB = restore_all_biggiefiles_from_stream(filelist);
     5965        if (bkpinfo->backup_media_type == cdstream) {
     5966            closein_cdstream();
     5967        } else {
     5968            closein_tape();
     5969        }
     5970    } else {
     5971        mvaddstr_and_log_it(g_currentY++, 0,
     5972                            "Restoring OS and data from CD/USB   ");
     5973        mount_media();
     5974        resA = restore_all_tarballs_from_CD(filelist);
     5975        resB = restore_all_biggiefiles_from_CD(filelist);
     5976    }
     5977    chdir(cwd);
     5978    if (resA + resB) {
     5979        log_to_screen("Errors occurred while data was being restored.");
     5980    }
     5981    if (length_of_file("/etc/raidtab") > 0) {
     5982        log_msg(2, "Copying local raidtab to restored filesystem");
     5983        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
     5984                                   "/etc/raidtab", FALSE);
     5985    }
     5986    kill_petris();
     5987    log_msg(2, "restore_everything() --- leaving");
     5988    paranoid_free(cwd);
     5989    paranoid_free(newpath);
     5990    paranoid_free(tmp);
     5991    return (resA + resB);
     5992}
     5993
     5994/**************************************************************************
     5995 *END_RESTORE_EVERYTHING                                                  *
     5996 **************************************************************************/
     5997
     5998
     5999
     6000/**
     6001 * @brief Haha. You wish! (This function is not implemented :-)
     6002 */
     6003int
     6004restore_live_from_monitas_server(char *monitas_device,
     6005                                 char *restore_this_directory,
     6006                                 char *restore_here)
     6007     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
     6008{
     6009    FILE *fout;
     6010    int retval = 0;
     6011    int i;
     6012    int j;
     6013    struct mountlist_itself the_mountlist;
     6014    static struct raidlist_itself the_raidlist;
     6015  /** malloc **/
     6016    char tmp[MAX_STR_LEN + 1];
     6017    char command[MAX_STR_LEN + 1];
     6018    char datablock[256 * 1024];
     6019    char datadisks_fname[MAX_STR_LEN + 1];
     6020    long k;
     6021    long length;
     6022    long long llt;
     6023    struct s_node *filelist = NULL;
     6024    assert(bkpinfo != NULL);
     6025    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
     6026    assert(restore_this_directory != NULL);
     6027    assert(restore_here != NULL);
     6028
     6029    sprintf(tmp, "restore_here = '%s'", restore_here);
     6030
     6031    log_msg(2, tmp);
     6032
     6033    log_msg(2, "restore_live_from_monitas_server() - starting");
     6034    unlink("/tmp/mountlist.txt");
     6035    unlink("/tmp/filelist.full");
     6036    unlink("/tmp/biggielist.txt");
     6037    if (restore_here[0] == '\0') {
     6038        strcpy(bkpinfo->restore_path, MNT_RESTORING);
     6039    } else {
     6040        strcpy(bkpinfo->restore_path, restore_here);
     6041    }
     6042    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
     6043    sprintf(tmp, "FYI - data will be restored to %s",
     6044            bkpinfo->restore_path);
     6045    log_msg(3, tmp);
     6046    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
     6047    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
     6048            (int) (random() % 32768));
     6049    chdir(bkpinfo->tmpdir);
     6050
     6051    sprintf(command, "cat %s", monitas_device);
     6052    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
     6053    if (!(fout = fopen(datadisks_fname, "w"))) {
     6054        log_OS_error(datadisks_fname);
     6055        return (1);
     6056    }
     6057    for (i = 0; i < 32; i++) {
     6058        for (j = 0; j < 4; j++) {
     6059            for (length = k = 0; length < 256 * 1024; length += k) {
     6060                k = fread(datablock + length, 1, 256 * 1024 - length,
     6061                          g_tape_stream);
     6062            }
     6063            fwrite(datablock, 1, length, fout);
     6064            g_tape_posK += length;
     6065        }
     6066    }
     6067    paranoid_fclose(fout);
     6068    sprintf(command,
     6069            "tar -zxvf %s ./tmp/mondo-restore.cfg ./tmp/mountlist.txt ./tmp/filelist.full ./tmp/biggielist.txt",
     6070            datadisks_fname);
     6071    run_program_and_log_output(command, 4);
     6072    read_header_block_from_stream(&llt, tmp, &i);
     6073    read_header_block_from_stream(&llt, tmp, &i);
     6074
     6075    unlink(datadisks_fname);
     6076    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
     6077    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
     6078
     6079
     6080    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
     6081    iamhere("FIXME");
     6082    fatal_error("This will fail");
     6083    sprintf(command,
     6084            "grep -E '^%s.*$' %s > %s",
     6085            restore_this_directory, g_filelist_full, g_filelist_full);
     6086    if (system(command)) {
     6087        retval++;
     6088        log_to_screen
     6089            ("Error(s) occurred while processing filelist and wildcard");
     6090    }
     6091    iamhere("FIXME");
     6092    fatal_error("This will fail");
     6093    sprintf(command,
     6094            "grep -E '^%s.*$' %s > %s",
     6095            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
     6096    if (system(command)) {
     6097        log_msg(1,
     6098                "Error(s) occurred while processing biggielist and wildcard");
     6099    }
     6100    sprintf(command, "touch %s", g_biggielist_txt);
     6101    run_program_and_log_output(command, FALSE);
     6102//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
     6103    retval += restore_everything(filelist);
     6104    free_filelist(filelist);
     6105    log_msg(2, "--------End of restore_live_from_monitas_server--------");
     6106    return (retval);
     6107}
     6108
     6109/**************************************************************************
     6110 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
     6111 **************************************************************************/
     6112
     6113
     6114
     6115
     6116extern void wait_until_software_raids_are_prepped(char *, int);
     6117
     6118
     6119char which_restore_mode(void);
     6120
     6121
     6122/**
     6123 * Log a "don't panic" message to the logfile.
     6124 */
     6125void welcome_to_mondorestore()
     6126{
     6127    log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
     6128    log_msg(0,
     6129            "DON'T PANIC! Mondorestore logs almost everything, so please ");
     6130    log_msg(0,
     6131            "don't break out in a cold sweat just because you see a few  ");
     6132    log_msg(0,
     6133            "error messages in the log. Read them; analyze them; see if  ");
     6134    log_msg(0,
     6135            "they are significant; above all, verify your backups! Please");
     6136    log_msg(0,
     6137            "attach a compressed copy of this log to any e-mail you send ");
     6138    log_msg(0,
     6139            "to the Mondo mailing list when you are seeking technical    ");
     6140    log_msg(0,
     6141            "support. Without it, we can't help you.            - DevTeam");
     6142    log_msg(0,
     6143            "------------------------------------------------------------");
     6144    log_msg(0,
     6145            "BTW, despite (or perhaps because of) the wealth of messages,");
     6146    log_msg(0,
     6147            "some users are inclined to stop reading this log.  If Mondo ");
     6148    log_msg(0,
     6149            "stopped for some reason, chances are it's detailed here.    ");
     6150    log_msg(0,
     6151            "More than likely there's a message at the very end of this  ");
     6152    log_msg(0,
     6153            "log that will tell you what is wrong.  Please read it!      ");
     6154    log_msg(0,
     6155            "------------------------------------------------------------");
     6156}
     6157
     6158
     6159
     6160/**
     6161 * Restore the user's data.
     6162 * What did you think it did, anyway? :-)
     6163 */
     6164int main(int argc, char *argv[])
     6165{
     6166    FILE *fin;
     6167    FILE *fout;
     6168    int retval = 0;
     6169    int res;
     6170//  int c;
     6171    char *tmp;
     6172
     6173    struct mountlist_itself *mountlist;
     6174    struct raidlist_itself *raidlist;
     6175    struct s_node *filelist;
     6176    char *a, *b;
     6177    bool run_postnuke = FALSE;
     6178
     6179  /**************************************************************************
     6180   * hugo-                                                                  *
     6181   * busy stuff here - it needs some comments -stan                           *
     6182   *                                                                        *
     6183   **************************************************************************/
     6184    if (getuid() != 0) {
     6185        fprintf(stderr, "Please run as root.\r\n");
     6186        exit(127);
     6187    }
     6188    if (!
     6189        (bkpinfo = malloc(sizeof(struct s_bkpinfo)))) {
     6190        fatal_error("Cannot malloc bkpinfo");
     6191    }
     6192    reset_bkpinfo();
     6193
     6194    g_loglevel = DEFAULT_MR_LOGLEVEL;
     6195    malloc_string(tmp);
     6196
     6197/* Configure global variables */
     6198#ifdef __FreeBSD__
     6199    if (strstr
     6200        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
     6201         "textonly"))
     6202#else
     6203    if (strstr
     6204        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
     6205         "textonly"))
     6206#endif
     6207    {
     6208        g_text_mode = TRUE;
     6209        log_msg(1, "TEXTONLY MODE");
     6210    } else {
     6211        g_text_mode = FALSE;
     6212    }                           // newt :-)
     6213    if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
     6214        fatal_error("Cannot malloc mountlist");
     6215    }
     6216    if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
     6217        fatal_error("Cannot malloc raidlist");
     6218    }
     6219
     6220    malloc_libmondo_global_strings();
     6221
     6222    strcpy(g_mondo_home,
     6223           call_program_and_get_last_line_of_output("which mondorestore"));
     6224    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
     6225    make_hole_for_dir(g_tmpfs_mountpt);
     6226    g_current_media_number = 1; // precaution
     6227
     6228    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
     6229
     6230    malloc_string(tmp);
     6231    malloc_string(a);
     6232    malloc_string(b);
     6233    setup_MR_global_filenames();    // malloc() and set globals, using bkpinfo->tmpdir etc.
     6234    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
     6235    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
     6236    if (am_I_in_disaster_recovery_mode()) {
     6237        run_program_and_log_output("mount / -o remount,rw", 2);
     6238    }                           // for b0rken distros
     6239    g_main_pid = getpid();
     6240    srandom((int) (time(NULL)));
     6241    register_pid(getpid(), "mondo");
     6242    set_signals(TRUE);
     6243    g_kernel_version = get_kernel_version();
     6244
     6245    log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
     6246    if (strlen(g_mountlist_fname) < 3) {
     6247        fatal_error
     6248            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
     6249    }
     6250    mkdir(MNT_CDROM, 0x770);
     6251    make_hole_for_dir(MONDO_CACHE);
     6252
     6253    /* Backup original mountlist.txt */
     6254    sprintf(tmp, "%s.orig", g_mountlist_fname);
     6255    if (!does_file_exist(g_mountlist_fname)) {
     6256        log_msg(2,
     6257                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
     6258                __LINE__, g_mountlist_fname);
     6259    } else if (!does_file_exist(tmp)) {
     6260        sprintf(tmp, "cp -f %s %s.orig", g_mountlist_fname,
     6261                g_mountlist_fname);
     6262        run_program_and_log_output(tmp, FALSE);
     6263    }
     6264
     6265    /* Init directories */
     6266    make_hole_for_dir("/var/log");
     6267    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
     6268    run_program_and_log_output("umount " MNT_CDROM, FALSE);
     6269    /*
     6270    run_program_and_log_output("ln -sf /var/log/mondo-archive.log /tmp/mondorestore.log",
     6271         FALSE);
     6272         */
     6273
     6274    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
     6275
     6276    /* Init GUI */
     6277    malloc_libmondo_global_strings();
     6278    setup_newt_stuff();         /* call newtInit and setup screen log */
     6279    welcome_to_mondorestore();
     6280    if (bkpinfo->disaster_recovery) {
     6281        log_msg(1, "I am in disaster recovery mode");
     6282    } else {
     6283        log_msg(1, "I am in normal, live mode");
     6284    }
     6285
     6286    iamhere("what time is it");
     6287
     6288    /* Process command-line parameters */
     6289    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
     6290#ifdef __FreeBSD__
     6291        system("mv -f /tmp/raidconf.txt /etc/raidtab");
     6292        if (!does_file_exist("/etc/raidtab"))
     6293            system("vinum printconfig > /etc/raidtab");
     6294#endif
     6295        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     6296        if (!does_file_exist(g_mountlist_fname)) {
     6297            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     6298        }
     6299        res = let_user_edit_the_mountlist(mountlist, raidlist);
     6300#ifdef __FreeBSD__
     6301        system("mv -f /etc/raidtab /tmp/raidconf.txt");
     6302#endif
     6303        paranoid_MR_finish(res);
     6304    }
     6305
     6306    g_loglevel = DEFAULT_MR_LOGLEVEL;
     6307    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
     6308        fout = fopen("/tmp/out.txt", "w");
     6309        fput_string_one_char_at_a_time(stderr, argv[2]);
     6310        finish(0);
     6311    }
     6312
     6313    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
     6314        make_grub_install_scriptlet(argv[2]);
     6315        finish(0);
     6316    }
     6317
     6318    if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
     6319        if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
     6320            system("mount " MNT_CDROM);
     6321        }
     6322        bkpinfo->compression_level = 1;
     6323        g_current_media_number = 2;
     6324        strcpy(bkpinfo->restore_path, "/tmp/TESTING");
     6325        bkpinfo->backup_media_type = dvd;
     6326        open_progress_form("Reassembling /dev/hda1",
     6327                           "Shark is a bit of a silly person.",
     6328                           "Please wait. This may take some time.",
     6329                           "", 1999);
     6330        system("rm -Rf /tmp/*pih*");
     6331
     6332        restore_a_biggiefile_from_CD(42, NULL, tmp);
     6333    }
     6334
     6335    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
     6336        g_loglevel = 6;
     6337        filelist = load_filelist(argv[2]);
     6338        if (!filelist) {
     6339            fatal_error("Failed to load filelist");
     6340        }
     6341        toggle_node_selection(filelist, FALSE);
     6342        toggle_all_root_dirs_on(filelist);
     6343        // BERLIOS: /usr/lib ???
     6344        toggle_path_selection(filelist, "/usr/share", TRUE);
     6345//      show_filelist(filelist);
     6346        save_filelist(filelist, "/tmp/out.txt");
     6347//      finish(0);
     6348//      toggle_path_selection (filelist, "/root/stuff", TRUE);
     6349        strcpy(a, argv[3]);
     6350        strcpy(b, argv[4]);
     6351
     6352        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
     6353        free_filelist(filelist);
     6354        printf("res = %d", res);
     6355        finish(0);
     6356    }
     6357
     6358    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
     6359        popup_changelist_from_file(argv[2]);
     6360        paranoid_MR_finish(0);
     6361    }
     6362
     6363    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
     6364        log_msg(1, "SCORE");
     6365        g_loglevel = 10;
     6366        if (strstr(argv[2], "save")) {
     6367            log_msg(1, "Saving from %s to %s", argv[3], argv[4]);
     6368            fin = fopen(argv[3], "r");
     6369            fout = fopen(argv[4], "w");
     6370            copy_from_src_to_dest(fin, fout, 'w');
     6371            fclose(fin);
     6372            fin = fopen(argv[3], "r");
     6373            copy_from_src_to_dest(fin, fout, 'w');
     6374            fclose(fout);
     6375            fclose(fin);
     6376        } else if (strstr(argv[2], "restore")) {
     6377            fout = fopen(argv[3], "w");
     6378            fin = fopen(argv[4], "r");
     6379            copy_from_src_to_dest(fout, fin, 'r');
     6380            fclose(fin);
     6381            fin = fopen(argv[4], "r");
     6382            copy_from_src_to_dest(fout, fin, 'r');
     6383            fclose(fout);
     6384            fclose(fin);
     6385        } else {
     6386            fatal_error("Unknown additional param");
     6387        }
     6388        finish(0);
     6389    }
     6390
     6391    if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
     6392        wait_until_software_raids_are_prepped(argv[2], 100);
     6393        finish(0);
     6394    }
     6395
     6396    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
     6397        finish(create_raidtab_from_mdstat(argv[2]));
     6398    }
     6399
     6400    if (argc == 3 && strcmp(argv[1], "-p") == 0) {
     6401        strcpy(bkpinfo->prefix,argv[2]);
     6402        log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
     6403    }
     6404
     6405    if (argc == 3 && strcmp(argv[1], "-K") == 0) {
     6406        g_loglevel = atoi(argv[2]);
     6407        log_msg(1,"Loglevel forced to %s",g_loglevel);
     6408    }
     6409
     6410    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
     6411        retval = run_grub(FALSE, "/dev/hda");
     6412        if (retval) {
     6413            log_to_screen("Failed to write Master Boot Record");
     6414        }
     6415        paranoid_MR_finish(0);
     6416    }
     6417    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
     6418        g_current_media_number = atoi(argv[2]);
     6419        pause_and_ask_for_cdr(5, NULL);
     6420        paranoid_MR_finish(0);
     6421    } else if (!bkpinfo->disaster_recovery) {   // live!
     6422        if (argc != 1) {
     6423            popup_and_OK
     6424                ("Live mode doesn't support command-line parameters yet.");
     6425            paranoid_MR_finish(1);
     6426//    return(1);
     6427        }
     6428        log_msg(1, "I am in normal, live mode.");
     6429        log_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
     6430        mount_boot_if_necessary();  /* for Gentoo users */
     6431        log_msg(2, "Still here.");
     6432        if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
     6433            g_restoring_live_from_cd = TRUE;
     6434        }
     6435        if (bkpinfo->backup_media_type == nfs) {
     6436            g_restoring_live_from_nfs = TRUE;
     6437        }
     6438        if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
     6439            retval =
     6440                restore_live_from_monitas_server(argv[2],
     6441                                                 argv[3], argv[4]);
     6442        } else {
     6443            log_msg(2, "Calling restore_to_live_filesystem()");
     6444            retval = restore_to_live_filesystem();
     6445        }
     6446        log_msg(2, "Still here. Yay.");
     6447        if (strlen(bkpinfo->tmpdir) > 0) {
     6448            sprintf(tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
     6449            run_program_and_log_output(tmp, FALSE);
     6450        }
     6451        unmount_boot_if_necessary();    /* for Gentoo users */
     6452        paranoid_MR_finish(retval);
     6453    } else {
     6454        /* Disaster recovery mode (must be) */
     6455        log_msg(1, "I must be in disaster recovery mode.");
     6456        log_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
     6457        if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
     6458            log_to_screen("Uh, that hasn't been implemented yet.");
     6459            paranoid_MR_finish(1);
     6460        }
     6461
     6462        iamhere("About to call load_mountlist and load_raidtab");
     6463        strcpy(bkpinfo->restore_path, MNT_RESTORING);
     6464        read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
     6465        retval = load_mountlist(mountlist, g_mountlist_fname);
     6466        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     6467        iamhere
     6468            ("Returned from calling load_mountlist and load_raidtab successfully");
     6469
     6470        if (argc > 1
     6471            && (strcmp(argv[1], "--compare") == 0
     6472                || strcmp(argv[1], "--nuke") == 0)) {
     6473            if (bkpinfo->backup_media_type == nfs
     6474                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
     6475                log_msg(1, "Mounting nfs dir");
     6476                sprintf(bkpinfo->isodir, "/tmp/isodir");
     6477                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
     6478                sprintf(tmp, "mount %s -t nfs -o nolock /tmp/isodir",
     6479                        bkpinfo->nfs_mount);
     6480                run_program_and_log_output(tmp, 1);
     6481            }
     6482        }
     6483
     6484
     6485        if (retval) {
     6486            log_to_screen
     6487                ("Warning - load_raidtab_into_raidlist returned an error");
     6488        }
     6489
     6490
     6491        log_msg(1, "Send in the clowns.");
     6492
     6493        if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
     6494            log_msg(0, "Partitioning only.");
     6495            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     6496            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     6497            load_mountlist(mountlist, g_mountlist_fname);
     6498            res = partition_everything(mountlist);
     6499            finish(res);
     6500        }
     6501
     6502        if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
     6503            log_msg(0, "Formatting only.");
     6504            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     6505            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     6506            load_mountlist(mountlist, g_mountlist_fname);
     6507            res = format_everything(mountlist, FALSE, raidlist);
     6508            finish(res);
     6509        }
     6510
     6511        if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
     6512            log_msg(0, "Stopping LVM and RAID");
     6513            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     6514            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     6515            load_mountlist(mountlist, g_mountlist_fname);
     6516            res = do_my_funky_lvm_stuff(TRUE, FALSE);
     6517            res += stop_all_raid_devices(mountlist);
     6518            finish(res);
     6519        }
     6520
     6521        if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
     6522            iamhere("nuking");
     6523            retval += nuke_mode(mountlist, raidlist);
     6524        } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
     6525            iamhere("catchall");
     6526            retval += catchall_mode(mountlist, raidlist);
     6527        } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
     6528            iamhere("compare");
     6529            retval += compare_mode(mountlist, raidlist);
     6530        } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
     6531            iamhere("iso");
     6532            retval = iso_mode(mountlist, raidlist, FALSE);
     6533        } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
     6534            iamhere("mbr");
     6535            retval = mount_all_devices(mountlist, TRUE);
     6536            if (!retval) {
     6537                retval += run_boot_loader(FALSE);
     6538                retval += unmount_all_devices(mountlist);
     6539            }
     6540            if (retval) {
     6541                log_to_screen("Failed to write Master Boot Record");
     6542            }
     6543        } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
     6544            iamhere("isonuke");
     6545            retval = iso_mode(mountlist, raidlist, TRUE);
     6546        } else if (argc != 1) {
     6547            log_to_screen("Invalid paremeters");
     6548            paranoid_MR_finish(1);
     6549        } else {
     6550            iamhere("catchall (no mode specified in command-line call");
     6551            retval += catchall_mode(mountlist, raidlist);
     6552        }
     6553    }
     6554
     6555    /* clean up at the end */
     6556    if (retval) {
     6557        if (does_file_exist(MONDO_CACHE"/changed.files")) {
     6558            log_to_screen
     6559                ("See "MONDO_CACHE"/changed.files for list of files that have changed.");
     6560        }
     6561        mvaddstr_and_log_it(g_currentY++,
     6562                            0,
     6563                            "Run complete. Errors were reported. Please review the logfile.");
     6564    } else {
     6565        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     6566            mvaddstr_and_log_it(g_currentY++,
     6567                                0,
     6568                                "Run complete. Please remove media and reboot.");
     6569        } else {
     6570            run_program_and_log_output("sync", FALSE);
     6571            if (is_this_device_mounted(MNT_CDROM)) {
     6572                res =
     6573                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
     6574            } else {
     6575                res = 0;
     6576            }
     6577
     6578            if (!bkpinfo->please_dont_eject) {
     6579                res = eject_device("/dev/cdrom");
     6580/*
     6581              if (res)
     6582        {
     6583          log_to_screen( "WARNING - failed to eject CD-ROM disk" );
     6584        }
     6585*/
     6586            }
     6587            mvaddstr_and_log_it(g_currentY++,
     6588                                0,
     6589                                "Run complete. Please remove media and reboot.");
     6590        }
     6591    }
     6592
     6593// g_I_have_just_nuked is set true by nuke_mode() just before it returns
     6594    if (!system("which post-nuke > /dev/null 2> /dev/null")) {
     6595      log_msg(1, "post-nuke found; find out whether we should run it...");
     6596      if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
     6597        run_postnuke = TRUE;
     6598        log_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
     6599      } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
     6600        run_postnuke = TRUE;
     6601        log_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
     6602      } else {
     6603        run_postnuke = FALSE;
     6604        log_msg(1, "No, will not run post-nuke.");
     6605      }
     6606    } else {
     6607      log_msg(1, "No post-nuke found.");
     6608    }
     6609    if (run_postnuke) {
     6610      log_to_screen("Running post-nuke...");
     6611      if (mount_all_devices(mountlist, TRUE)) {
     6612        log_to_screen
     6613          ("Unable to re-mount partitions for post-nuke stuff");
     6614      } else {
     6615        log_msg(1, "Re-mounted partitions for post-nuke stuff");
     6616        sprintf(tmp, "post-nuke %s %d", bkpinfo->restore_path,
     6617            retval);
     6618        log_msg(2, "Calling '%s'", tmp);
     6619        if ((res = run_program_and_log_output(tmp, 0))) {
     6620          log_OS_error(tmp);
     6621        }
     6622        log_msg(1, "post-nuke returned w/ res=%d", res);
     6623      }
     6624      unmount_all_devices(mountlist);
     6625      log_to_screen("I've finished post-nuking.");
     6626    }
     6627
     6628/* 
     6629  log_to_screen("If you are REALLY in a hurry, hit Ctrl-Alt-Del now.");
     6630  log_to_screen("Otherwise, please wait until the RAID disks are done.");
     6631  wait_until_software_raids_are_prepped("/proc/mdstat", 100);
     6632  log_to_screen("Thank you.");
     6633*/
     6634    unlink("/tmp/mondo-run-prog.tmp");
     6635    set_signals(FALSE);
     6636    log_to_screen("Restore log (%s) copied to /var/log on your hard disk", MONDO_LOGFILE);
     6637    sprintf(tmp,
     6638            "Mondo-restore is exiting (retval=%d)                                      ",
     6639            retval);
     6640    log_to_screen(tmp);
     6641    sprintf(tmp, "umount %s", bkpinfo->isodir);
     6642    run_program_and_log_output(tmp, 5);
     6643    paranoid_free(mountlist);
     6644    paranoid_free(raidlist);
     6645    if (am_I_in_disaster_recovery_mode()) {
     6646        run_program_and_log_output("mount / -o remount,rw", 2);
     6647    }                           // for b0rken distros
     6648    sprintf(tmp, "rm -Rf %s", bkpinfo->tmpdir);
     6649    system(tmp);
     6650    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
     6651    free_libmondo_global_strings(); // it's fine to have this here :) really :)
     6652    paranoid_free(a);
     6653    paranoid_free(b);
     6654    paranoid_free(tmp);
     6655
     6656    unlink("/tmp/filelist.full");
     6657    unlink("/tmp/filelist.full.gz");
     6658
     6659    exit(retval);
     6660}
     6661
     6662/**************************************************************************
     6663 *END_MAIN                                                                *
     6664 **************************************************************************/
     6665
     6666
     6667
     6668
     6669
     6670/**************************************************************************
     6671 *END_MONDO-RESTORE.C                                                     *
     6672 **************************************************************************/
Note: See TracChangeset for help on using the changeset viewer.