]> wimlib.net Git - wimlib/blobdiff - src/write.c
wimlib-imagex: Allow specifying LZMS compression
[wimlib] / src / write.c
index 95365744d9b435bf754fb08c3c528fabea77697e..98ee80d8fef81df7d3d629b2b02f14ee41278633 100644 (file)
@@ -43,6 +43,9 @@
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
 #include "wimlib/resource.h"
+#ifdef __WIN32__
+#  include "wimlib/win32.h" /* win32_rename_replacement() */
+#endif
 #include "wimlib/write.h"
 #include "wimlib/xml.h"
 
@@ -220,7 +223,7 @@ stream_set_out_reshdr_for_reuse(struct wim_lookup_table_entry *lte)
 
                lte->out_res_offset_in_wim = rspec->offset_in_wim;
                lte->out_res_size_in_wim = rspec->size_in_wim;
-               lte->out_res_uncompressed_size = rspec->uncompressed_size;
+               /*lte->out_res_uncompressed_size = rspec->uncompressed_size;*/
        } else {
                wimlib_assert(!(lte->flags & WIM_RESHDR_FLAG_PACKED_STREAMS));
 
@@ -242,7 +245,7 @@ write_pwm_stream_header(const struct wim_lookup_table_entry *lte,
        u32 reshdr_flags;
        int ret;
 
-       stream_hdr.magic = PWM_STREAM_MAGIC;
+       stream_hdr.magic = cpu_to_le64(PWM_STREAM_MAGIC);
        stream_hdr.uncompressed_size = cpu_to_le64(lte->size);
        if (additional_reshdr_flags & PWM_RESHDR_FLAG_UNHASHED) {
                zero_out_hash(stream_hdr.hash);
@@ -283,31 +286,32 @@ struct write_streams_progress_data {
 
 static void
 do_write_streams_progress(struct write_streams_progress_data *progress_data,
-                         struct wim_lookup_table_entry *lte,
-                         bool stream_discarded)
+                         u64 size,
+                         bool discarded,
+                         struct wim_lookup_table_entry *cur_stream)
 {
        union wimlib_progress_info *progress = &progress_data->progress;
        bool new_wim_part;
 
-       if (stream_discarded) {
-               progress->write_streams.total_bytes -= lte->size;
+       if (discarded) {
+               progress->write_streams.total_bytes -= size;
                if (progress_data->next_progress != ~(uint64_t)0 &&
                    progress_data->next_progress > progress->write_streams.total_bytes)
                {
                        progress_data->next_progress = progress->write_streams.total_bytes;
                }
        } else {
-               progress->write_streams.completed_bytes += lte->size;
+               progress->write_streams.completed_bytes += size;
        }
        new_wim_part = false;
-       if (lte->resource_location == RESOURCE_IN_WIM &&
-           lte->rspec->wim != progress_data->prev_wim_part)
+       if (cur_stream->resource_location == RESOURCE_IN_WIM &&
+           cur_stream->rspec->wim != progress_data->prev_wim_part)
        {
                if (progress_data->prev_wim_part) {
                        new_wim_part = true;
                        progress->write_streams.completed_parts++;
                }
-               progress_data->prev_wim_part = lte->rspec->wim;
+               progress_data->prev_wim_part = cur_stream->rspec->wim;
        }
        progress->write_streams.completed_streams++;
        if (progress_data->progress_func
@@ -402,9 +406,10 @@ struct write_streams_ctx {
 };
 
 static u64
-get_chunk_entry_size(u64 res_size)
+get_chunk_entry_size(u64 res_size, int write_resource_flags)
 {
-       if (res_size <= UINT32_MAX)
+       if (res_size <= UINT32_MAX ||
+           (write_resource_flags & WIM_RESHDR_FLAG_PACKED_STREAMS))
                return 4;
        else
                return 8;
@@ -459,7 +464,9 @@ begin_chunk_table(struct write_streams_ctx *ctx, u64 res_expected_size)
                 * prove to be needed.  At this point, we just use @chunk_csizes
                 * for a buffer of 0's because the actual compressed chunk sizes
                 * are unknown.  */
-               reserve_size = expected_num_chunk_entries * get_chunk_entry_size(res_expected_size);
+               reserve_size = expected_num_chunk_entries *
+                              get_chunk_entry_size(res_expected_size,
+                                                   ctx->write_resource_flags);
                if (ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS)
                        reserve_size += sizeof(struct alt_chunk_table_header_disk);
                memset(ctx->chunk_csizes, 0, reserve_size);
@@ -505,7 +512,8 @@ end_chunk_table(struct write_streams_ctx *ctx, u64 res_actual_size,
        if (!(ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS))
                actual_num_chunk_entries--;
 
-       chunk_entry_size = get_chunk_entry_size(res_actual_size);
+       chunk_entry_size = get_chunk_entry_size(res_actual_size,
+                                               ctx->write_resource_flags);
 
        typedef le64 __attribute__((may_alias)) aliased_le64_t;
        typedef le32 __attribute__((may_alias)) aliased_le32_t;
@@ -542,7 +550,7 @@ end_chunk_table(struct write_streams_ctx *ctx, u64 res_actual_size,
 
        size_t chunk_table_size = actual_num_chunk_entries * chunk_entry_size;
        u64 res_start_offset;
-       u64 res_end_offset = ctx->out_fd->offset;
+       u64 res_end_offset;
 
        if (ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE) {
                ret = full_write(ctx->out_fd, ctx->chunk_csizes, chunk_table_size);
@@ -651,7 +659,6 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte,
        if (ctx->lookup_table != NULL && lte->unhashed && !lte->unique_size) {
 
                wimlib_assert(!is_partial_res);
-               wimlib_assert(ctx->lookup_table != NULL);
 
                struct wim_lookup_table_entry *lte_new;
 
@@ -673,7 +680,7 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte,
                                DEBUG("Discarding duplicate stream of "
                                      "length %"PRIu64, lte->size);
                                do_write_streams_progress(&ctx->progress_data,
-                                                         lte, true);
+                                                         lte->size, true, lte);
                                list_del(&lte->write_streams_list);
                                list_del(&lte->lookup_table_list);
                                if (lte_new->will_be_in_output_wim)
@@ -714,16 +721,16 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk,
 {
        int ret;
 
+       struct wim_lookup_table_entry *lte;
+
+       lte = list_entry(ctx->pending_streams.next,
+                        struct wim_lookup_table_entry, write_streams_list);
+
        if (ctx->cur_write_res_offset == 0 &&
            !(ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS))
        {
                /* Starting to write a new stream in non-packed mode.  */
 
-               struct wim_lookup_table_entry *lte;
-
-               lte = list_entry(ctx->pending_streams.next,
-                                struct wim_lookup_table_entry, write_streams_list);
-
                if (ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE) {
                        int additional_reshdr_flags = 0;
                        if (ctx->compressor != NULL)
@@ -768,6 +775,9 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk,
 
        ctx->cur_write_res_offset += usize;
 
+       do_write_streams_progress(&ctx->progress_data,
+                                 usize, false, lte);
+
        if (ctx->cur_write_res_offset == ctx->cur_write_res_size &&
            !(ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS))
        {
@@ -779,8 +789,6 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk,
 
                /* Finished writing a stream in non-packed mode.  */
 
-               do_write_streams_progress(&ctx->progress_data, lte, false);
-
                ret = end_write_resource(ctx, &lte->out_reshdr);
                if (ret)
                        return ret;
@@ -1205,6 +1213,12 @@ 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.");
+               }
+
                if (ctx.num_bytes_to_compress >= 2000000) {
                        ret = new_parallel_chunk_compressor(out_ctype,
                                                            out_chunk_size,
@@ -1241,6 +1255,11 @@ write_stream_list(struct list_head *stream_list,
 
        INIT_LIST_HEAD(&ctx.pending_streams);
 
+       if (ctx.progress_data.progress_func) {
+               (*ctx.progress_data.progress_func)(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                                                  &ctx.progress_data.progress);
+       }
+
        if (write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS) {
                ret = begin_write_resource(&ctx, ctx.num_bytes_to_compress);
                if (ret)
@@ -1296,7 +1315,7 @@ write_stream_list(struct list_head *stream_list,
                        lte->out_reshdr.offset_in_wim = offset_in_res;
                        lte->out_res_offset_in_wim = reshdr.offset_in_wim;
                        lte->out_res_size_in_wim = reshdr.size_in_wim;
-                       lte->out_res_uncompressed_size = reshdr.uncompressed_size;
+                       /*lte->out_res_uncompressed_size = reshdr.uncompressed_size;*/
                        offset_in_res += lte->size;
                }
                wimlib_assert(offset_in_res == reshdr.uncompressed_size);
@@ -1901,7 +1920,7 @@ cmp_streams_by_out_rspec(const void *p1, const void *p2)
                if (lte2->out_reshdr.flags & WIM_RESHDR_FLAG_PACKED_STREAMS)
                        return -1;
        }
-       return cmp_u64(lte1->out_reshdr.offset_in_wim, 
+       return cmp_u64(lte1->out_reshdr.offset_in_wim,
                       lte2->out_reshdr.offset_in_wim);
 }
 
@@ -2929,6 +2948,9 @@ can_overwrite_wim_inplace(const WIMStruct *wim, int write_flags)
                        return false;
                if (wim->chunk_size != wim->out_chunk_size)
                        return false;
+       } else {
+               if (write_flags & WIMLIB_WRITE_FLAG_NO_PACK_STREAMS)
+                       return false;
        }
 
        return true;