X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwrite.c;h=0aacdf13e04fc57e5abd3574c7321a929201c99c;hp=7c39971fec0e9543c26023724b4ac3c54ba6abb3;hb=740a1b2d814ec0f6ecaede7f195de468ce757ae9;hpb=832455ca09a05ae3cd50d281a3a4a6238aeee2a9 diff --git a/src/write.c b/src/write.c index 7c39971f..0aacdf13 100644 --- a/src/write.c +++ b/src/write.c @@ -34,7 +34,7 @@ # include #endif -#include "wimlib/compress_chunks.h" +#include "wimlib/chunk_compressor.h" #include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/file_io.h" @@ -268,20 +268,6 @@ write_pwm_stream_header(const struct wim_lookup_table_entry *lte, return ret; } -#if 0 -static int -seek_and_truncate(struct filedes *out_fd, off_t offset) -{ - if (filedes_seek(out_fd, offset) == -1 || - ftruncate(out_fd->fd, offset)) - { - ERROR_WITH_ERRNO("Failed to truncate output WIM file"); - return WIMLIB_ERR_WRITE; - } - return 0; -} -#endif - struct write_streams_progress_data { wimlib_progress_func_t progress_func; union wimlib_progress_info progress; @@ -718,6 +704,33 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte, return 0; } +static int +write_stream_uncompressed(struct wim_lookup_table_entry *lte, + struct filedes *out_fd) +{ + int ret; + + if (-1 == lseek(out_fd->fd, lte->out_reshdr.offset_in_wim, SEEK_SET) || + 0 != ftruncate(out_fd->fd, lte->out_reshdr.offset_in_wim)) + { + ERROR_WITH_ERRNO("Can't truncate output file to " + "offset %"PRIu64, lte->out_reshdr.offset_in_wim); + return WIMLIB_ERR_WRITE; + } + + out_fd->offset = lte->out_reshdr.offset_in_wim; + + ret = extract_stream_to_fd(lte, out_fd, lte->size); + if (ret) + return ret; + + wimlib_assert(out_fd->offset - lte->out_reshdr.offset_in_wim == lte->size); + lte->out_reshdr.size_in_wim = lte->size; + lte->out_reshdr.flags &= ~(WIM_RESHDR_FLAG_COMPRESSED | + WIM_RESHDR_FLAG_PACKED_STREAMS); + return 0; +} + /* Write the next chunk of (typically compressed) data to the output WIM, * handling the writing of the chunk table. */ static int @@ -798,12 +811,32 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk, if (ret) return ret; - wimlib_assert(lte->out_reshdr.uncompressed_size == lte->size); - lte->out_reshdr.flags = filter_resource_flags(lte->flags); if (ctx->compressor != NULL) lte->out_reshdr.flags |= WIM_RESHDR_FLAG_COMPRESSED; + if (ctx->compressor != NULL && + lte->out_reshdr.size_in_wim >= lte->out_reshdr.uncompressed_size && + !(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) && + !(lte->flags & WIM_RESHDR_FLAG_PACKED_STREAMS)) + { + /* Stream did not compress to less than its original + * size. If we're not writing a pipable WIM (which + * could mean the output file descriptor is + * non-seekable), and the stream isn't located in a + * resource pack (which would make reading it again + * costly), truncate the file to the start of the stream + * and write it uncompressed instead. */ + DEBUG("Stream of size %"PRIu64" did not compress to " + "less than original size; writing uncompressed.", + lte->size); + ret = write_stream_uncompressed(lte, ctx->out_fd); + if (ret) + return ret; + } + + wimlib_assert(lte->out_reshdr.uncompressed_size == lte->size); + list_del(<e->write_streams_list); ctx->cur_write_res_offset = 0; } @@ -1199,11 +1232,6 @@ remove_zero_length_streams(struct list_head *stream_list) * no streams are hard-filtered or no streams are unhashed, this parameter * can be NULL. * - * @comp_ctx - * A location in which to allocate the pointer to the default LZX - * compression context. This will only be used if @out_ctype is - * WIMLIB_COMPRESSION_TYPE_LZX. - * * @progress_func * If non-NULL, a progress function that will be called periodically with * WIMLIB_PROGRESS_MSG_WRITE_STREAMS messages. Note that on-the-fly @@ -1268,7 +1296,6 @@ write_stream_list(struct list_head *stream_list, unsigned num_threads, struct wim_lookup_table *lookup_table, struct filter_context *filter_ctx, - struct wimlib_lzx_context **comp_ctx, wimlib_progress_func_t progress_func) { int ret; @@ -1355,6 +1382,7 @@ write_stream_list(struct list_head *stream_list, "actually be written uncompressed."); } + #ifdef ENABLE_MULTITHREADED_COMPRESSION if (ctx.num_bytes_to_compress >= 2000000) { ret = new_parallel_chunk_compressor(out_ctype, out_chunk_size, @@ -1365,17 +1393,11 @@ write_stream_list(struct list_head *stream_list, "(status %d)", ret); } } + #endif if (ctx.compressor == NULL) { - if (out_ctype == WIMLIB_COMPRESSION_TYPE_LZX) { - ret = wimlib_lzx_alloc_context(out_chunk_size, - NULL, - comp_ctx); - if (ret) - goto out_destroy_context; - } ret = new_serial_chunk_compressor(out_ctype, out_chunk_size, - *comp_ctx, &ctx.compressor); + &ctx.compressor); if (ret) goto out_destroy_context; } @@ -1478,8 +1500,7 @@ write_wim_resource(struct wim_lookup_table_entry *lte, struct filedes *out_fd, int out_ctype, u32 out_chunk_size, - int write_resource_flags, - struct wimlib_lzx_context **comp_ctx) + int write_resource_flags) { LIST_HEAD(stream_list); list_add(<e->write_streams_list, &stream_list); @@ -1492,7 +1513,6 @@ write_wim_resource(struct wim_lookup_table_entry *lte, 1, NULL, NULL, - comp_ctx, NULL); } @@ -1503,8 +1523,7 @@ write_wim_resource_from_buffer(const void *buf, size_t buf_size, u32 out_chunk_size, struct wim_reshdr *out_reshdr, u8 *hash, - int write_resource_flags, - struct wimlib_lzx_context **comp_ctx) + int write_resource_flags) { int ret; struct wim_lookup_table_entry *lte; @@ -1529,7 +1548,7 @@ write_wim_resource_from_buffer(const void *buf, size_t buf_size, } ret = write_wim_resource(lte, out_fd, out_ctype, out_chunk_size, - write_resource_flags, comp_ctx); + write_resource_flags); if (ret) goto out_free_lte; @@ -1936,7 +1955,6 @@ write_wim_streams(WIMStruct *wim, int image, int write_flags, num_threads, wim->lookup_table, filter_ctx, - &wim->lzx_context, progress_func); } @@ -1996,8 +2014,7 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags, &wim->out_fd, wim->out_compression_type, wim->out_chunk_size, - write_resource_flags, - &wim->lzx_context); + write_resource_flags); } if (ret) return ret; @@ -2117,8 +2134,7 @@ write_wim_lookup_table(WIMStruct *wim, int image, int write_flags, &wim->out_fd, wim->hdr.part_number, out_reshdr, - write_flags_to_resource_flags(write_flags), - &wim->lzx_context); + write_flags_to_resource_flags(write_flags)); } /* @@ -2991,7 +3007,6 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, num_threads, wim->lookup_table, &filter_ctx, - &wim->lzx_context, progress_func); if (ret) goto out_truncate;