Changeset 3374


Ignore:
Timestamp:
Apr 27, 2015, 4:25:29 PM (5 years ago)
Author:
Bruno Cornec
Message:
  • Fix compilation warnings and errors
Location:
branches/3.2/mondo
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mondo/src/common/libmondo-devices.c

    r3373 r3374  
    32843284}
    32853285/* @} - end of deviceGroup */
     3286
     3287
  • branches/3.2/mondo/src/common/libmondo-mountlist.c

    r3308 r3374  
    2222/*@unused@*/
    2323//static char cvsid[] = "$Id$";
    24 
    25 /* Reference to global bkpinfo */
    26 extern struct s_bkpinfo *bkpinfo;
    2724
    2825/**
  • branches/3.2/mondo/src/include/mr_str.h

    r3193 r3374  
    1919extern inline char *mr_date(void);
    2020extern void mr_strip_spaces(char *in_out);
     21extern char *mr_str_substitute(const char *in, const char *token, const char *subst);
    2122/*
    2223extern void mr_strip_char(char *in_out, char *caracs);
  • branches/3.2/mondo/src/mondorestore/mondorestore.c

    r3301 r3374  
    1717#include "mondo-rstr-compare-EXT.h"
    1818#include "mondo-rstr-tools-EXT.h"
     19#include <utime.h>
     20
     21extern void wait_until_software_raids_are_prepped(char *, int);
    1922
    2023extern void twenty_seconds_til_yikes(void);
     
    2629struct s_bkpinfo *bkpinfo;
    2730
     31char which_restore_mode(void);
    2832
    2933/* For use in other programs (ex. XMondo) */
     
    132136#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."
    133137
    134 
    135 
    136 
    137 /**
    138  * Allow the user to modify the mountlist before we partition & format their drives.
    139  * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
    140  * @param mountlist The mountlist to let the user modify.
    141  * @param raidlist The raidlist that goes with @p mountlist.
    142  * @return 0 for success, nonzero for failure.
    143  * @ingroup restoreGuiGroup
    144  */
    145 int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
    146                                 struct raidlist_itself *raidlist)
    147 {
    148     int retval = 0, res = 0;
    149 
    150     log_msg(2, "let_user_edit_the_mountlist() --- starting");
    151 
    152     assert(bkpinfo != NULL);
    153     assert(mountlist != NULL);
    154     assert(raidlist != NULL);
    155     if (!bkpinfo->disaster_recovery) {
    156         strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
    157         log_msg(2, "I guess you're testing edit_mountlist()");
    158     }
    159     if (!does_file_exist(g_mountlist_fname)) {
    160         log_to_screen(g_mountlist_fname);
    161         log_to_screen("does not exist");
    162         return (1);
    163     }
    164 
    165     retval = load_mountlist(mountlist, g_mountlist_fname);
    166     load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
    167     if (retval) {
    168         log_to_screen
    169             ("Warning - load_raidtab_into_raidlist returned an error");
    170     }
    171     res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
    172     if (res) {
    173         return (1);
    174     }
    175 
    176     save_mountlist_to_disk(mountlist, g_mountlist_fname);
    177     save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
    178 
    179     log_to_screen("I have finished editing the mountlist for you.");
    180 
    181     return (retval);
    182 }
    183 
    184 
    185 
    186 
    187 
    188138/**
    189139 * Determine whether @p mountlist contains a Compaq diagnostic partition.
     
    193143 */
    194144bool
    195 partition_table_contains_Compaq_diagnostic_partition(struct
    196                                                      mountlist_itself *
    197                                                      mountlist)
    198 {
    199     int i;
    200 
    201     assert(mountlist != NULL);
    202 
    203     for (i = 0; i < mountlist->entries; i++) {
    204         if (strstr(mountlist->el[i].format, "ompaq")) {
    205             log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
    206                     i, mountlist->el[i].device, mountlist->el[i].format);
    207 
    208             return (TRUE);
    209         }
    210     }
    211     return (FALSE);
     145partition_table_contains_Compaq_diagnostic_partition(struct mountlist_itself * mountlist) {
     146
     147int i;
     148
     149assert(mountlist != NULL);
     150
     151for (i = 0; i < mountlist->entries; i++) {
     152    if (strstr(mountlist->el[i].format, "ompaq")) {
     153        log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)", i, mountlist->el[i].device, mountlist->el[i].format);
     154
     155        return (TRUE);
     156    }
     157}
     158return (FALSE);
    212159}
    213160
     
    225172{
    226173    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
    227     if (ask_me_yes_or_no
    228         ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
     174    if (ask_me_yes_or_no("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
    229175    {
    230         fatal_error
    231             ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
     176        fatal_error("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
    232177    }
    233178}
     
    237182 **************************************************************************/
    238183
    239 
    240 
    241 /**
    242  * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
    243  * @param bkpinfo The backup information structure. Most fields are used.
    244  * @param mountlist The mountlist containing information about the user's partitions.
    245  * @param raidlist The raidlist to go with @p mountlist.
    246  * @return The return code from the mode function called.
    247  * @ingroup restoreGroup
    248  */
    249 int
    250 catchall_mode(struct mountlist_itself *mountlist,
    251               struct raidlist_itself *raidlist)
    252 {
    253     char c;
    254     char *tmp = NULL;
    255     int retval = 0;
    256 
    257     log_it("inside catchall");
    258     assert(bkpinfo != NULL);
    259     assert(mountlist != NULL);
    260     assert(raidlist != NULL);
    261     log_it("pre wrm");
    262     c = which_restore_mode();
    263     log_it("post wrm");
    264     if (c == 'I' || c == 'C') {
    265         interactively_obtain_media_parameters_from_user(FALSE);
    266     } else if (c == 'N') {
    267         // Auto mode nothing special to do
    268     } else {
    269         popup_and_OK("No restoring or comparing will take place today.");
    270         if (is_this_device_mounted("/mnt/cdrom")) {
    271             run_program_and_log_output("umount -d /mnt/cdrom", FALSE);
    272         }
    273         if (g_ISO_restore_mode) {
    274             mr_asprintf(tmp, "umount -d %s", bkpinfo->isodir);
    275             run_program_and_log_output(tmp, FALSE);
    276             mr_free(tmp);
    277         }
    278         paranoid_MR_finish(0);
    279     }
    280 
    281     log_it("post int");
    282 
    283     if (bkpinfo->backup_media_type == iso) {
    284         if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
    285             log_msg(2,
    286                     "catchall_mode --- iso_fiddly_bits returned w/ error");
    287             return (1);
    288         } else {
    289             log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
    290         }
    291     }
    292 
    293     if (c == 'I') {
    294         log_msg(2, "IM selected");
    295         retval += interactive_mode(mountlist, raidlist);
    296     } else if (c == 'N') {
    297         log_msg(2, "NM selected");
    298         retval += nuke_mode(mountlist, raidlist);
    299     } else if (c == 'C') {
    300         log_msg(2, "CM selected");
    301         retval += compare_mode(mountlist, raidlist);
    302     }
    303     return (retval);
    304 }
    305 
    306 /**************************************************************************
    307  *END_CATCHALL_MODE                                                      *
    308  **************************************************************************/
    309 
    310 /**************************************************************************
    311  *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
    312  **************************************************************************/
    313 
    314 
    315 /**
    316  * Locate an executable in the directory structure rooted at @p restg.
    317  * @param out_path Where to put the executable.
    318  * @param fname The basename of the executable.
    319  * @param restg The directory structure to look in.
    320  * @note If it could not be found in @p restg then @p fname is put in @p out_path.
    321  * @ingroup restoreUtilityGroup
    322  */
    323 void
    324 find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
    325                                                     char *fname,
    326                                                     char *restg)
    327 {
    328     assert(out_path != NULL);
    329     assert_string_is_neither_NULL_nor_zerolength(fname);
    330 
    331     sprintf(out_path, "%s/sbin/%s", restg, fname);
    332     if (does_file_exist(out_path)) {
    333         sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
    334         if (does_file_exist(out_path)) {
    335             sprintf(out_path, "%s/bin/%s", restg, fname);
    336             if (does_file_exist(out_path)) {
    337                 sprintf(out_path, "%s/usr/bin/%s", restg, fname);
    338                 if (does_file_exist(out_path)) {
    339                     strcpy(out_path, fname);
    340                 }
    341             }
    342         }
    343     }
    344 }
    345 
    346 /**************************************************************************
    347  *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
    348  **************************************************************************/
    349184
    350185static void clean_blkid() {
     
    402237
    403238
     239/**
     240 * Restore biggiefile @p bigfileno from the currently mounted CD.
     241 * @param bkpinfo The backup information structure. Fields used:
     242 * - @c bkpinfo->backup_media_type
     243 * - @c bkpinfo->restore_path
     244 * @param bigfileno The biggiefile number (starting from 0) to restore.
     245 * @param filelist The node structure containing the list of files to restore.
     246 * If the biggiefile is not in this list, it will be skipped (return value will
     247 * still indicate success).
     248 * @return 0 for success (or skip), nonzero for failure.
     249 */
     250int restore_a_biggiefile_from_CD(long bigfileno,
     251                             struct s_node *filelist,
     252                             char *pathname_of_last_file_restored)
     253{
     254    FILE *fin;
     255    FILE *fout;
     256    FILE *fbzip2;
     257
     258  /** malloc ***/
     259    char *checksum = NULL;
     260    char *outfile_fname = NULL;
     261    char *tmp = NULL;
     262    char *bzip2_command = NULL;
     263    char *suffix = NULL;
     264    char *sz_devfile = NULL;
     265    char *bigblk;
     266    char *mds = NULL;
     267    int retval = 0;
     268    int finished = FALSE;
     269    long sliceno;
     270    long siz;
     271    char *ntfsprog_fifo = NULL;
     272    char *file_to_openout = NULL;
     273    struct s_filename_and_lstat_info biggiestruct;
     274    struct utimbuf the_utime_buf, *ubuf;
     275    bool use_ntfsprog_hack = FALSE;
     276    pid_t pid;
     277    int res = 0;
     278    int old_loglevel;
     279    struct s_node *node;
     280
     281    old_loglevel = g_loglevel;
     282    ubuf = &the_utime_buf;
     283    assert(bkpinfo != NULL);
     284
     285    pathname_of_last_file_restored[0] = '\0';
     286    if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
     287        fatal_error("Cannot malloc bigblk");
     288    }
     289
     290    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
     291        log_to_screen("Cannot even open bigfile's info file");
     292        return (1);
     293    }
     294
     295    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
     296    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
     297        sizeof(biggiestruct)) {
     298        log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
     299                bigfileno + 1);
     300    }
     301    paranoid_fclose(fin);
     302
     303    mr_asprintf(checksum, "%s", biggiestruct.checksum);
     304    if (!checksum[0]) {
     305        log_msg(3, "Warning - bigfile %ld does not have a checksum", bigfileno + 1);
     306    }
     307    mr_free(checksum);
     308
     309    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
     310    {
     311        mr_asprintf(outfile_fname, "%s", biggiestruct.filename);
     312    } else {
     313        mr_asprintf(outfile_fname, "%s/%s", bkpinfo->restore_path, biggiestruct.filename);
     314    }
     315
     316    /* skip file if we have a selective restore subset & it doesn't match */
     317    if (filelist != NULL) {
     318        node = find_string_at_node(filelist, biggiestruct.filename);
     319        if (!node) {
     320            log_msg(0, "Skipping %s (name isn't in filelist)", biggiestruct.filename);
     321            pathname_of_last_file_restored[0] = '\0';
     322            return (0);
     323        } else if (!(node->selected)) {
     324            log_msg(1, "Skipping %s (name isn't in biggielist subset)", biggiestruct.filename);
     325            pathname_of_last_file_restored[0] = '\0';
     326            return (0);
     327        }
     328    }
     329
     330    /* otherwise, continue */
     331    log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
     332    if (biggiestruct.use_ntfsprog) {
     333        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
     334            log_msg(1, "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
     335            log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
     336            biggiestruct.use_ntfsprog = FALSE;
     337        }
     338    }
     339
     340    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
     341    {
     342        g_loglevel = 4;
     343        use_ntfsprog_hack = TRUE;
     344        log_msg(2, "Calling ntfsclone in background because %s is an NTFS /dev entry", outfile_fname);
     345        mr_asprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768), (int) (random() % 32768));
     346        mkfifo(sz_devfile, 0x770);
     347        mr_asprintf(ntfsprog_fifo, "%s", sz_devfile);
     348        mr_free(sz_devfile);
     349        file_to_openout = ntfsprog_fifo;
     350        switch (pid = fork()) {
     351        case -1:
     352            fatal_error("Fork failure");
     353        case 0:
     354            log_msg(3, "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)", biggiestruct.filename, ntfsprog_fifo);
     355            res = feed_outfrom_ntfsprog(biggiestruct.filename, ntfsprog_fifo);
     356            mr_free(ntfsprog_fifo);
     357            exit(res);
     358            break;
     359        default:
     360            log_msg(3, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid));
     361        }
     362        mr_free(ntfsprog_fifo);
     363    } else {
     364        use_ntfsprog_hack = FALSE;
     365        file_to_openout = outfile_fname;
     366        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
     367        {
     368            make_hole_for_file(outfile_fname);
     369        }
     370    }
     371
     372    log_msg(2, "Reassembling big file %ld (%s)", bigfileno + 1, outfile_fname);
     373
     374    /*
     375       last slice is zero-length and uncompressed; when we find it, we stop.
     376       We DON'T wait until there are no more slices; if we did that,
     377       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
     378     */
     379
     380    strncpy(pathname_of_last_file_restored, biggiestruct.filename, MAX_STR_LEN - 1);
     381    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
     382
     383    log_msg(3, "file_to_openout = %s", file_to_openout);
     384    if (!(fout = fopen(file_to_openout, "w"))) {
     385        log_to_screen("Cannot openout outfile_fname - hard disk full?");
     386        return (1);
     387    }
     388    log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
     389
     390    for (sliceno = 1, finished = FALSE; !finished;) {
     391        if (!does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "")) &&
     392            !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzo")) &&
     393            !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "gz")) &&
     394            !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzma")) &&
     395            !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
     396            log_msg(3, "Cannot find a data slice or terminator slice on CD %d", g_current_media_number);
     397            g_current_media_number++;
     398            mds = media_descriptor_string(bkpinfo->backup_media_type);
     399            log_msg(2, "Asking for %s #%d so that I may read slice #%ld\n", mds, g_current_media_number, sliceno);
     400            mr_free(mds);
     401
     402            log_to_screen("Restoring from %s #%d", mds, g_current_media_number);
     403
     404            insist_on_this_cd_number(g_current_media_number);
     405            log_to_screen("Continuing to restore.");
     406        } else {
     407            mr_asprintf(tmp, "%s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
     408            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
     409                log_msg(2, "End of bigfile # %ld (slice %ld is the terminator)", bigfileno + 1, sliceno);
     410                finished = TRUE;
     411                mr_free(tmp);
     412                continue;
     413            } else {
     414                if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
     415                    mr_asprintf(bzip2_command, "lzop");
     416                    mr_asprintf(suffix, "lzo");
     417                } else
     418                    if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
     419                    mr_asprintf(bzip2_command, "gzip");
     420                    mr_asprintf(suffix, "gz");
     421                } else
     422                    if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzma"))) {
     423                    mr_asprintf(bzip2_command, "lzma");
     424                    mr_asprintf(suffix, "lzma");
     425                } else
     426                    if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
     427                    mr_asprintf(bzip2_command, "bzip2");
     428                    mr_asprintf(suffix, "bz2");
     429                } else
     430                    if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))) {
     431                    mr_asprintf(bzip2_command, "");
     432                    mr_asprintf(suffix, "");
     433                } else {
     434                    log_to_screen("OK, that's pretty fsck0red...");
     435                    mr_free(tmp);
     436                    return (1);
     437                }
     438            }
     439            mr_free(tmp);
     440            if (bzip2_command != NULL) {
     441                mr_strcat(bzip2_command, " -dc %s 2>> %s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, suffix), MONDO_LOGFILE);
     442            } else {
     443                mr_asprintf(bzip2_command, "cat %s 2>> %s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, suffix), MONDO_LOGFILE);
     444            }
     445            mr_free(suffix);
     446
     447            mds = media_descriptor_string(bkpinfo->backup_media_type);
     448            mr_asprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ", mds, g_current_media_number, bigfileno + 1, sliceno);
     449            mr_free(mds);
     450            log_msg(2, tmp);
     451
     452            if (!g_text_mode) {
     453                newtDrawRootText(0, g_noof_rows - 2, tmp);
     454                newtRefresh();
     455                strip_spaces(tmp);
     456                update_progress_form(tmp);
     457            }
     458            mr_free(tmp);
     459
     460            if (!(fbzip2 = popen(bzip2_command, "r"))) {
     461                fatal_error("Can't run popen command");
     462            }
     463            mr_free(bzip2_command);
     464
     465            while (!feof(fbzip2)) {
     466                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
     467                if (siz > 0) {
     468                    siz = fwrite(bigblk, 1, siz, fout);
     469                }
     470            }
     471            paranoid_pclose(fbzip2);
     472
     473
     474            sliceno++;
     475            g_current_progress++;
     476        }
     477    }
     478    paranoid_fclose(fout);
     479    g_loglevel = old_loglevel;
     480
     481    if (use_ntfsprog_hack) {
     482        log_msg(3, "Waiting for ntfsclone to finish");
     483        mr_asprintf(tmp, " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
     484        while (system(tmp) == 0) {
     485            sleep(1);
     486        }
     487        mr_free(tmp);
     488        log_it("OK, ntfsclone has really finished");
     489    }
     490
     491    if (strcmp(outfile_fname, "/dev/null")) {
     492        if (chown(outfile_fname, biggiestruct.properties.st_uid, biggiestruct.properties.st_gid)) {
     493            // FIXME
     494        }
     495        chmod(outfile_fname, biggiestruct.properties.st_mode);
     496        ubuf->actime = biggiestruct.properties.st_atime;
     497        ubuf->modtime = biggiestruct.properties.st_mtime;
     498        utime(outfile_fname, ubuf);
     499    }
     500    mr_free(outfile_fname);
     501    paranoid_free(bigblk);
     502
     503    return (retval);
     504}
     505
     506/**************************************************************************
     507 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
     508 **************************************************************************/
     509
     510
     511/**
     512 * Restore all biggiefiles from all media in this CD backup.
     513 * The CD with the last afioball should be currently mounted.
     514 * @param bkpinfo The backup information structure. @c backup_media_type is the
     515 * only field used in this function.
     516 * @param filelist The node structure containing the list of files to be
     517 * restored. If a prospective biggiefile is not in this list, it will be ignored.
     518 * @return 0 for success, nonzero for failure.
     519 */
     520int restore_all_biggiefiles_from_CD(struct s_node *filelist) {
     521
     522    int retval = 0;
     523    int res = 0;
     524    long noof_biggiefiles, bigfileno = 0, total_slices;
     525  /** malloc **/
     526    char *tmp = NULL;
     527    char *tmp1 = NULL;
     528    char *mds = NULL;
     529    bool just_changed_cds = FALSE;
     530    char *xattr_fname = NULL;
     531    char *acl_fname = NULL;
     532    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
     533    char *pathname_of_last_biggie_restored;
     534    FILE *fbw = NULL;
     535
     536    malloc_string(pathname_of_last_biggie_restored);
     537    malloc_string(tmp);
     538    assert(bkpinfo != NULL);
     539
     540    mr_asprintf(biggies_whose_EXATs_we_should_set, "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
     541    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
     542        log_msg(1, "Warning - cannot openout %s", biggies_whose_EXATs_we_should_set);
     543    }
     544
     545    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
     546    total_slices = atol(tmp);
     547    mr_free(tmp);
     548
     549    mr_asprintf(tmp1, "Reassembling large files      ");
     550    mvaddstr_and_log_it(g_currentY, 0, tmp1);
     551    mr_free(tmp1);
     552
     553    if (length_of_file(BIGGIELIST) < 6) {
     554        log_msg(1, "OK, no biggielist; not restoring biggiefiles");
     555        return (0);
     556    }
     557    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
     558    if (noof_biggiefiles <= 0) {
     559        log_msg(2, "OK, no biggiefiles in biggielist; not restoring biggiefiles");
     560        return (0);
     561    }
     562    log_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
     563
     564    open_progress_form("Reassembling large files",
     565                       "I am now reassembling all the large files.",
     566                       "Please wait. This may take some time.",
     567                       "", total_slices);
     568    for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
     569        log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
     570        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
     571            log_msg(3, "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
     572            mds = media_descriptor_string(bkpinfo->backup_media_type);
     573            log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d", bigfileno + 1, mds, g_current_media_number);
     574            log_msg(3, "Slicename would have been %s",
     575                    slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
     576            // I'm not positive 'just_changed_cds' is even necessary...
     577            if (just_changed_cds) {
     578                just_changed_cds = FALSE;
     579                log_msg(3, "I'll continue to scan this CD for bigfiles to be restored.");
     580            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
     581                insist_on_this_cd_number(++g_current_media_number);
     582                log_to_screen("Restoring from %s #%d", mds, g_current_media_number);
     583                just_changed_cds = TRUE;
     584            } else {
     585                /* That big file doesn't exist, but the followings may */
     586                /* So we need to continue looping */
     587                log_msg(2, "There was no bigfile #%ld. That's OK.", bigfileno + 1);
     588                log_msg(2, "I'm going to stop restoring bigfiles now.");
     589                retval++;
     590                bigfileno++;
     591            }
     592            mr_free(mds);
     593        } else {
     594            just_changed_cds = FALSE;
     595            mr_asprintf(tmp1, "Restoring big file %ld", bigfileno + 1);
     596            update_progress_form(tmp1);
     597            mr_free(tmp1);
     598            res = restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
     599            log_it("%s",pathname_of_last_biggie_restored);
     600            if (fbw && pathname_of_last_biggie_restored[0]) {
     601                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
     602            }
     603            retval += res;
     604            bigfileno++;
     605
     606        }
     607    }
     608
     609    if (fbw) {
     610        fclose(fbw);
     611        if (g_getfattr) {
     612            mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
     613            if (length_of_file(xattr_fname) > 0) {
     614                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
     615            }
     616            mr_free(xattr_fname);
     617        }
     618        if (g_getfacl) {
     619            mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
     620            if (length_of_file(acl_fname) > 0) {
     621                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
     622            }
     623            mr_free(acl_fname);
     624        }
     625    }
     626    mr_free(biggies_whose_EXATs_we_should_set);
     627
     628    if (does_file_exist("/PAUSE")) {
     629        popup_and_OK("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     630    }
     631    close_progress_form();
     632    if (retval) {
     633        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     634    } else {
     635        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     636    }
     637    paranoid_free(pathname_of_last_biggie_restored);
     638    return (retval);
     639}
     640
     641/**************************************************************************
     642 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
     643 **************************************************************************/
     644
     645
     646
     647/**
     648 * Restore @p tarball_fname from CD.
     649 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
     650 * This will be used unmodified.
     651 * @param current_tarball_number The number (starting from 0) of the fileset
     652 * we're restoring now.
     653 * @param filelist The node structure containing the list of files to be
     654 * restored. If no file in the afioball is in this list, afio will still be
     655 * called, but nothing will be written.
     656 * @return 0 for success, nonzero for failure.
     657 */
     658int
     659restore_a_tarball_from_CD(char *tarball_fname,
     660                          long current_tarball_number,
     661                          struct s_node *filelist)
     662{
     663    int retval = 0;
     664    int res;
     665    char *p;
     666
     667  /** malloc **/
     668    char *command = NULL;
     669    char *tmp = NULL;
     670    char *filelist_name = NULL;
     671    char *filelist_subset_fname = NULL;
     672    char *executable = NULL;
     673    char *temp_log = NULL;
     674    long matches = 0;
     675    bool use_star;
     676    char *xattr_fname = NULL;
     677    char *acl_fname = NULL;
     678
     679    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
     680    assert(bkpinfo != NULL);
     681
     682    log_msg(5, "Entering");
     683    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
     684    mr_asprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
     685    run_program_and_log_output(command, 9);
     686    paranoid_free(command);
     687
     688    mr_asprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld", current_tarball_number);
     689    if (length_of_file(filelist_name) <= 2) {
     690        log_msg(2, "There are _zero_ files in filelist '%s'", filelist_name);
     691        log_msg(2, "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
     692        log_msg(2, "but it's non-critical. It's cosmetic. Don't worry about it.");
     693        retval = 0;
     694        mr_free(filelist_name);
     695        log_msg(5, "Leaving");
     696        return(0);
     697    }
     698    if (count_lines_in_file(filelist_name) <= 0 || length_of_file(tarball_fname) <= 0) {
     699        log_msg(3, "length_of_file(%s) = %llu", tarball_fname, length_of_file(tarball_fname));
     700        log_msg(3, "count_lines_in_file(%s) = %llu", tarball_fname, count_lines_in_file(tarball_fname));
     701        log_to_screen("Unable to restore fileset #%ld (CD I/O error)", current_tarball_number);
     702        mr_free(filelist_name);
     703        log_msg(5, "Leaving");
     704        return(1);
     705    }
     706
     707    if (filelist) {
     708        mr_asprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp", current_tarball_number);
     709        if ((matches =
     710             save_filelist_entries_in_common(filelist_name, filelist,
     711                                             filelist_subset_fname,
     712                                             use_star)) <= 0) {
     713            log_msg(1, "Skipping fileset %ld", current_tarball_number);
     714        } else {
     715            log_msg(3, "Saved fileset %ld's subset to %s", current_tarball_number, filelist_subset_fname);
     716        }
     717        log_to_screen("Tarball #%ld --- %ld matches", current_tarball_number, matches);
     718    }
     719    mr_free(filelist_name);
     720
     721    if (filelist == NULL || matches > 0) {
     722        if (g_getfattr) {
     723            mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
     724        }
     725        if (g_getfacl) {
     726            mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
     727        }
     728        if (strstr(tarball_fname, ".bz2")) {
     729            mr_asprintf(executable, "bzip2");
     730        } else if (strstr(tarball_fname, ".lzma")) {
     731            mr_asprintf(executable, "lzma");
     732        } else if (strstr(tarball_fname, ".gz")) {
     733            mr_asprintf(executable, "gzip");
     734        } else if (strstr(tarball_fname, ".lzo")) {
     735            mr_asprintf(executable, "lzop");
     736        }
     737        if (bkpinfo->compression_level == 0) {
     738            mr_asprintf(executable, "%s", "");
     739        } else {
     740            if (executable) {
     741                mr_asprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
     742                res = run_program_and_log_output(tmp, FALSE);
     743                mr_free(tmp);
     744   
     745                if (res) {
     746                    log_to_screen("(compare_a_tarball) Compression program %s not found - oh no!", executable);
     747                    paranoid_MR_finish(1);
     748                }
     749                tmp = executable;
     750                mr_asprintf(executable, "-P %s -Z", tmp);
     751                mr_free(tmp);
     752            }
     753        }
     754#ifdef __FreeBSD__
     755#define BUFSIZE 512
     756#else
     757#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
     758#endif
     759
     760        if (use_star) {
     761            mr_asprintf(command, "star -x -force-remove -sparse -U " STAR_ACL_SZ " file=%s", tarball_fname);
     762            if (strstr(tarball_fname, ".bz2")) {
     763                mr_strcat(command, " -bz");
     764            }
     765        } else {
     766            if (! executable) {
     767                log_msg(2, "No executable, this shouldn't happen !");
     768            } else {
     769                if (filelist_subset_fname != NULL) {
     770                    mr_asprintf(command, "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s", TAPE_BLOCK_SIZE, BUFSIZE, executable, filelist_subset_fname, tarball_fname);
     771                } else {
     772                    mr_asprintf(command, "afio -i -b %ld -c %ld -M 8m %s %s", TAPE_BLOCK_SIZE, BUFSIZE, executable, tarball_fname);
     773                }
     774            }
     775        }
     776        mr_free(executable);
     777
     778#undef BUFSIZE
     779        mr_asprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768), (int) (random() % 32768));
     780
     781        mr_strcat(command, " 2>> %s >> %s", temp_log, temp_log);
     782        log_msg(1, "command = '%s'", command);
     783        unlink(temp_log);
     784        res = system(command);
     785        if (res) {
     786            p = strstr(command, "-acl ");
     787            if (p) {
     788                p[0] = p[1] = p[2] = p[3] = ' ';
     789                log_msg(1, "new command = '%s'", command);
     790                res = system(command);
     791            }
     792        }
     793        paranoid_free(command);
     794
     795        if (res && length_of_file(temp_log) < 5) {
     796            res = 0;
     797        }
     798
     799        if (! use_star) {
     800            if (g_getfattr) {
     801                log_msg(1, "Setting fattr list %s", xattr_fname);
     802                if (length_of_file(xattr_fname) > 0) {
     803                    res = set_fattr_list(filelist_subset_fname, xattr_fname);
     804                    if (res) {
     805                        log_to_screen("Errors occurred while setting extended attributes");
     806                    } else {
     807                        log_msg(1, "I set xattr OK");
     808                    }
     809                    retval += res;
     810                }
     811            }
     812            if (g_getfacl) {
     813                log_msg(1, "Setting acl list %s", acl_fname);
     814                if (length_of_file(acl_fname) > 0) {
     815                    res = set_acl_list(filelist_subset_fname, acl_fname);
     816                    if (res) {
     817                        log_to_screen("Errors occurred while setting access control lists");
     818                    } else {
     819                        log_msg(1, "I set ACL OK");
     820                    }
     821                    retval += res;
     822                }
     823            }
     824        } else {
     825            retval = res;
     826        }
     827        // Be verbose for star
     828        if (retval || use_star) {
     829            mr_asprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
     830            paranoid_system(command);
     831            paranoid_free(command);
     832
     833            if (retval) {
     834                log_msg(2, "Errors occurred while processing fileset #%d", current_tarball_number);
     835            }
     836        } else {
     837            log_msg(2, "Fileset #%d processed OK", current_tarball_number);
     838        }
     839        unlink(temp_log);
     840        mr_free(temp_log);
     841    }
     842    if (does_file_exist("/PAUSE")) {
     843        popup_and_OK
     844            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     845    }
     846    unlink(filelist_subset_fname);
     847    mr_free(filelist_subset_fname);
     848    if (g_getfattr) {
     849        unlink(xattr_fname);
     850        mr_free(xattr_fname);
     851    }
     852    if (g_getfacl) {
     853        unlink(acl_fname);
     854        mr_free(acl_fname);
     855    }
     856
     857    log_msg(5, "Leaving");
     858    return (retval);
     859}
     860
     861/**************************************************************************
     862 *END_RESTORE_A_TARBALL_FROM_CD                                           *
     863 **************************************************************************/
     864
     865
     866
     867/**
     868 * Restore all afioballs from all CDs in the backup.
     869 * The first CD should be inserted (if not, it will be asked for).
     870 * @param bkpinfo The backup information structure. @c backup_media_type is the
     871 * only field used in @e this function.
     872 * @param filelist The node structure containing the list of files to be
     873 * restored. If no file in some particular afioball is in this list, afio will
     874 * still be called for that fileset, but nothing will be written.
     875 * @return 0 for success, or the number of filesets that failed.
     876 */
     877int
     878restore_all_tarballs_from_CD(struct s_node *filelist)
     879{
     880    int retval = 0;
     881    int res;
     882    int attempts;
     883    long current_tarball_number = 0L;
     884    long max_val;
     885  /**malloc ***/
     886    char *mds = NULL;
     887    char *tmp = NULL;
     888    char *tmp1 = NULL;
     889    char *tarball_fname = NULL;
     890    char *progress_str = NULL;
     891
     892    assert(bkpinfo != NULL);
     893
     894    malloc_string(tmp);
     895    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
     896    log_msg(2, "Insisting on 1st media, so that I can have a look at LAST-FILELIST-NUMBER");
     897    if (g_current_media_number != 1) {
     898        log_msg(3, "OK, that's jacked up.");
     899        g_current_media_number = 1;
     900    }
     901    insist_on_this_cd_number(g_current_media_number);
     902    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
     903    max_val = atol(tmp) + 1;
     904    paranoid_free(tmp);
     905
     906    mds = media_descriptor_string(bkpinfo->backup_media_type);
     907    mr_asprintf(progress_str, "Restoring from %s #%d", mds, g_current_media_number);
     908
     909    log_to_screen(progress_str);
     910    open_progress_form("Restoring from archives",
     911                       "Restoring data from the archives.",
     912                       "Please wait. This may take some time.",
     913                       progress_str, max_val);
     914    for (;;) {
     915        insist_on_this_cd_number(g_current_media_number);
     916        update_progress_form(progress_str);
     917        mr_free(progress_str);
     918
     919        mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2", current_tarball_number);
     920        if (!does_file_exist(tarball_fname)) {
     921            mr_free(tarball_fname);
     922            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz", current_tarball_number);
     923        }
     924        if (!does_file_exist(tarball_fname)) {
     925            mr_free(tarball_fname);
     926            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzma", current_tarball_number);
     927        }
     928        if (!does_file_exist(tarball_fname)) {
     929            mr_free(tarball_fname);
     930            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo", current_tarball_number);
     931        }
     932        if (!does_file_exist(tarball_fname)) {
     933            mr_free(tarball_fname);
     934            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.", current_tarball_number);
     935        }
     936        if (!does_file_exist(tarball_fname)) {
     937            mr_free(tarball_fname);
     938            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2", current_tarball_number);
     939        }
     940        if (!does_file_exist(tarball_fname)) {
     941            mr_free(tarball_fname);
     942            mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.", current_tarball_number);
     943        }
     944        if (!does_file_exist(tarball_fname)) {
     945            if (current_tarball_number == 0) {
     946                log_to_screen
     947                    ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
     948                mr_free(tarball_fname);
     949                return (0);
     950            }
     951            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
     952                || system("find " MNT_CDROM
     953                          "/archives/slice* > /dev/null 2> /dev/null") ==
     954                0) {
     955                break;
     956            }
     957            g_current_media_number++;
     958            mr_asprintf(progress_str, "Restoring from %s #%d", media_descriptor_string(bkpinfo->backup_media_type), g_current_media_number);
     959            log_to_screen(progress_str);
     960        } else {
     961            mr_asprintf(progress_str, "Restoring from fileset #%ld on %s #%d", current_tarball_number, mds, g_current_media_number);
     962            for (res = 999, attempts = 0; attempts < 3 && res != 0; attempts++) {
     963                res = restore_a_tarball_from_CD(tarball_fname, current_tarball_number, filelist);
     964            }
     965            mr_asprintf(tmp1, "%s #%d, fileset #%ld - restore ", mds, g_current_media_number, current_tarball_number);
     966            if (res) {
     967                mr_strcat(tmp1, "reported errors");
     968            } else if (attempts > 1) {
     969                mr_strcat(tmp1, "succeeded");
     970            } else {
     971                mr_strcat(tmp1, "succeeded");
     972            }
     973            if (attempts > 1) {
     974                mr_strcat(tmp1, " (%d attempts) - review logs", attempts);
     975            }
     976            if (attempts > 1) {
     977                log_to_screen(tmp1);
     978            }
     979            mr_free(tmp1);
     980
     981            retval += res;
     982            current_tarball_number++;
     983            g_current_progress++;
     984        }
     985        mr_free(tarball_fname);
     986
     987        /* Now we need to umount the current media to have the next mounted by insist_on_this_cd_number */
     988        /*   run_program_and_log_output("umount " MNT_CDROM, FALSE); */
     989    }
     990    mr_free(mds);
     991    mr_free(progress_str);
     992
     993    close_progress_form();
     994    if (retval) {
     995        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     996    } else {
     997        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     998    }
     999
     1000    return (retval);
     1001}
     1002
     1003/**************************************************************************
     1004 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
     1005 **************************************************************************/
     1006
     1007
     1008/**
     1009 * Restore a biggiefile from the currently opened stream.
     1010 * @param bkpinfo The backup information structure. Fields used:
     1011 * - @c bkpinfo->restore_path
     1012 * - @c bkpinfo->zip_exe
     1013 * @param orig_bf_fname The original filename of the biggiefile.
     1014 * @param biggiefile_number The number of the biggiefile (starting from 0).
     1015 * @param orig_checksum Unused.
     1016 * @param biggiefile_size Unused.
     1017 * @param filelist The node structure containing the list of files to be restored.
     1018 * If @p orig_bf_fname is not in the list, it will be ignored.
     1019 * @return 0 for success (or skip), nonzero for failure.
     1020 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
     1021 */
     1022int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
     1023                                     long long biggiefile_size, //UNUSED
     1024                                     struct s_node *filelist,
     1025                                     int use_ntfsprog,
     1026                                     char *pathname_of_last_file_restored)
     1027{
     1028    FILE *pout;
     1029    FILE *fin;
     1030
     1031  /** mallocs ********/
     1032    char *tmp = NULL;
     1033    char *tmp1 = NULL;
     1034    char *command = NULL;
     1035    char *outfile_fname = NULL;
     1036    char *sz_devfile = NULL;
     1037    char *ntfsprog_fifo = NULL;
     1038    char *file_to_openout = NULL;
     1039
     1040    struct s_node *node;
     1041
     1042    int old_loglevel;
     1043    long current_slice_number = 0;
     1044    int retval = 0;
     1045    int res = 0;
     1046    int ctrl_chr = '\0';
     1047    long long slice_siz;
     1048    bool dummy_restore = FALSE;
     1049    bool use_ntfsprog_hack = FALSE;
     1050    pid_t pid;
     1051    struct s_filename_and_lstat_info biggiestruct;
     1052    struct utimbuf the_utime_buf, *ubuf;
     1053    ubuf = &the_utime_buf;
     1054
     1055    malloc_string(tmp);
     1056    old_loglevel = g_loglevel;
     1057    assert(bkpinfo != NULL);
     1058    assert(orig_bf_fname != NULL);
     1059    assert(orig_checksum != NULL);
     1060
     1061    pathname_of_last_file_restored[0] = '\0';
     1062    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
     1063        use_ntfsprog = 1;
     1064        log_msg(1, "%s --- pih=YES", orig_bf_fname);
     1065    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
     1066        use_ntfsprog = 0;
     1067        log_msg(1, "%s --- pih=NO", orig_bf_fname);
     1068    } else {
     1069        use_ntfsprog = 0;
     1070        log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
     1071    }
     1072
     1073    strncpy(pathname_of_last_file_restored, orig_bf_fname,
     1074            MAX_STR_LEN - 1);
     1075    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
     1076
     1077    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
     1078
     1079    if (filelist != NULL) {
     1080        node = find_string_at_node(filelist, orig_bf_fname);
     1081        if (!node) {
     1082            dummy_restore = TRUE;
     1083            log_msg(1,
     1084                    "Skipping big file %ld (%s) - not in biggielist subset",
     1085                    biggiefile_number + 1, orig_bf_fname);
     1086            pathname_of_last_file_restored[0] = '\0';
     1087        } else if (!(node->selected)) {
     1088            dummy_restore = TRUE;
     1089            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
     1090                    orig_bf_fname);
     1091            pathname_of_last_file_restored[0] = '\0';
     1092        }
     1093    }
     1094
     1095    if (use_ntfsprog) {
     1096        if (strncmp(orig_bf_fname, "/dev/", 5)) {
     1097            log_msg(1,
     1098                    "I was in error when I set use_ntfsprog to TRUE.");
     1099            log_msg(1, "%s isn't even in /dev", orig_bf_fname);
     1100            use_ntfsprog = FALSE;
     1101        }
     1102    }
     1103
     1104    if (use_ntfsprog) {
     1105        g_loglevel = 4;
     1106        mr_asprintf(outfile_fname, "%s", orig_bf_fname);
     1107        use_ntfsprog_hack = TRUE;
     1108        log_msg(2, "Calling ntfsclone in background because %s is a /dev entry", outfile_fname);
     1109        mr_asprintf(sz_devfile, "%s/%d.%d.000", bkpinfo->tmpdir, (int) (random() % 32768), (int) (random() % 32768));
     1110        mkfifo(sz_devfile, 0x770);
     1111        mr_asprintf(ntfsprog_fifo, "%s", sz_devfile);
     1112        mr_free(sz_devfile);
     1113
     1114        file_to_openout = ntfsprog_fifo;
     1115        switch (pid = fork()) {
     1116        case -1:
     1117            fatal_error("Fork failure");
     1118        case 0:
     1119            log_msg(3, "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)", outfile_fname, ntfsprog_fifo);
     1120            res = feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
     1121            mr_free(ntfsprog_fifo);
     1122            exit(res);
     1123            break;
     1124        default:
     1125            log_msg(3, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid));
     1126        }
     1127        mr_free(ntfsprog_fifo);
     1128    } else {
     1129        if (!strncmp(orig_bf_fname, "/dev/", 5))    {
     1130            // non-NTFS partition
     1131            mr_asprintf(outfile_fname, "%s", orig_bf_fname);
     1132        } else {
     1133            // biggiefile
     1134            mr_asprintf(outfile_fname, "%s/%s", bkpinfo->restore_path, orig_bf_fname);
     1135        }
     1136        use_ntfsprog_hack = FALSE;
     1137        file_to_openout = outfile_fname;
     1138        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
     1139        {
     1140            make_hole_for_file(outfile_fname);
     1141        }
     1142        log_msg(2, "Reassembling big file %ld (%s)", biggiefile_number + 1, orig_bf_fname);
     1143    }
     1144
     1145    if (dummy_restore) {
     1146        mr_free(outfile_fname);
     1147        mr_asprintf(outfile_fname, "/dev/null");
     1148    }
     1149
     1150    if (!bkpinfo->zip_exe[0]) {
     1151        mr_asprintf(command, "cat > \"%s\"", file_to_openout);
     1152    } else {
     1153        mr_asprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe, file_to_openout, MONDO_LOGFILE);
     1154        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
     1155            /* Ignore SIGPIPE for gzip as it causes errors on big files
     1156             * Cf: http://trac.mondorescue.org/ticket/244 */
     1157            signal(SIGPIPE,SIG_IGN);
     1158        }
     1159    }
     1160    log_msg(3, "Pipe command = '%s'", command);
     1161
     1162    /* restore biggiefile, one slice at a time */
     1163    if (!(pout = popen(command, "w"))) {
     1164        fatal_error("Cannot pipe out");
     1165    }
     1166    mr_free(command);
     1167
     1168    for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
     1169         ctrl_chr != BLK_STOP_A_BIGGIE;
     1170         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
     1171        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     1172            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     1173        }
     1174        log_msg(2, "Working on file #%ld, slice #%ld    ", biggiefile_number + 1, current_slice_number);
     1175        if (!g_text_mode) {
     1176            newtDrawRootText(0, g_noof_rows - 2, tmp);
     1177            newtRefresh();
     1178        }
     1179        strip_spaces(tmp);
     1180        update_progress_form(tmp);
     1181        if (current_slice_number == 0) {
     1182            res =
     1183                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
     1184                                              slice_siz);
     1185            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
     1186                log_OS_error("blah blah");
     1187            } else {
     1188                if (fread
     1189                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
     1190                     fin) < sizeof(biggiestruct)) {
     1191                    log_msg(2,
     1192                            "Warning - unable to get biggiestruct of bigfile #%d",
     1193                            biggiefile_number + 1);
     1194                }
     1195                paranoid_fclose(fin);
     1196            }
     1197        } else {
     1198            res =
     1199                read_file_from_stream_to_stream(pout, slice_siz);
     1200        }
     1201        retval += res;
     1202        res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
     1203        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
     1204            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
     1205        }
     1206        current_slice_number++;
     1207        g_current_progress++;
     1208    }
     1209    paranoid_pclose(pout);
     1210
     1211    if (bkpinfo->zip_exe[0]) {
     1212        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
     1213            /* Re-enable SIGPIPE for gzip */
     1214            signal(SIGPIPE, terminate_daemon);
     1215        }
     1216    }
     1217
     1218    log_msg(1, "pathname_of_last_file_restored is now %s",
     1219            pathname_of_last_file_restored);
     1220
     1221    if (use_ntfsprog_hack) {
     1222        log_msg(3, "Waiting for ntfsclone to finish");
     1223        mr_asprintf(tmp1, " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
     1224        while (system(tmp1) == 0) {
     1225            sleep(1);
     1226        }
     1227        mr_free(tmp1);
     1228        log_msg(3, "OK, ntfsclone has really finished");
     1229    }
     1230
     1231    log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
     1232    log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
     1233    if (strcmp(outfile_fname, "/dev/null")) {
     1234        chmod(outfile_fname, biggiestruct.properties.st_mode);
     1235        if (chown(outfile_fname, biggiestruct.properties.st_uid, biggiestruct.properties.st_gid)) {
     1236            // FIXME
     1237        }
     1238        ubuf->actime = biggiestruct.properties.st_atime;
     1239        ubuf->modtime = biggiestruct.properties.st_mtime;
     1240        utime(outfile_fname, ubuf);
     1241    }
     1242    mr_free(outfile_fname);
     1243
     1244    paranoid_free(tmp);
     1245    g_loglevel = old_loglevel;
     1246    return (retval);
     1247}
     1248
     1249/**************************************************************************
     1250 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
     1251 **************************************************************************/
     1252
     1253
     1254
     1255/**
     1256 * Restore all biggiefiles from the currently opened stream.
     1257 * @param bkpinfo The backup information structure. Passed to other functions.
     1258 * @param filelist The node structure containing the list of files to be
     1259 * restored. If a prospective biggiefile is not in the list, it will be ignored.
     1260 * @return 0 for success, or the number of biggiefiles that failed.
     1261 */
     1262int
     1263restore_all_biggiefiles_from_stream(struct s_node *filelist)
     1264{
     1265    long noof_biggiefiles;
     1266    long current_bigfile_number = 0;
     1267    long total_slices;
     1268
     1269    int retval = 0;
     1270    int res = 0;
     1271    int ctrl_chr;
     1272
     1273  /** malloc add ****/
     1274    char *tmp = NULL;
     1275    char *tmp1 = NULL;
     1276    char *biggie_fname;
     1277    char *biggie_cksum;
     1278    char *xattr_fname = NULL;
     1279    char *acl_fname = NULL;
     1280    char *p;
     1281    char *pathname_of_last_biggie_restored;
     1282    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
     1283    long long biggie_size;
     1284    FILE *fbw = NULL;
     1285
     1286    malloc_string(tmp);
     1287    malloc_string(biggie_fname);
     1288    malloc_string(biggie_cksum);
     1289    malloc_string(pathname_of_last_biggie_restored);
     1290    assert(bkpinfo != NULL);
     1291
     1292    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
     1293
     1294    total_slices = atol(tmp);
     1295
     1296    if (g_getfattr) {
     1297        mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     1298    }
     1299    if (g_getfacl) {
     1300        mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     1301    }
     1302    mr_asprintf(tmp1, "Reassembling large files      ");
     1303    mvaddstr_and_log_it(g_currentY, 0, tmp1);
     1304    mr_free(tmp1);
     1305
     1306    mr_asprintf(biggies_whose_EXATs_we_should_set, "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
     1307    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
     1308        log_msg(1, "Warning - cannot openout %s", biggies_whose_EXATs_we_should_set);
     1309    }
     1310
     1311    // get xattr and acl files if they're there
     1312    res = read_header_block_from_stream(&biggie_size, biggie_fname, &ctrl_chr);
     1313    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
     1314        res = read_EXAT_files_from_tape(&biggie_size, biggie_fname, &ctrl_chr, xattr_fname, acl_fname);
     1315    }
     1316
     1317    noof_biggiefiles = atol(biggie_fname);
     1318    log_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
     1319    open_progress_form("Reassembling large files",
     1320                       "I am now reassembling all the large files.",
     1321                       "Please wait. This may take some time.",
     1322                       "", total_slices);
     1323
     1324    for (res =
     1325         read_header_block_from_stream(&biggie_size, biggie_fname,
     1326                                       &ctrl_chr);
     1327         ctrl_chr != BLK_STOP_BIGGIEFILES;
     1328         res =
     1329         read_header_block_from_stream(&biggie_size, biggie_fname,
     1330                                       &ctrl_chr)) {
     1331        if (ctrl_chr != BLK_START_A_NORMBIGGIE
     1332            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
     1333            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
     1334        }
     1335        p = strrchr(biggie_fname, '/');
     1336        if (!p) {
     1337            p = biggie_fname;
     1338        } else {
     1339            p++;
     1340        }
     1341        mr_asprintf(tmp1, "Restoring big file %ld (%lld K)", current_bigfile_number + 1, biggie_size / 1024);
     1342        update_progress_form(tmp1);
     1343        mr_free(tmp1);
     1344        res = restore_a_biggiefile_from_stream(biggie_fname,
     1345                                               current_bigfile_number,
     1346                                               biggie_cksum,
     1347                                               biggie_size,
     1348                                               filelist, ctrl_chr,
     1349                                               pathname_of_last_biggie_restored);
     1350        log_msg(1, "I believe I have restored %s",
     1351                pathname_of_last_biggie_restored);
     1352        if (fbw && pathname_of_last_biggie_restored[0]) {
     1353            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
     1354        }
     1355        retval += res;
     1356        current_bigfile_number++;
     1357
     1358    }
     1359    if (current_bigfile_number != noof_biggiefiles
     1360        && noof_biggiefiles != 0) {
     1361        log_msg(1, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n", current_bigfile_number, noof_biggiefiles);
     1362    } else {
     1363        log_msg(1, "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.", noof_biggiefiles, current_bigfile_number);
     1364    }
     1365
     1366    if (fbw) {
     1367        fclose(fbw);
     1368        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
     1369            log_it("Setting biggie-EXATs");
     1370            if (g_getfattr) {
     1371                if (length_of_file(xattr_fname) > 0) {
     1372                    log_msg(1, "set_fattr_List(%s,%s)", biggies_whose_EXATs_we_should_set, xattr_fname);
     1373                    set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
     1374                }
     1375            }
     1376            if (g_getfacl) {
     1377                if (length_of_file(acl_fname) > 0) {
     1378                    log_msg(1, "set_acl_list(%s,%s)", biggies_whose_EXATs_we_should_set, acl_fname);
     1379                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
     1380                }
     1381            }
     1382        } else {
     1383            log_it("No biggiefiles selected. So, no biggie-EXATs to set.");
     1384        }
     1385    }
     1386    mr_free(xattr_fname);
     1387    mr_free(acl_fname);
     1388    mr_free(biggies_whose_EXATs_we_should_set);
     1389
     1390    if (does_file_exist("/PAUSE")) {
     1391        popup_and_OK
     1392            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
     1393    }
     1394
     1395    close_progress_form();
     1396    if (retval) {
     1397        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     1398    } else {
     1399        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     1400    }
     1401    paranoid_free(pathname_of_last_biggie_restored);
     1402    paranoid_free(biggie_fname);
     1403    paranoid_free(biggie_cksum);
     1404    paranoid_free(tmp);
     1405    return (retval);
     1406}
     1407
     1408/**************************************************************************
     1409 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
     1410 **************************************************************************/
     1411
     1412
     1413
     1414
     1415/**
     1416 * Restore a tarball from the currently opened stream.
     1417 * @param bkpinfo The backup information structure. Fields used:
     1418 * - @c bkpinfo->backup_media_type
     1419 * - @c bkpinfo->media_device
     1420 * - @c bkpinfo->zip_exe
     1421 * @param tarball_fname The filename of the afioball to restore.
     1422 * @param current_tarball_number The number (starting from 0) of the fileset
     1423 * we're restoring now.
     1424 * @param filelist The node structure containing the list of files to be
     1425 * restored. If no file in the afioball is in this list, afio will still be
     1426 * called, but nothing will be written.
     1427 * @param size The size (in @b bytes) of the afioball.
     1428 * @return 0 for success, nonzero for failure.
     1429 */
     1430int
     1431restore_a_tarball_from_stream(char *tarball_fname,
     1432                              long current_tarball_number,
     1433                              struct s_node *filelist,
     1434                              long long size, char *xattr_fname,
     1435                              char *acl_fname)
     1436{
     1437    int retval = 0;
     1438    int res = 0;
     1439
     1440  /** malloc add ***/
     1441    char *mds = NULL;
     1442    char *command = NULL;
     1443    char *afio_fname = NULL;
     1444    char *filelist_fname = NULL;
     1445    char *filelist_subset_fname = NULL;
     1446    char *executable = NULL;
     1447    long matches = 0;
     1448    bool restore_this_fileset = FALSE;
     1449    bool use_star;
     1450
     1451    assert(bkpinfo != NULL);
     1452    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
     1453
     1454    /* to do it with a file... */
     1455    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
     1456    mds = media_descriptor_string(bkpinfo->backup_media_type);
     1457    log_msg(2, "Restoring from fileset #%ld (%ld KB) on %s #%d",
     1458            current_tarball_number, (long) size >> 10, mds, g_current_media_number);
     1459    mr_free(mds);
     1460
     1461    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
     1462
     1463  /****************************************************************************
     1464   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
     1465   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
     1466   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
     1467   ****************************************************************************/
     1468    mr_asprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld", current_tarball_number);
     1469    mr_asprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir, current_tarball_number);
     1470    mr_asprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp", bkpinfo->tmpdir, current_tarball_number);
     1471
     1472    res = read_file_from_stream_to_file(afio_fname, size);
     1473    if (strstr(tarball_fname, ".star")) {
     1474        bkpinfo->use_star = TRUE;
     1475    }
     1476    if (res) {
     1477        log_msg(1, "Warning - error reading afioball from tape");
     1478    }
     1479    if (bkpinfo->compression_level == 0) {
     1480        mr_asprintf(executable, "%s", "");
     1481    } else {
     1482        if (bkpinfo->use_star) {
     1483            mr_asprintf(executable, "%s", " -bz");
     1484        } else {
     1485            mr_asprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
     1486        }
     1487    }
     1488
     1489    if (!filelist)              // if unconditional restore then restore entire fileset
     1490    {
     1491        restore_this_fileset = TRUE;
     1492    } else                      // If restoring selectively then get TOC from tarball
     1493    {
     1494        if (strstr(tarball_fname, ".star.")) {
     1495            use_star = TRUE;
     1496            mr_asprintf(command, "star -sparse -t file=%s %s", afio_fname, executable);
     1497        } else {
     1498            use_star = FALSE;
     1499            mr_asprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE, executable, afio_fname);
     1500        }
     1501        mr_strcat(command, " > %s 2>> %s", filelist_fname, MONDO_LOGFILE);
     1502        log_msg(1, "command = %s", command);
     1503        if (system(command)) {
     1504            log_msg(4, "Warning - error occurred while retrieving TOC");
     1505        }
     1506        mr_free(command);
     1507
     1508        if ((matches =
     1509             save_filelist_entries_in_common(filelist_fname, filelist,
     1510                                             filelist_subset_fname,
     1511                                             use_star))
     1512            <= 0 || length_of_file(filelist_subset_fname) < 2) {
     1513            if (length_of_file(filelist_subset_fname) < 2) {
     1514                log_msg(1, "No matches found in fileset %ld",
     1515                        current_tarball_number);
     1516            }
     1517            log_msg(2, "Skipping fileset %ld", current_tarball_number);
     1518            restore_this_fileset = FALSE;
     1519        } else {
     1520            log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
     1521                    matches, current_tarball_number,
     1522                    filelist_subset_fname);
     1523            restore_this_fileset = TRUE;
     1524        }
     1525    }
     1526
     1527// Concoct the call to star/afio to restore files
     1528    if (strstr(tarball_fname, ".star.")) {
     1529        // star
     1530        mr_asprintf(command, "star -sparse -x file=%s %s", afio_fname, executable);
     1531        if (filelist) {
     1532            mr_strcat(command, " list=%s", filelist_subset_fname);
     1533        }
     1534    } else {
     1535        // afio
     1536        mr_asprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE, executable);
     1537        if (filelist) {
     1538            mr_strcat(command, " -w %s", filelist_subset_fname);
     1539        }
     1540        mr_strcat(command, " %s", afio_fname);
     1541    }
     1542    mr_strcat(command, " 2>> %s", MONDO_LOGFILE);
     1543    mr_free(executable);
     1544
     1545// Call if IF there are files to restore (selectively/unconditionally)
     1546    if (restore_this_fileset) {
     1547        log_msg(1, "Calling command='%s'", command);
     1548        paranoid_system(command);
     1549
     1550        if (g_getfattr) {
     1551            log_it("Restoring xattr stuff");
     1552            res = set_fattr_list(filelist_subset_fname, xattr_fname);
     1553            if (res) {
     1554                log_msg(1, "Errors occurred while setting xattr");
     1555            } else {
     1556                log_msg(1, "I set xattr OK");
     1557            }
     1558            retval += res;
     1559        }
     1560
     1561        if (g_getfacl) {
     1562            log_it("Restoring acl stuff");
     1563            res = set_acl_list(filelist_subset_fname, acl_fname);
     1564            if (res) {
     1565                log_msg(1, "Errors occurred while setting ACL");
     1566            } else {
     1567                log_msg(1, "I set ACL OK");
     1568            }
     1569            retval += res;
     1570        }
     1571
     1572    } else {
     1573        log_msg(1, "NOT CALLING '%s'", command);
     1574    }
     1575    mr_free(command);
     1576
     1577    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
     1578        log_to_screen("Paused after set %ld", current_tarball_number);
     1579        popup_and_OK("Pausing. Press ENTER to continue.");
     1580    }
     1581
     1582    unlink(filelist_subset_fname);
     1583    mr_free(filelist_subset_fname);
     1584    unlink(filelist_fname);
     1585    mr_free(filelist_fname);
     1586    unlink(afio_fname);
     1587    mr_free(afio_fname);
     1588
     1589    return (retval);
     1590}
     1591
     1592/**************************************************************************
     1593 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
     1594 **************************************************************************/
     1595
     1596
     1597
     1598
     1599
     1600/**
     1601 * Restore all afioballs from the currently opened tape stream.
     1602 * @param bkpinfo The backup information structure. Fields used:
     1603 * - @c bkpinfo->backup_media_type
     1604 * - @c bkpinfo->restore_path
     1605 * @param filelist The node structure containing the list of files to be
     1606 * restored. If no file in an afioball is in this list, afio will still be
     1607 * called for that fileset, but nothing will be written.
     1608 * @return 0 for success, or the number of filesets that failed.
     1609 */
     1610int restore_all_tarballs_from_stream(struct s_node *filelist)
     1611{
     1612    int retval = 0;
     1613    int res;
     1614    long current_afioball_number = 0;
     1615    int ctrl_chr;
     1616    long max_val /*, total_noof_files */ ;
     1617
     1618  /** malloc **/
     1619    char *tmp = NULL;
     1620    char *mds = NULL;
     1621    char *progress_str = NULL;
     1622    char *tmp_fname;
     1623    char *xattr_fname = NULL;
     1624    char *acl_fname = NULL;
     1625
     1626    long long tmp_size;
     1627
     1628    malloc_string(tmp);
     1629    malloc_string(tmp_fname);
     1630    assert(bkpinfo != NULL);
     1631    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
     1632    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
     1633    max_val = atol(tmp) + 1;
     1634
     1635    if (chdir(bkpinfo->restore_path)) { /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
     1636        //FIXME
     1637    }
     1638
     1639    run_program_and_log_output("pwd", 5);
     1640
     1641    mr_asprintf(progress_str, "Restoring from media #%d", g_current_media_number);
     1642    log_to_screen(progress_str);
     1643    open_progress_form("Restoring from archives",
     1644                       "Restoring data from the archives.",
     1645                       "Please wait. This may take some time.",
     1646                       progress_str, max_val);
     1647
     1648    log_msg(3, "hey");
     1649
     1650    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     1651    if (res) {
     1652        log_msg(2, "Warning - error reading afioball from tape");
     1653    }
     1654    retval += res;
     1655    if (ctrl_chr != BLK_START_AFIOBALLS) {
     1656        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
     1657    }
     1658    log_msg(2, "ho");
     1659    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     1660    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
     1661        update_progress_form(progress_str);
     1662        if (g_getfattr) {
     1663            mr_asprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir, current_afioball_number);
     1664            unlink(xattr_fname);
     1665        }
     1666        if (g_getfacl) {
     1667            mr_asprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir, current_afioball_number);
     1668            unlink(acl_fname);
     1669        }
     1670        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
     1671            log_it("Reading EXAT files from tape");
     1672            res = read_EXAT_files_from_tape(&tmp_size, tmp_fname, &ctrl_chr, xattr_fname, acl_fname);
     1673        }
     1674        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     1675            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     1676        }
     1677        log_msg(4, "Restoring from fileset #%ld (name=%s, size=%ld K)", current_afioball_number, tmp_fname, (long) tmp_size >> 10);
     1678        res = restore_a_tarball_from_stream(tmp_fname, current_afioball_number, filelist, tmp_size, xattr_fname, acl_fname);
     1679        retval += res;
     1680        if (res) {
     1681            log_to_screen("Fileset %ld - errors occurred", current_afioball_number);
     1682        }
     1683        res =
     1684            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     1685        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
     1686            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
     1687        }
     1688
     1689        current_afioball_number++;
     1690        g_current_progress++;
     1691        mds = media_descriptor_string(bkpinfo->backup_media_type),
     1692
     1693        mr_free(progress_str);
     1694        mr_asprintf(progress_str, "Restoring from fileset #%ld on %s #%d", current_afioball_number, mds, g_current_media_number);
     1695        mr_free(mds);
     1696        res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
     1697        if (g_getfattr) {
     1698            unlink(xattr_fname);
     1699        }
     1700        if (g_getfacl) {
     1701            unlink(acl_fname);
     1702        }
     1703    }                           // next
     1704    mr_free(progress_str);
     1705    if (g_getfattr) {
     1706        mr_free(xattr_fname);
     1707    }
     1708    if (g_getfacl) {
     1709        mr_free(acl_fname);
     1710    }
     1711
     1712    log_msg(1, "All done with afioballs");
     1713    close_progress_form();
     1714    if (retval) {
     1715        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     1716    } else {
     1717        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     1718    }
     1719    paranoid_free(tmp);
     1720    paranoid_free(tmp_fname);
     1721    return (retval);
     1722}
     1723
     1724/**************************************************************************
     1725 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
     1726 **************************************************************************/
     1727
     1728/* @} - end of LLrestoreGroup */
     1729
     1730
     1731/**
     1732 * Restore all files in @p filelist.
     1733 * @param bkpinfo The backup information structure. Most fields are used.
     1734 * @param filelist The node structure containing the list of files to be
     1735 * restored.
     1736 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
     1737 * @ingroup restoreGroup
     1738 */
     1739int restore_everything(struct s_node *filelist)
     1740{
     1741    int resA;
     1742    int resB;
     1743
     1744  /** mallco ***/
     1745    char *cwd;
     1746    char *newpath;
     1747    char *tmp = NULL;
     1748    assert(bkpinfo != NULL);
     1749
     1750    malloc_string(cwd);
     1751    malloc_string(newpath);
     1752    log_msg(2, "restore_everything() --- starting");
     1753    g_current_media_number = 1;
     1754    if (getcwd(cwd, MAX_STR_LEN - 1)) {
     1755        // FIXME
     1756    }
     1757    mr_asprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
     1758    run_program_and_log_output(tmp, FALSE);
     1759    mr_free(tmp);
     1760
     1761    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
     1762    if (chdir(bkpinfo->restore_path)) {
     1763        //FIXME
     1764    }
     1765    if (getcwd(newpath, MAX_STR_LEN - 1)) {
     1766        // FIXME
     1767    }
     1768    log_msg(1, "path is now %s", newpath);
     1769    log_msg(1, "restoring everything");
     1770    if (!find_home_of_exe("petris") && !g_text_mode) {
     1771        newtDrawRootText(0, g_noof_rows - 2,
     1772                         "Press ALT-<left cursor> twice to play Petris :-) ");
     1773        newtRefresh();
     1774    }
     1775    mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
     1776    mount_media();
     1777    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     1778        mvaddstr_and_log_it(g_currentY++, 0,
     1779                            "Restoring OS and data from streaming media");
     1780        if (bkpinfo->backup_media_type == cdstream) {
     1781            openin_cdstream();
     1782        } else {
     1783            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
     1784            openin_tape();
     1785        }
     1786        resA = restore_all_tarballs_from_stream(filelist);
     1787        resB = restore_all_biggiefiles_from_stream(filelist);
     1788        if (bkpinfo->backup_media_type == cdstream) {
     1789            closein_cdstream();
     1790        } else {
     1791            closein_tape();
     1792        }
     1793    } else {
     1794        mvaddstr_and_log_it(g_currentY++, 0,
     1795                            "Restoring OS and data from CD/USB   ");
     1796        resA = restore_all_tarballs_from_CD(filelist);
     1797        resB = restore_all_biggiefiles_from_CD(filelist);
     1798    }
     1799    if (chdir(cwd)) {
     1800        //FIXME
     1801    }
     1802    if (resA + resB) {
     1803        log_to_screen("Errors occurred while data was being restored.");
     1804    }
     1805    if (length_of_file("/etc/raidtab") > 0) {
     1806        log_msg(2, "Copying local raidtab to restored filesystem");
     1807        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
     1808                                   "/etc/raidtab", FALSE);
     1809    }
     1810    kill_petris();
     1811    log_msg(2, "restore_everything() --- leaving");
     1812    paranoid_free(cwd);
     1813    paranoid_free(newpath);
     1814    return (resA + resB);
     1815}
     1816
     1817/**************************************************************************
     1818 *END_RESTORE_EVERYTHING                                                  *
     1819 **************************************************************************/
    4041820
    4051821
     
    6612077
    6622078/**
    663  * Run an arbitrary restore mode (prompt the user), but from ISO images
    664  * instead of real media.
    665  * @param mountlist The mountlist containing information about the user's partitions.
    666  * @param raidlist The raidlist that goes with @p mountlist.
    667  * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
    668  * @return 0 for success, or the number of errors encountered.
    669  */
    670 int
    671 iso_mode(struct mountlist_itself *mountlist,
    672          struct raidlist_itself *raidlist, bool nuke_me_please)
    673 {
    674     char c;
    675     int retval = 0;
    676 
    677     assert(mountlist != NULL);
    678     assert(raidlist != NULL);
    679     if (iso_fiddly_bits(nuke_me_please)) {
    680         log_msg(1, "iso_mode --- returning w/ error");
    681         return (1);
    682     } else {
    683         c = which_restore_mode();
    684         if (c == 'I' || c == 'N' || c == 'C') {
    685             interactively_obtain_media_parameters_from_user(FALSE);
    686         }
    687         if (c == 'I') {
    688             retval += interactive_mode(mountlist, raidlist);
    689         } else if (c == 'N') {
    690             retval += nuke_mode(mountlist, raidlist);
    691         } else if (c == 'C') {
    692             retval += compare_mode(mountlist, raidlist);
    693         } else {
    694             log_to_screen("OK, I shan't restore/compare any files.");
    695         }
    696     }
    697     if (is_this_device_mounted(MNT_CDROM)) {
    698         paranoid_system("umount -d " MNT_CDROM);
    699     }
    700 //  if (! already_mounted)
    701 //    {
    702     if (system("umount -d /tmp/isodir 2> /dev/null")) {
    703         log_to_screen("WARNING - unable to unmount device where the ISO files are stored.");
    704     }
    705 //    }
    706     return (retval);
    707 }
    708 
    709 /**************************************************************************
    710  *END_ISO_MODE                                                            *
    711  **************************************************************************/
    712 
    713 
    714 /*            MONDO - saving your systems since Feb 18th, 2000            */
    715 
    716 
    717 
    718 
    719 /**
    7202079 * Restore the user's data automatically (no prompts), after a twenty-second
    7212080 * warning period.
     
    8702229
    8712230/**
     2231 * Allow the user to modify the mountlist before we partition & format their drives.
     2232 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
     2233 * @param mountlist The mountlist to let the user modify.
     2234 * @param raidlist The raidlist that goes with @p mountlist.
     2235 * @return 0 for success, nonzero for failure.
     2236 * @ingroup restoreGuiGroup
     2237 */
     2238int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
     2239                                struct raidlist_itself *raidlist)
     2240{
     2241    int retval = 0, res = 0;
     2242
     2243    log_msg(2, "let_user_edit_the_mountlist() --- starting");
     2244
     2245    assert(bkpinfo != NULL);
     2246    assert(mountlist != NULL);
     2247    assert(raidlist != NULL);
     2248    if (!bkpinfo->disaster_recovery) {
     2249        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
     2250        log_msg(2, "I guess you're testing edit_mountlist()");
     2251    }
     2252    if (!does_file_exist(g_mountlist_fname)) {
     2253        log_to_screen(g_mountlist_fname);
     2254        log_to_screen("does not exist");
     2255        return (1);
     2256    }
     2257
     2258    retval = load_mountlist(mountlist, g_mountlist_fname);
     2259    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
     2260    if (retval) {
     2261        log_to_screen
     2262            ("Warning - load_raidtab_into_raidlist returned an error");
     2263    }
     2264    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
     2265    if (res) {
     2266        return (1);
     2267    }
     2268
     2269    save_mountlist_to_disk(mountlist, g_mountlist_fname);
     2270    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
     2271
     2272    log_to_screen("I have finished editing the mountlist for you.");
     2273
     2274    return (retval);
     2275}
     2276
     2277
     2278
     2279
     2280
     2281/**
     2282 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
     2283 * @param bkpinfo The backup information structure. Most fields are used.
     2284 * @param mountlist The mountlist containing information about the user's partitions.
     2285 * @param raidlist The raidlist to go with @p mountlist.
     2286 * @return The return code from the mode function called.
     2287 * @ingroup restoreGroup
     2288 */
     2289int
     2290catchall_mode(struct mountlist_itself *mountlist,
     2291              struct raidlist_itself *raidlist)
     2292{
     2293    char c;
     2294    char *tmp = NULL;
     2295    int retval = 0;
     2296
     2297    log_it("inside catchall");
     2298    assert(bkpinfo != NULL);
     2299    assert(mountlist != NULL);
     2300    assert(raidlist != NULL);
     2301    log_it("pre wrm");
     2302    c = which_restore_mode();
     2303    log_it("post wrm");
     2304    if (c == 'I' || c == 'C') {
     2305        interactively_obtain_media_parameters_from_user(FALSE);
     2306    } else if (c == 'N') {
     2307        // Auto mode nothing special to do
     2308    } else {
     2309        popup_and_OK("No restoring or comparing will take place today.");
     2310        if (is_this_device_mounted("/mnt/cdrom")) {
     2311            run_program_and_log_output("umount -d /mnt/cdrom", FALSE);
     2312        }
     2313        if (g_ISO_restore_mode) {
     2314            mr_asprintf(tmp, "umount -d %s", bkpinfo->isodir);
     2315            run_program_and_log_output(tmp, FALSE);
     2316            mr_free(tmp);
     2317        }
     2318        paranoid_MR_finish(0);
     2319    }
     2320
     2321    log_it("post int");
     2322
     2323    if (bkpinfo->backup_media_type == iso) {
     2324        if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
     2325            log_msg(2,
     2326                    "catchall_mode --- iso_fiddly_bits returned w/ error");
     2327            return (1);
     2328        } else {
     2329            log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
     2330        }
     2331    }
     2332
     2333    if (c == 'I') {
     2334        log_msg(2, "IM selected");
     2335        retval += interactive_mode(mountlist, raidlist);
     2336    } else if (c == 'N') {
     2337        log_msg(2, "NM selected");
     2338        retval += nuke_mode(mountlist, raidlist);
     2339    } else if (c == 'C') {
     2340        log_msg(2, "CM selected");
     2341        retval += compare_mode(mountlist, raidlist);
     2342    }
     2343    return (retval);
     2344}
     2345
     2346/**************************************************************************
     2347 *END_CATCHALL_MODE                                                      *
     2348 **************************************************************************/
     2349
     2350/**************************************************************************
     2351 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
     2352 **************************************************************************/
     2353
     2354
     2355/**
     2356 * Locate an executable in the directory structure rooted at @p restg.
     2357 * @param out_path Where to put the executable.
     2358 * @param fname The basename of the executable.
     2359 * @param restg The directory structure to look in.
     2360 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
     2361 * @ingroup restoreUtilityGroup
     2362 */
     2363void
     2364find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
     2365                                                    char *fname,
     2366                                                    char *restg)
     2367{
     2368    assert(out_path != NULL);
     2369    assert_string_is_neither_NULL_nor_zerolength(fname);
     2370
     2371    sprintf(out_path, "%s/sbin/%s", restg, fname);
     2372    if (does_file_exist(out_path)) {
     2373        sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
     2374        if (does_file_exist(out_path)) {
     2375            sprintf(out_path, "%s/bin/%s", restg, fname);
     2376            if (does_file_exist(out_path)) {
     2377                sprintf(out_path, "%s/usr/bin/%s", restg, fname);
     2378                if (does_file_exist(out_path)) {
     2379                    strcpy(out_path, fname);
     2380                }
     2381            }
     2382        }
     2383    }
     2384}
     2385
     2386/**************************************************************************
     2387 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
     2388 **************************************************************************/
     2389
     2390
     2391/**
     2392 * Run an arbitrary restore mode (prompt the user), but from ISO images
     2393 * instead of real media.
     2394 * @param mountlist The mountlist containing information about the user's partitions.
     2395 * @param raidlist The raidlist that goes with @p mountlist.
     2396 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
     2397 * @return 0 for success, or the number of errors encountered.
     2398 */
     2399int
     2400iso_mode(struct mountlist_itself *mountlist,
     2401         struct raidlist_itself *raidlist, bool nuke_me_please)
     2402{
     2403    char c;
     2404    int retval = 0;
     2405
     2406    assert(mountlist != NULL);
     2407    assert(raidlist != NULL);
     2408    if (iso_fiddly_bits(nuke_me_please)) {
     2409        log_msg(1, "iso_mode --- returning w/ error");
     2410        return (1);
     2411    } else {
     2412        c = which_restore_mode();
     2413        if (c == 'I' || c == 'N' || c == 'C') {
     2414            interactively_obtain_media_parameters_from_user(FALSE);
     2415        }
     2416        if (c == 'I') {
     2417            retval += interactive_mode(mountlist, raidlist);
     2418        } else if (c == 'N') {
     2419            retval += nuke_mode(mountlist, raidlist);
     2420        } else if (c == 'C') {
     2421            retval += compare_mode(mountlist, raidlist);
     2422        } else {
     2423            log_to_screen("OK, I shan't restore/compare any files.");
     2424        }
     2425    }
     2426    if (is_this_device_mounted(MNT_CDROM)) {
     2427        paranoid_system("umount -d " MNT_CDROM);
     2428    }
     2429//  if (! already_mounted)
     2430//    {
     2431    if (system("umount -d /tmp/isodir 2> /dev/null")) {
     2432        log_to_screen("WARNING - unable to unmount device where the ISO files are stored.");
     2433    }
     2434//    }
     2435    return (retval);
     2436}
     2437
     2438/**************************************************************************
     2439 *END_ISO_MODE                                                            *
     2440 **************************************************************************/
     2441
     2442
     2443/*            MONDO - saving your systems since Feb 18th, 2000            */
     2444
     2445
     2446
     2447/**
    8722448 * Restore the user's data (or a subset of it) to the live filesystem.
    8732449 * This should not be called if we're booted from CD!
     
    9592535
    9602536/* @} - end of restoreGroup */
    961 
    962 
    963 #include <utime.h>
    964 /**
    965  * @addtogroup LLrestoreGroup
    966  * @{
    967  */
    968 
    969 /**
    970  * Restore biggiefile @p bigfileno from the currently mounted CD.
    971  * @param bkpinfo The backup information structure. Fields used:
    972  * - @c bkpinfo->backup_media_type
    973  * - @c bkpinfo->restore_path
    974  * @param bigfileno The biggiefile number (starting from 0) to restore.
    975  * @param filelist The node structure containing the list of files to restore.
    976  * If the biggiefile is not in this list, it will be skipped (return value will
    977  * still indicate success).
    978  * @return 0 for success (or skip), nonzero for failure.
    979  */
    980 int restore_a_biggiefile_from_CD(long bigfileno,
    981                              struct s_node *filelist,
    982                              char *pathname_of_last_file_restored)
    983 {
    984     FILE *fin;
    985     FILE *fout;
    986     FILE *fbzip2;
    987 
    988   /** malloc ***/
    989     char *checksum = NULL;
    990     char *outfile_fname = NULL;
    991     char *tmp = NULL;
    992     char *bzip2_command = NULL;
    993     char *suffix = NULL;
    994     char *sz_devfile = NULL;
    995     char *bigblk;
    996     char *mds = NULL;
    997     int retval = 0;
    998     int finished = FALSE;
    999     long sliceno;
    1000     long siz;
    1001     char *ntfsprog_fifo = NULL;
    1002     char *file_to_openout = NULL;
    1003     struct s_filename_and_lstat_info biggiestruct;
    1004     struct utimbuf the_utime_buf, *ubuf;
    1005     bool use_ntfsprog_hack = FALSE;
    1006     pid_t pid;
    1007     int res = 0;
    1008     int old_loglevel;
    1009     struct s_node *node;
    1010 
    1011     old_loglevel = g_loglevel;
    1012     ubuf = &the_utime_buf;
    1013     assert(bkpinfo != NULL);
    1014 
    1015     pathname_of_last_file_restored[0] = '\0';
    1016     if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
    1017         fatal_error("Cannot malloc bigblk");
    1018     }
    1019 
    1020     if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
    1021         log_to_screen("Cannot even open bigfile's info file");
    1022         return (1);
    1023     }
    1024 
    1025     memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
    1026     if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
    1027         sizeof(biggiestruct)) {
    1028         log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
    1029                 bigfileno + 1);
    1030     }
    1031     paranoid_fclose(fin);
    1032 
    1033     mr_asprintf(checksum, "%s", biggiestruct.checksum);
    1034     if (!checksum[0]) {
    1035         log_msg(3, "Warning - bigfile %ld does not have a checksum", bigfileno + 1);
    1036     }
    1037     mr_free(checksum);
    1038 
    1039     if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
    1040     {
    1041         mr_asprintf(outfile_fname, "%s", biggiestruct.filename);
    1042     } else {
    1043         mr_asprintf(outfile_fname, "%s/%s", bkpinfo->restore_path, biggiestruct.filename);
    1044     }
    1045 
    1046     /* skip file if we have a selective restore subset & it doesn't match */
    1047     if (filelist != NULL) {
    1048         node = find_string_at_node(filelist, biggiestruct.filename);
    1049         if (!node) {
    1050             log_msg(0, "Skipping %s (name isn't in filelist)", biggiestruct.filename);
    1051             pathname_of_last_file_restored[0] = '\0';
    1052             return (0);
    1053         } else if (!(node->selected)) {
    1054             log_msg(1, "Skipping %s (name isn't in biggielist subset)", biggiestruct.filename);
    1055             pathname_of_last_file_restored[0] = '\0';
    1056             return (0);
    1057         }
    1058     }
    1059 
    1060     /* otherwise, continue */
    1061     log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
    1062     if (biggiestruct.use_ntfsprog) {
    1063         if (strncmp(biggiestruct.filename, "/dev/", 5)) {
    1064             log_msg(1, "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
    1065             log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
    1066             biggiestruct.use_ntfsprog = FALSE;
    1067         }
    1068     }
    1069 
    1070     if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
    1071     {
    1072         g_loglevel = 4;
    1073         use_ntfsprog_hack = TRUE;
    1074         log_msg(2, "Calling ntfsclone in background because %s is an NTFS /dev entry", outfile_fname);
    1075         mr_asprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768), (int) (random() % 32768));
    1076         mkfifo(sz_devfile, 0x770);
    1077         mr_asprintf(ntfsprog_fifo, "%s", sz_devfile);
    1078         mr_free(sz_devfile);
    1079         file_to_openout = ntfsprog_fifo;
    1080         switch (pid = fork()) {
    1081         case -1:
    1082             fatal_error("Fork failure");
    1083         case 0:
    1084             log_msg(3, "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)", biggiestruct.filename, ntfsprog_fifo);
    1085             res = feed_outfrom_ntfsprog(biggiestruct.filename, ntfsprog_fifo);
    1086             mr_free(ntfsprog_fifo);
    1087             exit(res);
    1088             break;
    1089         default:
    1090             log_msg(3, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid));
    1091         }
    1092         mr_free(ntfsprog_fifo);
    1093     } else {
    1094         use_ntfsprog_hack = FALSE;
    1095         file_to_openout = outfile_fname;
    1096         if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
    1097         {
    1098             make_hole_for_file(outfile_fname);
    1099         }
    1100     }
    1101 
    1102     log_msg(2, "Reassembling big file %ld (%s)", bigfileno + 1, outfile_fname);
    1103 
    1104     /*
    1105        last slice is zero-length and uncompressed; when we find it, we stop.
    1106        We DON'T wait until there are no more slices; if we did that,
    1107        We might stop at end of CD, not at last slice (which is 0-len and uncompd)
    1108      */
    1109 
    1110     strncpy(pathname_of_last_file_restored, biggiestruct.filename, MAX_STR_LEN - 1);
    1111     pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
    1112 
    1113     log_msg(3, "file_to_openout = %s", file_to_openout);
    1114     if (!(fout = fopen(file_to_openout, "w"))) {
    1115         log_to_screen("Cannot openout outfile_fname - hard disk full?");
    1116         return (1);
    1117     }
    1118     log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
    1119 
    1120     for (sliceno = 1, finished = FALSE; !finished;) {
    1121         if (!does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "")) &&
    1122             !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzo")) &&
    1123             !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "gz")) &&
    1124             !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzma")) &&
    1125             !does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
    1126             log_msg(3, "Cannot find a data slice or terminator slice on CD %d", g_current_media_number);
    1127             g_current_media_number++;
    1128             mds = media_descriptor_string(bkpinfo->backup_media_type);
    1129             log_msg(2, "Asking for %s #%d so that I may read slice #%ld\n", mds, g_current_media_number, sliceno);
    1130             mr_free(mds);
    1131 
    1132             log_to_screen("Restoring from %s #%d", mds, g_current_media_number);
    1133 
    1134             insist_on_this_cd_number(g_current_media_number);
    1135             log_to_screen("Continuing to restore.");
    1136         } else {
    1137             mr_asprintf(tmp, "%s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
    1138             if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
    1139                 log_msg(2, "End of bigfile # %ld (slice %ld is the terminator)", bigfileno + 1, sliceno);
    1140                 finished = TRUE;
    1141                 mr_free(tmp);
    1142                 continue;
    1143             } else {
    1144                 if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
    1145                     mr_asprintf(bzip2_command, "lzop");
    1146                     mr_asprintf(suffix, "lzo");
    1147                 } else
    1148                     if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
    1149                     mr_asprintf(bzip2_command, "gzip");
    1150                     mr_asprintf(suffix, "gz");
    1151                 } else
    1152                     if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "lzma"))) {
    1153                     mr_asprintf(bzip2_command, "lzma");
    1154                     mr_asprintf(suffix, "lzma");
    1155                 } else
    1156                     if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
    1157                     mr_asprintf(bzip2_command, "bzip2");
    1158                     mr_asprintf(suffix, "bz2");
    1159                 } else
    1160                     if (does_file_exist(slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))) {
    1161                     mr_asprintf(bzip2_command, "");
    1162                     mr_asprintf(suffix, "");
    1163                 } else {
    1164                     log_to_screen("OK, that's pretty fsck0red...");
    1165                     mr_free(tmp);
    1166                     return (1);
    1167                 }
    1168             }
    1169             mr_free(tmp);
    1170             if (bzip2_command != NULL) {
    1171                 mr_strcat(bzip2_command, " -dc %s 2>> %s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, suffix), MONDO_LOGFILE);
    1172             } else {
    1173                 mr_asprintf(bzip2_command, "cat %s 2>> %s", slice_fname(bigfileno, sliceno, ARCHIVES_PATH, suffix), MONDO_LOGFILE);
    1174             }
    1175             mr_free(suffix);
    1176 
    1177             mds = media_descriptor_string(bkpinfo->backup_media_type);
    1178             mr_asprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ", mds, g_current_media_number, bigfileno + 1, sliceno);
    1179             mr_free(mds);
    1180             log_msg(2, tmp);
    1181 
    1182             if (!g_text_mode) {
    1183                 newtDrawRootText(0, g_noof_rows - 2, tmp);
    1184                 newtRefresh();
    1185                 strip_spaces(tmp);
    1186                 update_progress_form(tmp);
    1187             }
    1188             mr_free(tmp);
    1189 
    1190             if (!(fbzip2 = popen(bzip2_command, "r"))) {
    1191                 fatal_error("Can't run popen command");
    1192             }
    1193             mr_free(bzip2_command);
    1194 
    1195             while (!feof(fbzip2)) {
    1196                 siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
    1197                 if (siz > 0) {
    1198                     siz = fwrite(bigblk, 1, siz, fout);
    1199                 }
    1200             }
    1201             paranoid_pclose(fbzip2);
    1202 
    1203 
    1204             sliceno++;
    1205             g_current_progress++;
    1206         }
    1207     }
    1208     paranoid_fclose(fout);
    1209     g_loglevel = old_loglevel;
    1210 
    1211     if (use_ntfsprog_hack) {
    1212         log_msg(3, "Waiting for ntfsclone to finish");
    1213         mr_asprintf(tmp, " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
    1214         while (system(tmp) == 0) {
    1215             sleep(1);
    1216         }
    1217         mr_free(tmp);
    1218         log_it("OK, ntfsclone has really finished");
    1219     }
    1220 
    1221     if (strcmp(outfile_fname, "/dev/null")) {
    1222         if (chown(outfile_fname, biggiestruct.properties.st_uid, biggiestruct.properties.st_gid)) {
    1223             // FIXME
    1224         }
    1225         chmod(outfile_fname, biggiestruct.properties.st_mode);
    1226         ubuf->actime = biggiestruct.properties.st_atime;
    1227         ubuf->modtime = biggiestruct.properties.st_mtime;
    1228         utime(outfile_fname, ubuf);
    1229     }
    1230     mr_free(outfile_fname);
    1231     paranoid_free(bigblk);
    1232 
    1233     return (retval);
    1234 }
    1235 
    1236 /**************************************************************************
    1237  *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
    1238  **************************************************************************/
    1239 
    1240 
    1241 
    1242 /**
    1243  * Restore a biggiefile from the currently opened stream.
    1244  * @param bkpinfo The backup information structure. Fields used:
    1245  * - @c bkpinfo->restore_path
    1246  * - @c bkpinfo->zip_exe
    1247  * @param orig_bf_fname The original filename of the biggiefile.
    1248  * @param biggiefile_number The number of the biggiefile (starting from 0).
    1249  * @param orig_checksum Unused.
    1250  * @param biggiefile_size Unused.
    1251  * @param filelist The node structure containing the list of files to be restored.
    1252  * If @p orig_bf_fname is not in the list, it will be ignored.
    1253  * @return 0 for success (or skip), nonzero for failure.
    1254  * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
    1255  */
    1256 int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
    1257                                      long long biggiefile_size, //UNUSED
    1258                                      struct s_node *filelist,
    1259                                      int use_ntfsprog,
    1260                                      char *pathname_of_last_file_restored)
    1261 {
    1262     FILE *pout;
    1263     FILE *fin;
    1264 
    1265   /** mallocs ********/
    1266     char *tmp = NULL;
    1267     char *tmp1 = NULL;
    1268     char *command = NULL;
    1269     char *outfile_fname = NULL;
    1270     char *sz_devfile = NULL;
    1271     char *ntfsprog_fifo = NULL;
    1272     char *file_to_openout = NULL;
    1273 
    1274     struct s_node *node;
    1275 
    1276     int old_loglevel;
    1277     long current_slice_number = 0;
    1278     int retval = 0;
    1279     int res = 0;
    1280     int ctrl_chr = '\0';
    1281     long long slice_siz;
    1282     bool dummy_restore = FALSE;
    1283     bool use_ntfsprog_hack = FALSE;
    1284     pid_t pid;
    1285     struct s_filename_and_lstat_info biggiestruct;
    1286     struct utimbuf the_utime_buf, *ubuf;
    1287     ubuf = &the_utime_buf;
    1288 
    1289     malloc_string(tmp);
    1290     old_loglevel = g_loglevel;
    1291     assert(bkpinfo != NULL);
    1292     assert(orig_bf_fname != NULL);
    1293     assert(orig_checksum != NULL);
    1294 
    1295     pathname_of_last_file_restored[0] = '\0';
    1296     if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
    1297         use_ntfsprog = 1;
    1298         log_msg(1, "%s --- pih=YES", orig_bf_fname);
    1299     } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
    1300         use_ntfsprog = 0;
    1301         log_msg(1, "%s --- pih=NO", orig_bf_fname);
    1302     } else {
    1303         use_ntfsprog = 0;
    1304         log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
    1305     }
    1306 
    1307     strncpy(pathname_of_last_file_restored, orig_bf_fname,
    1308             MAX_STR_LEN - 1);
    1309     pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
    1310 
    1311     /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
    1312 
    1313     if (filelist != NULL) {
    1314         node = find_string_at_node(filelist, orig_bf_fname);
    1315         if (!node) {
    1316             dummy_restore = TRUE;
    1317             log_msg(1,
    1318                     "Skipping big file %ld (%s) - not in biggielist subset",
    1319                     biggiefile_number + 1, orig_bf_fname);
    1320             pathname_of_last_file_restored[0] = '\0';
    1321         } else if (!(node->selected)) {
    1322             dummy_restore = TRUE;
    1323             log_msg(1, "Skipping %s (name isn't in biggielist subset)",
    1324                     orig_bf_fname);
    1325             pathname_of_last_file_restored[0] = '\0';
    1326         }
    1327     }
    1328 
    1329     if (use_ntfsprog) {
    1330         if (strncmp(orig_bf_fname, "/dev/", 5)) {
    1331             log_msg(1,
    1332                     "I was in error when I set use_ntfsprog to TRUE.");
    1333             log_msg(1, "%s isn't even in /dev", orig_bf_fname);
    1334             use_ntfsprog = FALSE;
    1335         }
    1336     }
    1337 
    1338     if (use_ntfsprog) {
    1339         g_loglevel = 4;
    1340         mr_asprintf(outfile_fname, "%s", orig_bf_fname);
    1341         use_ntfsprog_hack = TRUE;
    1342         log_msg(2, "Calling ntfsclone in background because %s is a /dev entry", outfile_fname);
    1343         mr_asprintf(sz_devfile, "%s/%d.%d.000", bkpinfo->tmpdir, (int) (random() % 32768), (int) (random() % 32768));
    1344         mkfifo(sz_devfile, 0x770);
    1345         mr_asprintf(ntfsprog_fifo, "%s", sz_devfile);
    1346         mr_free(sz_devfile);
    1347 
    1348         file_to_openout = ntfsprog_fifo;
    1349         switch (pid = fork()) {
    1350         case -1:
    1351             fatal_error("Fork failure");
    1352         case 0:
    1353             log_msg(3, "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)", outfile_fname, ntfsprog_fifo);
    1354             res = feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
    1355             mr_free(ntfsprog_fifo);
    1356             exit(res);
    1357             break;
    1358         default:
    1359             log_msg(3, "feed_into_ntfsprog() called in background --- pid=%ld", (long int) (pid));
    1360         }
    1361         mr_free(ntfsprog_fifo);
    1362     } else {
    1363         if (!strncmp(orig_bf_fname, "/dev/", 5))    {
    1364             // non-NTFS partition
    1365             mr_asprintf(outfile_fname, "%s", orig_bf_fname);
    1366         } else {
    1367             // biggiefile
    1368             mr_asprintf(outfile_fname, "%s/%s", bkpinfo->restore_path, orig_bf_fname);
    1369         }
    1370         use_ntfsprog_hack = FALSE;
    1371         file_to_openout = outfile_fname;
    1372         if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
    1373         {
    1374             make_hole_for_file(outfile_fname);
    1375         }
    1376         log_msg(2, "Reassembling big file %ld (%s)", biggiefile_number + 1, orig_bf_fname);
    1377     }
    1378 
    1379     if (dummy_restore) {
    1380         mr_free(outfile_fname);
    1381         mr_asprintf(outfile_fname, "/dev/null");
    1382     }
    1383 
    1384     if (!bkpinfo->zip_exe[0]) {
    1385         mr_asprintf(command, "cat > \"%s\"", file_to_openout);
    1386     } else {
    1387         mr_asprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe, file_to_openout, MONDO_LOGFILE);
    1388         if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
    1389             /* Ignore SIGPIPE for gzip as it causes errors on big files
    1390              * Cf: http://trac.mondorescue.org/ticket/244 */
    1391             signal(SIGPIPE,SIG_IGN);
    1392         }
    1393     }
    1394     log_msg(3, "Pipe command = '%s'", command);
    1395 
    1396     /* restore biggiefile, one slice at a time */
    1397     if (!(pout = popen(command, "w"))) {
    1398         fatal_error("Cannot pipe out");
    1399     }
    1400     mr_free(command);
    1401 
    1402     for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
    1403          ctrl_chr != BLK_STOP_A_BIGGIE;
    1404          res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
    1405         if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
    1406             wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
    1407         }
    1408         log_msg(2, "Working on file #%ld, slice #%ld    ", biggiefile_number + 1, current_slice_number);
    1409         if (!g_text_mode) {
    1410             newtDrawRootText(0, g_noof_rows - 2, tmp);
    1411             newtRefresh();
    1412         }
    1413         strip_spaces(tmp);
    1414         update_progress_form(tmp);
    1415         if (current_slice_number == 0) {
    1416             res =
    1417                 read_file_from_stream_to_file("/tmp/biggie-blah.txt",
    1418                                               slice_siz);
    1419             if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
    1420                 log_OS_error("blah blah");
    1421             } else {
    1422                 if (fread
    1423                     ((void *) &biggiestruct, 1, sizeof(biggiestruct),
    1424                      fin) < sizeof(biggiestruct)) {
    1425                     log_msg(2,
    1426                             "Warning - unable to get biggiestruct of bigfile #%d",
    1427                             biggiefile_number + 1);
    1428                 }
    1429                 paranoid_fclose(fin);
    1430             }
    1431         } else {
    1432             res =
    1433                 read_file_from_stream_to_stream(pout, slice_siz);
    1434         }
    1435         retval += res;
    1436         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
    1437         if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
    1438             wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
    1439         }
    1440         current_slice_number++;
    1441         g_current_progress++;
    1442     }
    1443     paranoid_pclose(pout);
    1444 
    1445     if (bkpinfo->zip_exe[0]) {
    1446         if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
    1447             /* Re-enable SIGPIPE for gzip */
    1448             signal(SIGPIPE, terminate_daemon);
    1449         }
    1450     }
    1451 
    1452     log_msg(1, "pathname_of_last_file_restored is now %s",
    1453             pathname_of_last_file_restored);
    1454 
    1455     if (use_ntfsprog_hack) {
    1456         log_msg(3, "Waiting for ntfsclone to finish");
    1457         mr_asprintf(tmp1, " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
    1458         while (system(tmp1) == 0) {
    1459             sleep(1);
    1460         }
    1461         mr_free(tmp1);
    1462         log_msg(3, "OK, ntfsclone has really finished");
    1463     }
    1464 
    1465     log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
    1466     log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
    1467     if (strcmp(outfile_fname, "/dev/null")) {
    1468         chmod(outfile_fname, biggiestruct.properties.st_mode);
    1469         if (chown(outfile_fname, biggiestruct.properties.st_uid, biggiestruct.properties.st_gid)) {
    1470             // FIXME
    1471         }
    1472         ubuf->actime = biggiestruct.properties.st_atime;
    1473         ubuf->modtime = biggiestruct.properties.st_mtime;
    1474         utime(outfile_fname, ubuf);
    1475     }
    1476     mr_free(outfile_fname);
    1477 
    1478     paranoid_free(tmp);
    1479     g_loglevel = old_loglevel;
    1480     return (retval);
    1481 }
    1482 
    1483 /**************************************************************************
    1484  *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
    1485  **************************************************************************/
    1486 
    1487 
    1488 
    1489 /**
    1490  * Restore @p tarball_fname from CD.
    1491  * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
    1492  * This will be used unmodified.
    1493  * @param current_tarball_number The number (starting from 0) of the fileset
    1494  * we're restoring now.
    1495  * @param filelist The node structure containing the list of files to be
    1496  * restored. If no file in the afioball is in this list, afio will still be
    1497  * called, but nothing will be written.
    1498  * @return 0 for success, nonzero for failure.
    1499  */
    1500 int
    1501 restore_a_tarball_from_CD(char *tarball_fname,
    1502                           long current_tarball_number,
    1503                           struct s_node *filelist)
    1504 {
    1505     int retval = 0;
    1506     int res;
    1507     char *p;
    1508 
    1509   /** malloc **/
    1510     char *command = NULL;
    1511     char *tmp = NULL;
    1512     char *filelist_name = NULL;
    1513     char *filelist_subset_fname = NULL;
    1514     char *executable = NULL;
    1515     char *temp_log = NULL;
    1516     long matches = 0;
    1517     bool use_star;
    1518     char *xattr_fname = NULL;
    1519     char *acl_fname = NULL;
    1520 
    1521     assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
    1522     assert(bkpinfo != NULL);
    1523 
    1524     log_msg(5, "Entering");
    1525     use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
    1526     mr_asprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
    1527     run_program_and_log_output(command, 9);
    1528     paranoid_free(command);
    1529 
    1530     mr_asprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld", current_tarball_number);
    1531     if (length_of_file(filelist_name) <= 2) {
    1532         log_msg(2, "There are _zero_ files in filelist '%s'", filelist_name);
    1533         log_msg(2, "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
    1534         log_msg(2, "but it's non-critical. It's cosmetic. Don't worry about it.");
    1535         retval = 0;
    1536         mr_free(filelist_name);
    1537         log_msg(5, "Leaving");
    1538         return(0);
    1539     }
    1540     if (count_lines_in_file(filelist_name) <= 0 || length_of_file(tarball_fname) <= 0) {
    1541         log_msg(3, "length_of_file(%s) = %llu", tarball_fname, length_of_file(tarball_fname));
    1542         log_msg(3, "count_lines_in_file(%s) = %llu", tarball_fname, count_lines_in_file(tarball_fname));
    1543         log_to_screen("Unable to restore fileset #%ld (CD I/O error)", current_tarball_number);
    1544         mr_free(filelist_name);
    1545         log_msg(5, "Leaving");
    1546         return(1);
    1547     }
    1548 
    1549     if (filelist) {
    1550         mr_asprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp", current_tarball_number);
    1551         if ((matches =
    1552              save_filelist_entries_in_common(filelist_name, filelist,
    1553                                              filelist_subset_fname,
    1554                                              use_star)) <= 0) {
    1555             log_msg(1, "Skipping fileset %ld", current_tarball_number);
    1556         } else {
    1557             log_msg(3, "Saved fileset %ld's subset to %s", current_tarball_number, filelist_subset_fname);
    1558         }
    1559         log_to_screen("Tarball #%ld --- %ld matches", current_tarball_number, matches);
    1560     }
    1561     mr_free(filelist_name);
    1562 
    1563     if (filelist == NULL || matches > 0) {
    1564         if (g_getfattr) {
    1565             mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
    1566         }
    1567         if (g_getfacl) {
    1568             mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
    1569         }
    1570         if (strstr(tarball_fname, ".bz2")) {
    1571             mr_asprintf(executable, "bzip2");
    1572         } else if (strstr(tarball_fname, ".lzma")) {
    1573             mr_asprintf(executable, "lzma");
    1574         } else if (strstr(tarball_fname, ".gz")) {
    1575             mr_asprintf(executable, "gzip");
    1576         } else if (strstr(tarball_fname, ".lzo")) {
    1577             mr_asprintf(executable, "lzop");
    1578         }
    1579         if (bkpinfo->compression_level == 0) {
    1580             mr_asprintf(executable, "%s", "");
    1581         } else {
    1582             if (executable) {
    1583                 mr_asprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
    1584                 res = run_program_and_log_output(tmp, FALSE);
    1585                 mr_free(tmp);
    1586    
    1587                 if (res) {
    1588                     log_to_screen("(compare_a_tarball) Compression program %s not found - oh no!", executable);
    1589                     paranoid_MR_finish(1);
    1590                 }
    1591                 tmp = executable;
    1592                 mr_asprintf(executable, "-P %s -Z", tmp);
    1593                 mr_free(tmp);
    1594             }
    1595         }
    1596 #ifdef __FreeBSD__
    1597 #define BUFSIZE 512
    1598 #else
    1599 #define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
    1600 #endif
    1601 
    1602         if (use_star) {
    1603             mr_asprintf(command, "star -x -force-remove -sparse -U " STAR_ACL_SZ " file=%s", tarball_fname);
    1604             if (strstr(tarball_fname, ".bz2")) {
    1605                 mr_strcat(command, " -bz");
    1606             }
    1607         } else {
    1608             if (! executable) {
    1609                 log_msg(2, "No executable, this shouldn't happen !");
    1610             } else {
    1611                 if (filelist_subset_fname != NULL) {
    1612                     mr_asprintf(command, "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s", TAPE_BLOCK_SIZE, BUFSIZE, executable, filelist_subset_fname, tarball_fname);
    1613                 } else {
    1614                     mr_asprintf(command, "afio -i -b %ld -c %ld -M 8m %s %s", TAPE_BLOCK_SIZE, BUFSIZE, executable, tarball_fname);
    1615                 }
    1616             }
    1617         }
    1618         mr_free(executable);
    1619 
    1620 #undef BUFSIZE
    1621         mr_asprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768), (int) (random() % 32768));
    1622 
    1623         mr_strcat(command, " 2>> %s >> %s", temp_log, temp_log);
    1624         log_msg(1, "command = '%s'", command);
    1625         unlink(temp_log);
    1626         res = system(command);
    1627         if (res) {
    1628             p = strstr(command, "-acl ");
    1629             if (p) {
    1630                 p[0] = p[1] = p[2] = p[3] = ' ';
    1631                 log_msg(1, "new command = '%s'", command);
    1632                 res = system(command);
    1633             }
    1634         }
    1635         paranoid_free(command);
    1636 
    1637         if (res && length_of_file(temp_log) < 5) {
    1638             res = 0;
    1639         }
    1640 
    1641         if (! use_star) {
    1642             if (g_getfattr) {
    1643                 log_msg(1, "Setting fattr list %s", xattr_fname);
    1644                 if (length_of_file(xattr_fname) > 0) {
    1645                     res = set_fattr_list(filelist_subset_fname, xattr_fname);
    1646                     if (res) {
    1647                         log_to_screen("Errors occurred while setting extended attributes");
    1648                     } else {
    1649                         log_msg(1, "I set xattr OK");
    1650                     }
    1651                     retval += res;
    1652                 }
    1653             }
    1654             if (g_getfacl) {
    1655                 log_msg(1, "Setting acl list %s", acl_fname);
    1656                 if (length_of_file(acl_fname) > 0) {
    1657                     res = set_acl_list(filelist_subset_fname, acl_fname);
    1658                     if (res) {
    1659                         log_to_screen("Errors occurred while setting access control lists");
    1660                     } else {
    1661                         log_msg(1, "I set ACL OK");
    1662                     }
    1663                     retval += res;
    1664                 }
    1665             }
    1666         } else {
    1667             retval = res;
    1668         }
    1669         // Be verbose for star
    1670         if (retval || use_star) {
    1671             mr_asprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
    1672             paranoid_system(command);
    1673             paranoid_free(command);
    1674 
    1675             if (retval) {
    1676                 log_msg(2, "Errors occurred while processing fileset #%d", current_tarball_number);
    1677             }
    1678         } else {
    1679             log_msg(2, "Fileset #%d processed OK", current_tarball_number);
    1680         }
    1681         unlink(temp_log);
    1682         mr_free(temp_log);
    1683     }
    1684     if (does_file_exist("/PAUSE")) {
    1685         popup_and_OK
    1686             ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
    1687     }
    1688     unlink(filelist_subset_fname);
    1689     mr_free(filelist_subset_fname);
    1690     if (g_getfattr) {
    1691         unlink(xattr_fname);
    1692         mr_free(xattr_fname);
    1693     }
    1694     if (g_getfacl) {
    1695         unlink(acl_fname);
    1696         mr_free(acl_fname);
    1697     }
    1698 
    1699     log_msg(5, "Leaving");
    1700     return (retval);
    1701 }
    1702 
    1703 /**************************************************************************
    1704  *END_RESTORE_A_TARBALL_FROM_CD                                           *
    1705  **************************************************************************/
    1706 
    1707 
    1708 /**
    1709  * Restore a tarball from the currently opened stream.
    1710  * @param bkpinfo The backup information structure. Fields used:
    1711  * - @c bkpinfo->backup_media_type
    1712  * - @c bkpinfo->media_device
    1713  * - @c bkpinfo->zip_exe
    1714  * @param tarball_fname The filename of the afioball to restore.
    1715  * @param current_tarball_number The number (starting from 0) of the fileset
    1716  * we're restoring now.
    1717  * @param filelist The node structure containing the list of files to be
    1718  * restored. If no file in the afioball is in this list, afio will still be
    1719  * called, but nothing will be written.
    1720  * @param size The size (in @b bytes) of the afioball.
    1721  * @return 0 for success, nonzero for failure.
    1722  */
    1723 int
    1724 restore_a_tarball_from_stream(char *tarball_fname,
    1725                               long current_tarball_number,
    1726                               struct s_node *filelist,
    1727                               long long size, char *xattr_fname,
    1728                               char *acl_fname)
    1729 {
    1730     int retval = 0;
    1731     int res = 0;
    1732 
    1733   /** malloc add ***/
    1734     char *mds = NULL;
    1735     char *command = NULL;
    1736     char *afio_fname = NULL;
    1737     char *filelist_fname = NULL;
    1738     char *filelist_subset_fname = NULL;
    1739     char *executable = NULL;
    1740     long matches = 0;
    1741     bool restore_this_fileset = FALSE;
    1742     bool use_star;
    1743 
    1744     assert(bkpinfo != NULL);
    1745     assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
    1746 
    1747     /* to do it with a file... */
    1748     use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
    1749     mds = media_descriptor_string(bkpinfo->backup_media_type);
    1750     log_msg(2, "Restoring from fileset #%ld (%ld KB) on %s #%d",
    1751             current_tarball_number, (long) size >> 10, mds, g_current_media_number);
    1752     mr_free(mds);
    1753 
    1754     run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
    1755 
    1756   /****************************************************************************
    1757    * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
    1758    * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
    1759    * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
    1760    ****************************************************************************/
    1761     mr_asprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld", current_tarball_number);
    1762     mr_asprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir, current_tarball_number);
    1763     mr_asprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp", bkpinfo->tmpdir, current_tarball_number);
    1764 
    1765     res = read_file_from_stream_to_file(afio_fname, size);
    1766     if (strstr(tarball_fname, ".star")) {
    1767         bkpinfo->use_star = TRUE;
    1768     }
    1769     if (res) {
    1770         log_msg(1, "Warning - error reading afioball from tape");
    1771     }
    1772     if (bkpinfo->compression_level == 0) {
    1773         mr_asprintf(executable, "%s", "");
    1774     } else {
    1775         if (bkpinfo->use_star) {
    1776             mr_asprintf(executable, "%s", " -bz");
    1777         } else {
    1778             mr_asprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
    1779         }
    1780     }
    1781 
    1782     if (!filelist)              // if unconditional restore then restore entire fileset
    1783     {
    1784         restore_this_fileset = TRUE;
    1785     } else                      // If restoring selectively then get TOC from tarball
    1786     {
    1787         if (strstr(tarball_fname, ".star.")) {
    1788             use_star = TRUE;
    1789             mr_asprintf(command, "star -sparse -t file=%s %s", afio_fname, executable);
    1790         } else {
    1791             use_star = FALSE;
    1792             mr_asprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE, executable, afio_fname);
    1793         }
    1794         mr_strcat(command, " > %s 2>> %s", filelist_fname, MONDO_LOGFILE);
    1795         log_msg(1, "command = %s", command);
    1796         if (system(command)) {
    1797             log_msg(4, "Warning - error occurred while retrieving TOC");
    1798         }
    1799         mr_free(command);
    1800 
    1801         if ((matches =
    1802              save_filelist_entries_in_common(filelist_fname, filelist,
    1803                                              filelist_subset_fname,
    1804                                              use_star))
    1805             <= 0 || length_of_file(filelist_subset_fname) < 2) {
    1806             if (length_of_file(filelist_subset_fname) < 2) {
    1807                 log_msg(1, "No matches found in fileset %ld",
    1808                         current_tarball_number);
    1809             }
    1810             log_msg(2, "Skipping fileset %ld", current_tarball_number);
    1811             restore_this_fileset = FALSE;
    1812         } else {
    1813             log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
    1814                     matches, current_tarball_number,
    1815                     filelist_subset_fname);
    1816             restore_this_fileset = TRUE;
    1817         }
    1818     }
    1819 
    1820 // Concoct the call to star/afio to restore files
    1821     if (strstr(tarball_fname, ".star.")) {
    1822         // star
    1823         mr_asprintf(command, "star -sparse -x file=%s %s", afio_fname, executable);
    1824         if (filelist) {
    1825             mr_strcat(command, " list=%s", filelist_subset_fname);
    1826         }
    1827     } else {
    1828         // afio
    1829         mr_asprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE, executable);
    1830         if (filelist) {
    1831             mr_strcat(command, " -w %s", filelist_subset_fname);
    1832         }
    1833         mr_strcat(command, " %s", afio_fname);
    1834     }
    1835     mr_strcat(command, " 2>> %s", MONDO_LOGFILE);
    1836     mr_free(executable);
    1837 
    1838 // Call if IF there are files to restore (selectively/unconditionally)
    1839     if (restore_this_fileset) {
    1840         log_msg(1, "Calling command='%s'", command);
    1841         paranoid_system(command);
    1842 
    1843         if (g_getfattr) {
    1844             log_it("Restoring xattr stuff");
    1845             res = set_fattr_list(filelist_subset_fname, xattr_fname);
    1846             if (res) {
    1847                 log_msg(1, "Errors occurred while setting xattr");
    1848             } else {
    1849                 log_msg(1, "I set xattr OK");
    1850             }
    1851             retval += res;
    1852         }
    1853 
    1854         if (g_getfacl) {
    1855             log_it("Restoring acl stuff");
    1856             res = set_acl_list(filelist_subset_fname, acl_fname);
    1857             if (res) {
    1858                 log_msg(1, "Errors occurred while setting ACL");
    1859             } else {
    1860                 log_msg(1, "I set ACL OK");
    1861             }
    1862             retval += res;
    1863         }
    1864 
    1865     } else {
    1866         log_msg(1, "NOT CALLING '%s'", command);
    1867     }
    1868     mr_free(command);
    1869 
    1870     if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
    1871         log_to_screen("Paused after set %ld", current_tarball_number);
    1872         popup_and_OK("Pausing. Press ENTER to continue.");
    1873     }
    1874 
    1875     unlink(filelist_subset_fname);
    1876     mr_free(filelist_subset_fname);
    1877     unlink(filelist_fname);
    1878     mr_free(filelist_fname);
    1879     unlink(afio_fname);
    1880     mr_free(afio_fname);
    1881 
    1882     return (retval);
    1883 }
    1884 
    1885 /**************************************************************************
    1886  *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
    1887  **************************************************************************/
    1888 
    1889 
    1890 
    1891 
    1892 /**
    1893  * Restore all biggiefiles from all media in this CD backup.
    1894  * The CD with the last afioball should be currently mounted.
    1895  * @param bkpinfo The backup information structure. @c backup_media_type is the
    1896  * only field used in this function.
    1897  * @param filelist The node structure containing the list of files to be
    1898  * restored. If a prospective biggiefile is not in this list, it will be ignored.
    1899  * @return 0 for success, nonzero for failure.
    1900  */
    1901 int restore_all_biggiefiles_from_CD(struct s_node *filelist) {
    1902 
    1903     int retval = 0;
    1904     int res = 0;
    1905     long noof_biggiefiles, bigfileno = 0, total_slices;
    1906   /** malloc **/
    1907     char *tmp = NULL;
    1908     char *tmp1 = NULL;
    1909     char *mds = NULL;
    1910     bool just_changed_cds = FALSE;
    1911     char *xattr_fname = NULL;
    1912     char *acl_fname = NULL;
    1913     char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
    1914     char *pathname_of_last_biggie_restored;
    1915     FILE *fbw = NULL;
    1916 
    1917     malloc_string(pathname_of_last_biggie_restored);
    1918     malloc_string(tmp);
    1919     assert(bkpinfo != NULL);
    1920 
    1921     mr_asprintf(biggies_whose_EXATs_we_should_set, "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
    1922     if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
    1923         log_msg(1, "Warning - cannot openout %s", biggies_whose_EXATs_we_should_set);
    1924     }
    1925 
    1926     read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
    1927     total_slices = atol(tmp);
    1928     mr_free(tmp);
    1929 
    1930     mr_asprintf(tmp1, "Reassembling large files      ");
    1931     mvaddstr_and_log_it(g_currentY, 0, tmp1);
    1932     mr_free(tmp1);
    1933 
    1934     if (length_of_file(BIGGIELIST) < 6) {
    1935         log_msg(1, "OK, no biggielist; not restoring biggiefiles");
    1936         return (0);
    1937     }
    1938     noof_biggiefiles = count_lines_in_file(BIGGIELIST);
    1939     if (noof_biggiefiles <= 0) {
    1940         log_msg(2, "OK, no biggiefiles in biggielist; not restoring biggiefiles");
    1941         return (0);
    1942     }
    1943     log_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
    1944 
    1945     open_progress_form("Reassembling large files",
    1946                        "I am now reassembling all the large files.",
    1947                        "Please wait. This may take some time.",
    1948                        "", total_slices);
    1949     for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
    1950         log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
    1951         if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
    1952             log_msg(3, "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
    1953             mds = media_descriptor_string(bkpinfo->backup_media_type);
    1954             log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d", bigfileno + 1, mds, g_current_media_number);
    1955             log_msg(3, "Slicename would have been %s",
    1956                     slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
    1957             // I'm not positive 'just_changed_cds' is even necessary...
    1958             if (just_changed_cds) {
    1959                 just_changed_cds = FALSE;
    1960                 log_msg(3, "I'll continue to scan this CD for bigfiles to be restored.");
    1961             } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
    1962                 insist_on_this_cd_number(++g_current_media_number);
    1963                 log_to_screen("Restoring from %s #%d", mds, g_current_media_number);
    1964                 just_changed_cds = TRUE;
    1965             } else {
    1966                 /* That big file doesn't exist, but the followings may */
    1967                 /* So we need to continue looping */
    1968                 log_msg(2, "There was no bigfile #%ld. That's OK.", bigfileno + 1);
    1969                 log_msg(2, "I'm going to stop restoring bigfiles now.");
    1970                 retval++;
    1971                 bigfileno++;
    1972             }
    1973             mr_free(mds);
    1974         } else {
    1975             just_changed_cds = FALSE;
    1976             mr_asprintf(tmp1, "Restoring big file %ld", bigfileno + 1);
    1977             update_progress_form(tmp1);
    1978             mr_free(tmp1);
    1979             res = restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
    1980             log_it("%s",pathname_of_last_biggie_restored);
    1981             if (fbw && pathname_of_last_biggie_restored[0]) {
    1982                 fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
    1983             }
    1984             retval += res;
    1985             bigfileno++;
    1986 
    1987         }
    1988     }
    1989 
    1990     if (fbw) {
    1991         fclose(fbw);
    1992         if (g_getfattr) {
    1993             mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
    1994             if (length_of_file(xattr_fname) > 0) {
    1995                 set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
    1996             }
    1997             mr_free(xattr_fname);
    1998         }
    1999         if (g_getfacl) {
    2000             mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
    2001             if (length_of_file(acl_fname) > 0) {
    2002                 set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
    2003             }
    2004             mr_free(acl_fname);
    2005         }
    2006     }
    2007     mr_free(biggies_whose_EXATs_we_should_set);
    2008 
    2009     if (does_file_exist("/PAUSE")) {
    2010         popup_and_OK("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
    2011     }
    2012     close_progress_form();
    2013     if (retval) {
    2014         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2015     } else {
    2016         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2017     }
    2018     paranoid_free(pathname_of_last_biggie_restored);
    2019     return (retval);
    2020 }
    2021 
    2022 /**************************************************************************
    2023  *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
    2024  **************************************************************************/
    2025 
    2026 
    2027 
    2028 /**
    2029  * Restore all afioballs from all CDs in the backup.
    2030  * The first CD should be inserted (if not, it will be asked for).
    2031  * @param bkpinfo The backup information structure. @c backup_media_type is the
    2032  * only field used in @e this function.
    2033  * @param filelist The node structure containing the list of files to be
    2034  * restored. If no file in some particular afioball is in this list, afio will
    2035  * still be called for that fileset, but nothing will be written.
    2036  * @return 0 for success, or the number of filesets that failed.
    2037  */
    2038 int
    2039 restore_all_tarballs_from_CD(struct s_node *filelist)
    2040 {
    2041     int retval = 0;
    2042     int res;
    2043     int attempts;
    2044     long current_tarball_number = 0L;
    2045     long max_val;
    2046   /**malloc ***/
    2047     char *mds = NULL;
    2048     char *tmp = NULL;
    2049     char *tmp1 = NULL;
    2050     char *tarball_fname = NULL;
    2051     char *progress_str = NULL;
    2052 
    2053     assert(bkpinfo != NULL);
    2054 
    2055     malloc_string(tmp);
    2056     mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
    2057     log_msg(2, "Insisting on 1st media, so that I can have a look at LAST-FILELIST-NUMBER");
    2058     if (g_current_media_number != 1) {
    2059         log_msg(3, "OK, that's jacked up.");
    2060         g_current_media_number = 1;
    2061     }
    2062     insist_on_this_cd_number(g_current_media_number);
    2063     read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
    2064     max_val = atol(tmp) + 1;
    2065     paranoid_free(tmp);
    2066 
    2067     mds = media_descriptor_string(bkpinfo->backup_media_type);
    2068     mr_asprintf(progress_str, "Restoring from %s #%d", mds, g_current_media_number);
    2069 
    2070     log_to_screen(progress_str);
    2071     open_progress_form("Restoring from archives",
    2072                        "Restoring data from the archives.",
    2073                        "Please wait. This may take some time.",
    2074                        progress_str, max_val);
    2075     for (;;) {
    2076         insist_on_this_cd_number(g_current_media_number);
    2077         update_progress_form(progress_str);
    2078         mr_free(progress_str);
    2079 
    2080         mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2", current_tarball_number);
    2081         if (!does_file_exist(tarball_fname)) {
    2082             mr_free(tarball_fname);
    2083             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz", current_tarball_number);
    2084         }
    2085         if (!does_file_exist(tarball_fname)) {
    2086             mr_free(tarball_fname);
    2087             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzma", current_tarball_number);
    2088         }
    2089         if (!does_file_exist(tarball_fname)) {
    2090             mr_free(tarball_fname);
    2091             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo", current_tarball_number);
    2092         }
    2093         if (!does_file_exist(tarball_fname)) {
    2094             mr_free(tarball_fname);
    2095             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.", current_tarball_number);
    2096         }
    2097         if (!does_file_exist(tarball_fname)) {
    2098             mr_free(tarball_fname);
    2099             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2", current_tarball_number);
    2100         }
    2101         if (!does_file_exist(tarball_fname)) {
    2102             mr_free(tarball_fname);
    2103             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.", current_tarball_number);
    2104         }
    2105         if (!does_file_exist(tarball_fname)) {
    2106             if (current_tarball_number == 0) {
    2107                 log_to_screen
    2108                     ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
    2109                 mr_free(tarball_fname);
    2110                 return (0);
    2111             }
    2112             if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
    2113                 || system("find " MNT_CDROM
    2114                           "/archives/slice* > /dev/null 2> /dev/null") ==
    2115                 0) {
    2116                 break;
    2117             }
    2118             g_current_media_number++;
    2119             mr_asprintf(progress_str, "Restoring from %s #%d", media_descriptor_string(bkpinfo->backup_media_type), g_current_media_number);
    2120             log_to_screen(progress_str);
    2121         } else {
    2122             mr_asprintf(progress_str, "Restoring from fileset #%ld on %s #%d", current_tarball_number, mds, g_current_media_number);
    2123             for (res = 999, attempts = 0; attempts < 3 && res != 0; attempts++) {
    2124                 res = restore_a_tarball_from_CD(tarball_fname, current_tarball_number, filelist);
    2125             }
    2126             mr_asprintf(tmp1, "%s #%d, fileset #%ld - restore ", mds, g_current_media_number, current_tarball_number);
    2127             if (res) {
    2128                 mr_strcat(tmp1, "reported errors");
    2129             } else if (attempts > 1) {
    2130                 mr_strcat(tmp1, "succeeded");
    2131             } else {
    2132                 mr_strcat(tmp1, "succeeded");
    2133             }
    2134             if (attempts > 1) {
    2135                 mr_strcat(tmp1, " (%d attempts) - review logs", attempts);
    2136             }
    2137             if (attempts > 1) {
    2138                 log_to_screen(tmp1);
    2139             }
    2140             mr_free(tmp1);
    2141 
    2142             retval += res;
    2143             current_tarball_number++;
    2144             g_current_progress++;
    2145         }
    2146         mr_free(tarball_fname);
    2147 
    2148         /* Now we need to umount the current media to have the next mounted by insist_on_this_cd_number */
    2149         /*   run_program_and_log_output("umount " MNT_CDROM, FALSE); */
    2150     }
    2151     mr_free(mds);
    2152     mr_free(progress_str);
    2153 
    2154     close_progress_form();
    2155     if (retval) {
    2156         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2157     } else {
    2158         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2159     }
    2160 
    2161     return (retval);
    2162 }
    2163 
    2164 /**************************************************************************
    2165  *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
    2166  **************************************************************************/
    2167 
    2168 
    2169 
    2170 /**
    2171  * Restore all biggiefiles from the currently opened stream.
    2172  * @param bkpinfo The backup information structure. Passed to other functions.
    2173  * @param filelist The node structure containing the list of files to be
    2174  * restored. If a prospective biggiefile is not in the list, it will be ignored.
    2175  * @return 0 for success, or the number of biggiefiles that failed.
    2176  */
    2177 int
    2178 restore_all_biggiefiles_from_stream(struct s_node *filelist)
    2179 {
    2180     long noof_biggiefiles;
    2181     long current_bigfile_number = 0;
    2182     long total_slices;
    2183 
    2184     int retval = 0;
    2185     int res = 0;
    2186     int ctrl_chr;
    2187 
    2188   /** malloc add ****/
    2189     char *tmp = NULL;
    2190     char *tmp1 = NULL;
    2191     char *biggie_fname;
    2192     char *biggie_cksum;
    2193     char *xattr_fname = NULL;
    2194     char *acl_fname = NULL;
    2195     char *p;
    2196     char *pathname_of_last_biggie_restored;
    2197     char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
    2198     long long biggie_size;
    2199     FILE *fbw = NULL;
    2200 
    2201     malloc_string(tmp);
    2202     malloc_string(biggie_fname);
    2203     malloc_string(biggie_cksum);
    2204     malloc_string(pathname_of_last_biggie_restored);
    2205     assert(bkpinfo != NULL);
    2206 
    2207     read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
    2208 
    2209     total_slices = atol(tmp);
    2210 
    2211     if (g_getfattr) {
    2212         mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
    2213     }
    2214     if (g_getfacl) {
    2215         mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
    2216     }
    2217     mr_asprintf(tmp1, "Reassembling large files      ");
    2218     mvaddstr_and_log_it(g_currentY, 0, tmp1);
    2219     mr_free(tmp1);
    2220 
    2221     mr_asprintf(biggies_whose_EXATs_we_should_set, "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
    2222     if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
    2223         log_msg(1, "Warning - cannot openout %s", biggies_whose_EXATs_we_should_set);
    2224     }
    2225 
    2226     // get xattr and acl files if they're there
    2227     res = read_header_block_from_stream(&biggie_size, biggie_fname, &ctrl_chr);
    2228     if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
    2229         res = read_EXAT_files_from_tape(&biggie_size, biggie_fname, &ctrl_chr, xattr_fname, acl_fname);
    2230     }
    2231 
    2232     noof_biggiefiles = atol(biggie_fname);
    2233     log_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
    2234     open_progress_form("Reassembling large files",
    2235                        "I am now reassembling all the large files.",
    2236                        "Please wait. This may take some time.",
    2237                        "", total_slices);
    2238 
    2239     for (res =
    2240          read_header_block_from_stream(&biggie_size, biggie_fname,
    2241                                        &ctrl_chr);
    2242          ctrl_chr != BLK_STOP_BIGGIEFILES;
    2243          res =
    2244          read_header_block_from_stream(&biggie_size, biggie_fname,
    2245                                        &ctrl_chr)) {
    2246         if (ctrl_chr != BLK_START_A_NORMBIGGIE
    2247             && ctrl_chr != BLK_START_A_PIHBIGGIE) {
    2248             wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
    2249         }
    2250         p = strrchr(biggie_fname, '/');
    2251         if (!p) {
    2252             p = biggie_fname;
    2253         } else {
    2254             p++;
    2255         }
    2256         mr_asprintf(tmp1, "Restoring big file %ld (%lld K)", current_bigfile_number + 1, biggie_size / 1024);
    2257         update_progress_form(tmp1);
    2258         mr_free(tmp1);
    2259         res = restore_a_biggiefile_from_stream(biggie_fname,
    2260                                                current_bigfile_number,
    2261                                                biggie_cksum,
    2262                                                biggie_size,
    2263                                                filelist, ctrl_chr,
    2264                                                pathname_of_last_biggie_restored);
    2265         log_msg(1, "I believe I have restored %s",
    2266                 pathname_of_last_biggie_restored);
    2267         if (fbw && pathname_of_last_biggie_restored[0]) {
    2268             fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
    2269         }
    2270         retval += res;
    2271         current_bigfile_number++;
    2272 
    2273     }
    2274     if (current_bigfile_number != noof_biggiefiles
    2275         && noof_biggiefiles != 0) {
    2276         log_msg(1, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n", current_bigfile_number, noof_biggiefiles);
    2277     } else {
    2278         log_msg(1, "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.", noof_biggiefiles, current_bigfile_number);
    2279     }
    2280 
    2281     if (fbw) {
    2282         fclose(fbw);
    2283         if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
    2284             log_it("Setting biggie-EXATs");
    2285             if (g_getfattr) {
    2286                 if (length_of_file(xattr_fname) > 0) {
    2287                     log_msg(1, "set_fattr_List(%s,%s)", biggies_whose_EXATs_we_should_set, xattr_fname);
    2288                     set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
    2289                 }
    2290             }
    2291             if (g_getfacl) {
    2292                 if (length_of_file(acl_fname) > 0) {
    2293                     log_msg(1, "set_acl_list(%s,%s)", biggies_whose_EXATs_we_should_set, acl_fname);
    2294                     set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
    2295                 }
    2296             }
    2297         } else {
    2298             log_it("No biggiefiles selected. So, no biggie-EXATs to set.");
    2299         }
    2300     }
    2301     mr_free(xattr_fname);
    2302     mr_free(acl_fname);
    2303     mr_free(biggies_whose_EXATs_we_should_set);
    2304 
    2305     if (does_file_exist("/PAUSE")) {
    2306         popup_and_OK
    2307             ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
    2308     }
    2309 
    2310     close_progress_form();
    2311     if (retval) {
    2312         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2313     } else {
    2314         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2315     }
    2316     paranoid_free(pathname_of_last_biggie_restored);
    2317     paranoid_free(biggie_fname);
    2318     paranoid_free(biggie_cksum);
    2319     paranoid_free(tmp);
    2320     return (retval);
    2321 }
    2322 
    2323 /**************************************************************************
    2324  *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
    2325  **************************************************************************/
    2326 
    2327 
    2328 
    2329 
    2330 
    2331 
    2332 /**
    2333  * Restore all afioballs from the currently opened tape stream.
    2334  * @param bkpinfo The backup information structure. Fields used:
    2335  * - @c bkpinfo->backup_media_type
    2336  * - @c bkpinfo->restore_path
    2337  * @param filelist The node structure containing the list of files to be
    2338  * restored. If no file in an afioball is in this list, afio will still be
    2339  * called for that fileset, but nothing will be written.
    2340  * @return 0 for success, or the number of filesets that failed.
    2341  */
    2342 int restore_all_tarballs_from_stream(struct s_node *filelist)
    2343 {
    2344     int retval = 0;
    2345     int res;
    2346     long current_afioball_number = 0;
    2347     int ctrl_chr;
    2348     long max_val /*, total_noof_files */ ;
    2349 
    2350   /** malloc **/
    2351     char *tmp = NULL;
    2352     char *mds = NULL;
    2353     char *progress_str = NULL;
    2354     char *tmp_fname;
    2355     char *xattr_fname = NULL;
    2356     char *acl_fname = NULL;
    2357 
    2358     long long tmp_size;
    2359 
    2360     malloc_string(tmp);
    2361     malloc_string(tmp_fname);
    2362     assert(bkpinfo != NULL);
    2363     mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
    2364     read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
    2365     max_val = atol(tmp) + 1;
    2366 
    2367     if (chdir(bkpinfo->restore_path)) { /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
    2368         //FIXME
    2369     }
    2370 
    2371     run_program_and_log_output("pwd", 5);
    2372 
    2373     mr_asprintf(progress_str, "Restoring from media #%d", g_current_media_number);
    2374     log_to_screen(progress_str);
    2375     open_progress_form("Restoring from archives",
    2376                        "Restoring data from the archives.",
    2377                        "Please wait. This may take some time.",
    2378                        progress_str, max_val);
    2379 
    2380     log_msg(3, "hey");
    2381 
    2382     res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
    2383     if (res) {
    2384         log_msg(2, "Warning - error reading afioball from tape");
    2385     }
    2386     retval += res;
    2387     if (ctrl_chr != BLK_START_AFIOBALLS) {
    2388         wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
    2389     }
    2390     log_msg(2, "ho");
    2391     res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
    2392     while (ctrl_chr != BLK_STOP_AFIOBALLS) {
    2393         update_progress_form(progress_str);
    2394         if (g_getfattr) {
    2395             mr_asprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir, current_afioball_number);
    2396             unlink(xattr_fname);
    2397         }
    2398         if (g_getfacl) {
    2399             mr_asprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir, current_afioball_number);
    2400             unlink(acl_fname);
    2401         }
    2402         if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
    2403             log_it("Reading EXAT files from tape");
    2404             res = read_EXAT_files_from_tape(&tmp_size, tmp_fname, &ctrl_chr, xattr_fname, acl_fname);
    2405         }
    2406         if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
    2407             wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
    2408         }
    2409         log_msg(4, "Restoring from fileset #%ld (name=%s, size=%ld K)", current_afioball_number, tmp_fname, (long) tmp_size >> 10);
    2410         res = restore_a_tarball_from_stream(tmp_fname, current_afioball_number, filelist, tmp_size, xattr_fname, acl_fname);
    2411         retval += res;
    2412         if (res) {
    2413             log_to_screen("Fileset %ld - errors occurred", current_afioball_number);
    2414         }
    2415         res =
    2416             read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
    2417         if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
    2418             wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
    2419         }
    2420 
    2421         current_afioball_number++;
    2422         g_current_progress++;
    2423         mds = media_descriptor_string(bkpinfo->backup_media_type),
    2424 
    2425         mr_free(progress_str);
    2426         mr_asprintf(progress_str, "Restoring from fileset #%ld on %s #%d", current_afioball_number, mds, g_current_media_number);
    2427         mr_free(mds);
    2428         res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
    2429         if (g_getfattr) {
    2430             unlink(xattr_fname);
    2431         }
    2432         if (g_getfacl) {
    2433             unlink(acl_fname);
    2434         }
    2435     }                           // next
    2436     mr_free(progress_str);
    2437     if (g_getfattr) {
    2438         mr_free(xattr_fname);
    2439     }
    2440     if (g_getfacl) {
    2441         mr_free(acl_fname);
    2442     }
    2443 
    2444     log_msg(1, "All done with afioballs");
    2445     close_progress_form();
    2446     if (retval) {
    2447         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2448     } else {
    2449         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2450     }
    2451     paranoid_free(tmp);
    2452     paranoid_free(tmp_fname);
    2453     return (retval);
    2454 }
    2455 
    2456 /**************************************************************************
    2457  *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
    2458  **************************************************************************/
    2459 
    2460 /* @} - end of LLrestoreGroup */
    2461 
    2462 
    2463 /**
    2464  * Restore all files in @p filelist.
    2465  * @param bkpinfo The backup information structure. Most fields are used.
    2466  * @param filelist The node structure containing the list of files to be
    2467  * restored.
    2468  * @return 0 for success, or the number of afioballs and biggiefiles that failed.
    2469  * @ingroup restoreGroup
    2470  */
    2471 int restore_everything(struct s_node *filelist)
    2472 {
    2473     int resA;
    2474     int resB;
    2475 
    2476   /** mallco ***/
    2477     char *cwd;
    2478     char *newpath;
    2479     char *tmp = NULL;
    2480     assert(bkpinfo != NULL);
    2481 
    2482     malloc_string(cwd);
    2483     malloc_string(newpath);
    2484     log_msg(2, "restore_everything() --- starting");
    2485     g_current_media_number = 1;
    2486     if (getcwd(cwd, MAX_STR_LEN - 1)) {
    2487         // FIXME
    2488     }
    2489     mr_asprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
    2490     run_program_and_log_output(tmp, FALSE);
    2491     mr_free(tmp);
    2492 
    2493     log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
    2494     if (chdir(bkpinfo->restore_path)) {
    2495         //FIXME
    2496     }
    2497     if (getcwd(newpath, MAX_STR_LEN - 1)) {
    2498         // FIXME
    2499     }
    2500     log_msg(1, "path is now %s", newpath);
    2501     log_msg(1, "restoring everything");
    2502     if (!find_home_of_exe("petris") && !g_text_mode) {
    2503         newtDrawRootText(0, g_noof_rows - 2,
    2504                          "Press ALT-<left cursor> twice to play Petris :-) ");
    2505         newtRefresh();
    2506     }
    2507     mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
    2508     mount_media();
    2509     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2510         mvaddstr_and_log_it(g_currentY++, 0,
    2511                             "Restoring OS and data from streaming media");
    2512         if (bkpinfo->backup_media_type == cdstream) {
    2513             openin_cdstream();
    2514         } else {
    2515             assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
    2516             openin_tape();
    2517         }
    2518         resA = restore_all_tarballs_from_stream(filelist);
    2519         resB = restore_all_biggiefiles_from_stream(filelist);
    2520         if (bkpinfo->backup_media_type == cdstream) {
    2521             closein_cdstream();
    2522         } else {
    2523             closein_tape();
    2524         }
    2525     } else {
    2526         mvaddstr_and_log_it(g_currentY++, 0,
    2527                             "Restoring OS and data from CD/USB   ");
    2528         resA = restore_all_tarballs_from_CD(filelist);
    2529         resB = restore_all_biggiefiles_from_CD(filelist);
    2530     }
    2531     if (chdir(cwd)) {
    2532         //FIXME
    2533     }
    2534     if (resA + resB) {
    2535         log_to_screen("Errors occurred while data was being restored.");
    2536     }
    2537     if (length_of_file("/etc/raidtab") > 0) {
    2538         log_msg(2, "Copying local raidtab to restored filesystem");
    2539         run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
    2540                                    "/etc/raidtab", FALSE);
    2541     }
    2542     kill_petris();
    2543     log_msg(2, "restore_everything() --- leaving");
    2544     paranoid_free(cwd);
    2545     paranoid_free(newpath);
    2546     return (resA + resB);
    2547 }
    2548 
    2549 /**************************************************************************
    2550  *END_RESTORE_EVERYTHING                                                  *
    2551  **************************************************************************/
    2552 
    2553 
    2554 extern void wait_until_software_raids_are_prepped(char *, int);
    2555 
    2556 
    2557 char which_restore_mode(void);
    25582537
    25592538
  • branches/3.2/mondo/test/test-mountlist.c

    r3185 r3374  
    1717
    1818extern void twenty_seconds_til_yikes(void);
    19 
    20 /* Reference to global bkpinfo */
    21 struct s_bkpinfo *bkpinfo;
    2219
    2320extern bool g_text_mode;
     
    4744extern char *MONDO_LOGFILE;
    4845extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived, char direction);
     46extern int create_raid_device_via_mdadm(struct raidlist_itself *raidlist, char *device, bool test);
     47
     48/* Reference to global bkpinfo */
     49struct s_bkpinfo *bkpinfo;
     50
    4951/* We don't have a cleanup function yet */
    5052void (*mr_cleanup)(void) = NULL;
    5153
    52 void main() {
     54int main() {
    5355
    5456struct mountlist_itself *mountlist = NULL;
  • branches/3.2/mondo/test/test-mr_stresc.c

    r3294 r3374  
    1313/* Whether we should fail immediately at first error */
    1414bool g_fail_immediately = FALSE;
     15
     16/* Reference to global bkpinfo */
     17struct s_bkpinfo *bkpinfo;
    1518
    1619void (*mr_cleanup)(void) = NULL;
  • branches/3.2/mondo/test/test-truncname.c

    r3185 r3374  
    1313
    1414extern void twenty_seconds_til_yikes(void);
    15 
    16 /* Reference to global bkpinfo */
    17 struct s_bkpinfo *bkpinfo;
    1815
    1916extern bool g_text_mode;
     
    4037char *g_getfacl;
    4138char *g_getfattr;
     39
     40/* Reference to global bkpinfo */
     41struct s_bkpinfo *bkpinfo;
    4242
    4343extern char *MONDO_LOGFILE;
Note: See TracChangeset for help on using the changeset viewer.