X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fwrite.c;h=7302193034865cd5acca1a7b716deed0cfa4c2d5;hb=1c08e96f585821ad67c8ff9180e00ddb93f6c051;hp=0aacdf13e04fc57e5abd3574c7321a929201c99c;hpb=740a1b2d814ec0f6ecaede7f195de468ce757ae9;p=wimlib diff --git a/src/write.c b/src/write.c index 0aacdf13..73021930 100644 --- a/src/write.c +++ b/src/write.c @@ -176,6 +176,9 @@ can_raw_copy(const struct wim_lookup_table_entry *lte, rspec->wim->chunk_size == out_chunk_size); } + /* XXX: For compatibility, we can't allow multiple packed resources per + * WIM. */ +#if 0 if ((rspec->flags & WIM_RESHDR_FLAG_PACKED_STREAMS) && (write_resource_flags & WRITE_RESOURCE_FLAG_PACK_STREAMS)) { @@ -198,6 +201,8 @@ can_raw_copy(const struct wim_lookup_table_entry *lte, return (write_size > rspec->uncompressed_size / 2); } +#endif + return false; } @@ -704,27 +709,48 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte, return 0; } +/* Rewrite a stream that was just written compressed as uncompressed instead. + * This function is optional, but if a stream did not compress to less than its + * original size, it might as well be written uncompressed. */ static int write_stream_uncompressed(struct wim_lookup_table_entry *lte, struct filedes *out_fd) { int ret; + u64 begin_offset = lte->out_reshdr.offset_in_wim; + u64 end_offset = out_fd->offset; + + if (filedes_seek(out_fd, begin_offset) == -1) + return 0; + + ret = extract_stream_to_fd(lte, out_fd, lte->size); + if (ret) { + /* Error reading the uncompressed data. */ + if (out_fd->offset == begin_offset && + filedes_seek(out_fd, end_offset) != -1) + { + /* Nothing was actually written yet, and we successfully + * seeked to the end of the compressed resource, so + * don't issue a hard error; just keep the compressed + * resource instead. */ + WARNING("Recovered compressed stream of " + "size %"PRIu64", continuing on.", + lte->size); + return 0; + } + return ret; + } + + wimlib_assert(out_fd->offset - begin_offset == lte->size); - 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)) + if (out_fd->offset < end_offset && + 0 != ftruncate(out_fd->fd, out_fd->offset)) { ERROR_WITH_ERRNO("Can't truncate output file to " - "offset %"PRIu64, lte->out_reshdr.offset_in_wim); + "offset %"PRIu64, out_fd->offset); 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); @@ -799,10 +825,6 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk, if (ctx->cur_write_res_offset == ctx->cur_write_res_size && !(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PACK_STREAMS)) { - struct wim_lookup_table_entry *lte; - - lte = list_entry(ctx->pending_streams.next, - struct wim_lookup_table_entry, write_streams_list); wimlib_assert(ctx->cur_write_res_offset == lte->size); /* Finished writing a stream in non-packed mode. */ @@ -1332,7 +1354,8 @@ write_stream_list(struct list_head *stream_list, ctx.write_resource_flags = write_resource_flags; ctx.filter_ctx = filter_ctx; - if (out_chunk_size != 0) { + if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) { + wimlib_assert(out_chunk_size != 0); if (out_chunk_size <= STACK_MAX) { ctx.chunk_buf = alloca(out_chunk_size); } else { @@ -1376,12 +1399,6 @@ write_stream_list(struct list_head *stream_list, * bytes needing to be compressed is less 2000000 (heuristic value). */ if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) { - if (out_ctype == WIMLIB_COMPRESSION_TYPE_LZMS && - ctx.lookup_table != NULL) { - WARNING("LZMS compression not implemented; data will " - "actually be written uncompressed."); - } - #ifdef ENABLE_MULTITHREADED_COMPRESSION if (ctx.num_bytes_to_compress >= 2000000) { ret = new_parallel_chunk_compressor(out_ctype, @@ -1486,7 +1503,7 @@ out_write_raw_copy_resources: &ctx.progress_data); out_destroy_context: - if (out_chunk_size > STACK_MAX) + if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE && out_chunk_size > STACK_MAX) FREE(ctx.chunk_buf); FREE(ctx.chunk_csizes); if (ctx.compressor) @@ -1495,6 +1512,39 @@ out_destroy_context: return ret; } +static int +wim_write_stream_list(WIMStruct *wim, + struct list_head *stream_list, + int write_flags, + unsigned num_threads, + struct filter_context *filter_ctx, + wimlib_progress_func_t progress_func) +{ + int out_ctype; + u32 out_chunk_size; + int write_resource_flags; + + write_resource_flags = write_flags_to_resource_flags(write_flags); + + if (write_resource_flags & WRITE_RESOURCE_FLAG_PACK_STREAMS) { + out_chunk_size = wim->out_pack_chunk_size; + out_ctype = wim->out_pack_compression_type; + } else { + out_chunk_size = wim->out_chunk_size; + out_ctype = wim->out_compression_type; + } + + return write_stream_list(stream_list, + &wim->out_fd, + write_resource_flags, + out_ctype, + out_chunk_size, + num_threads, + wim->lookup_table, + filter_ctx, + progress_func); +} + static int write_wim_resource(struct wim_lookup_table_entry *lte, struct filedes *out_fd, @@ -1947,15 +1997,12 @@ write_wim_streams(WIMStruct *wim, int image, int write_flags, } } - return write_stream_list(stream_list, - &wim->out_fd, - write_flags_to_resource_flags(write_flags), - wim->out_compression_type, - wim->out_chunk_size, - num_threads, - wim->lookup_table, - filter_ctx, - progress_func); + return wim_write_stream_list(wim, + stream_list, + write_flags, + num_threads, + filter_ctx, + progress_func); } static int @@ -2513,9 +2560,6 @@ write_wim_part(WIMStruct *wim, if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) DEBUG("\tPACK_STREAMS"); - if (write_flags & WIMLIB_WRITE_FLAG_NO_PACK_STREAMS) - DEBUG("\tNO_PACK_STREAMS"); - if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) DEBUG("\tFILE_DESCRIPTOR"); @@ -2564,12 +2608,6 @@ write_wim_part(WIMStruct *wim, WIMLIB_WRITE_FLAG_NOT_PIPABLE)) return WIMLIB_ERR_INVALID_PARAM; - if ((write_flags & (WIMLIB_WRITE_FLAG_PACK_STREAMS | - WIMLIB_WRITE_FLAG_NO_PACK_STREAMS)) - == (WIMLIB_WRITE_FLAG_PACK_STREAMS | - WIMLIB_WRITE_FLAG_NO_PACK_STREAMS)) - return WIMLIB_ERR_INVALID_PARAM; - /* Save previous header, then start initializing the new one. */ memcpy(&hdr_save, &wim->hdr, sizeof(struct wim_header)); @@ -2588,13 +2626,6 @@ write_wim_part(WIMStruct *wim, write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; } - if (!(write_flags & (WIMLIB_WRITE_FLAG_PACK_STREAMS | - WIMLIB_WRITE_FLAG_NO_PACK_STREAMS))) - if (wim->hdr.wim_version == WIM_VERSION_PACKED_STREAMS) { - DEBUG("WIM version 3584; default to PACK_STREAMS."); - write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS; - } - if ((write_flags & (WIMLIB_WRITE_FLAG_PIPABLE | WIMLIB_WRITE_FLAG_PACK_STREAMS)) == (WIMLIB_WRITE_FLAG_PIPABLE | @@ -2611,7 +2642,8 @@ write_wim_part(WIMStruct *wim, wim->hdr.magic = WIM_MAGIC; /* Set appropriate version number. */ - if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) + if ((write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) || + wim->out_compression_type == WIMLIB_COMPRESSION_TYPE_LZMS) wim->hdr.wim_version = WIM_VERSION_PACKED_STREAMS; else wim->hdr.wim_version = WIM_VERSION_DEFAULT; @@ -2901,20 +2933,9 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, if (wim_has_integrity_table(wim)) write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY; - /* Set default packed flag. */ - if (!(write_flags & (WIMLIB_WRITE_FLAG_PACK_STREAMS | - WIMLIB_WRITE_FLAG_NO_PACK_STREAMS))) - { - #if 0 - if (wim->hdr.wim_version == WIM_VERSION_PACKED_STREAMS) - write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS; - #endif - /* wimlib allows multiple packs in a single WIM, but they don't - * seem to be compatible with WIMGAPI. Write new streams - * unpacked. */ - } else if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) { + /* Set WIM version if adding packed streams. */ + if (write_flags & WIMLIB_WRITE_FLAG_PACK_STREAMS) wim->hdr.wim_version = WIM_VERSION_PACKED_STREAMS; - } /* Set additional flags for overwrite. */ write_flags |= WIMLIB_WRITE_FLAG_OVERWRITE | @@ -2999,15 +3020,12 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, goto out_restore_physical_hdr; } - ret = write_stream_list(&stream_list, - &wim->out_fd, - write_flags_to_resource_flags(write_flags), - wim->compression_type, - wim->chunk_size, - num_threads, - wim->lookup_table, - &filter_ctx, - progress_func); + ret = wim_write_stream_list(wim, + &stream_list, + write_flags, + num_threads, + &filter_ctx, + progress_func); if (ret) goto out_truncate;