X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fresource.c;h=f61ecd5ac209c457fbb6d59b1324b62557d15fca;hb=3c96d0c4ff2175676ec8e0e204032ec0e254353e;hp=ff46114d7acc6b5f0bb457a2795dde65bf96ea22;hpb=c605cbfe13201cf1c4705e38a88832518bf0c027;p=wimlib diff --git a/src/resource.c b/src/resource.c index ff46114d..f61ecd5a 100644 --- a/src/resource.c +++ b/src/resource.c @@ -90,29 +90,6 @@ */ -/* Decompress the specified chunk that uses the specified compression type - * @ctype, part of a WIM with default chunk size @wim_chunk_size. For LZX the - * separate @wim_chunk_size is needed because it determines the window size used - * for LZX compression. */ -static int -decompress(const void *cchunk, unsigned clen, void *uchunk, unsigned ulen, - int ctype, u32 wim_chunk_size) -{ - switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_LZX: - return wimlib_lzx_decompress2(cchunk, clen, - uchunk, ulen, wim_chunk_size); - case WIMLIB_COMPRESSION_TYPE_XPRESS: - return wimlib_xpress_decompress(cchunk, clen, - uchunk, ulen); - case WIMLIB_COMPRESSION_TYPE_LZMS: - return wimlib_lzms_decompress(cchunk, clen, uchunk, ulen); - default: - ERROR("Invalid compression format (%d)", ctype); - return -1; - } -} - struct data_range { u64 offset; u64 size; @@ -164,6 +141,7 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec, bool chunk_offsets_malloced = false; bool ubuf_malloced = false; bool cbuf_malloced = false; + struct wimlib_decompressor *decompressor = NULL; /* Sanity checks */ wimlib_assert(rspec != NULL); @@ -197,9 +175,9 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec, /* Get the maximum size of uncompressed chunks in this resource, which * we require be a power of 2. */ - u32 chunk_size; + u32 chunk_size = 0; u64 cur_read_offset = rspec->offset_in_wim; - int ctype; + int ctype = WIMLIB_COMPRESSION_TYPE_NONE; if (alt_chunk_table) { /* Alternate chunk table format. Its header specifies the chunk * size and compression format. */ @@ -232,6 +210,21 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec, goto out_free_memory; } + /* Get valid decompressor. */ + if (ctype == rspec->wim->decompressor_ctype && + chunk_size == rspec->wim->decompressor_max_block_size) + { + /* Cached decompressor. */ + decompressor = rspec->wim->decompressor; + rspec->wim->decompressor_ctype = WIMLIB_COMPRESSION_TYPE_NONE; + rspec->wim->decompressor = NULL; + } else { + ret = wimlib_create_decompressor(ctype, chunk_size, NULL, + &decompressor); + if (ret) + goto out_free_memory; + } + const u32 chunk_order = bsr32(chunk_size); /* Calculate the total number of chunks the resource is divided into. */ @@ -494,12 +487,11 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec, DEBUG("Decompressing chunk %"PRIu64" " "(csize=%"PRIu32" usize=%"PRIu32")", i, chunk_csize, chunk_usize); - ret = decompress(cbuf, - chunk_csize, - ubuf, - chunk_usize, - ctype, - chunk_size); + ret = wimlib_decompress(cbuf, + chunk_csize, + ubuf, + chunk_usize, + decompressor); if (ret) { ERROR("Failed to decompress data!"); ret = WIMLIB_ERR_DECOMPRESSION; @@ -556,8 +548,15 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec, goto read_error; } ret = 0; + out_free_memory: errno_save = errno; + if (decompressor) { + wimlib_free_decompressor(rspec->wim->decompressor); + rspec->wim->decompressor = decompressor; + rspec->wim->decompressor_ctype = ctype; + rspec->wim->decompressor_max_block_size = chunk_size; + } if (chunk_offsets_malloced) FREE(chunk_offsets); if (ubuf_malloced) @@ -948,6 +947,8 @@ streamifier_cb(const void *chunk, size_t size, void *_ctx) if (ctx->cur_stream_offset == ctx->cur_stream->size) { /* Finished reading all the data for a stream. */ + ctx->cur_stream_offset = 0; + DEBUG("End stream (size=%"PRIu64").", ctx->cur_stream->size); ret = (*ctx->cbs.end_stream)(ctx->cur_stream, 0, ctx->cbs.end_stream_ctx); @@ -963,7 +964,6 @@ streamifier_cb(const void *chunk, size_t size, void *_ctx) else ctx->next_stream = NULL; } - ctx->cur_stream_offset = 0; } return 0; } @@ -1323,6 +1323,15 @@ extract_stream_to_fd(struct wim_lookup_table_entry *lte, return extract_stream(lte, size, extract_chunk_to_fd, fd); } +/* Extract the full uncompressed contents of the specified stream to the + * specified file descriptor. */ +int +extract_full_stream_to_fd(struct wim_lookup_table_entry *lte, + struct filedes *fd) +{ + return extract_stream_to_fd(lte, fd, lte->size); +} + /* Calculate the SHA1 message digest of a stream and store it in @lte->hash. */ int sha1_stream(struct wim_lookup_table_entry *lte)