]> wimlib.net Git - wimlib/blobdiff - src/write.c
wimlib_overwrite()): Change WIM version when appropriate
[wimlib] / src / write.c
index 2673081ae9a57b1d3e6b1ac104f5aabd5ae52088..09b74ec16c8b273ef9c94360c75eaea428fdf36f 100644 (file)
@@ -286,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
@@ -679,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)
@@ -720,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)
@@ -774,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))
        {
@@ -785,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;
@@ -1211,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,
@@ -1247,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)
@@ -2723,6 +2736,9 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
 
        DEBUG("Overwriting `%"TS"' in-place", wim->filename);
 
+       /* Save original header so it can be restored in case of error  */
+       memcpy(&hdr_save, &wim->hdr, sizeof(struct wim_header));
+
        /* Set default integrity flag.  */
        if (!(write_flags & (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
                             WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY)))
@@ -2732,8 +2748,12 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
        /* Set default packed flag.  */
        if (!(write_flags & (WIMLIB_WRITE_FLAG_PACK_STREAMS |
                             WIMLIB_WRITE_FLAG_NO_PACK_STREAMS)))
+       {
                if (wim->hdr.wim_version == WIM_VERSION_PACKED_STREAMS)
                        write_flags |= WIMLIB_WRITE_FLAG_PACK_STREAMS;
+       } else 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 |
@@ -2750,12 +2770,14 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
        if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0 &&
            wim->hdr.integrity_table_reshdr.offset_in_wim < old_xml_end) {
                WARNING("Didn't expect the integrity table to be before the XML data");
-               return WIMLIB_ERR_RESOURCE_ORDER;
+               ret = WIMLIB_ERR_RESOURCE_ORDER;
+               goto out_restore_memory_hdr;
        }
 
        if (old_lookup_table_end > old_xml_begin) {
                WARNING("Didn't expect the lookup table to be after the XML data");
-               return WIMLIB_ERR_RESOURCE_ORDER;
+               ret = WIMLIB_ERR_RESOURCE_ORDER;
+               goto out_restore_memory_hdr;
        }
 
        /* Set @old_wim_end, which indicates the point beyond which we don't
@@ -2786,31 +2808,28 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
 
        ret = check_resource_offsets(wim, old_wim_end);
        if (ret)
-               return ret;
+               goto out_restore_memory_hdr;
 
        ret = prepare_stream_list_for_write(wim, WIMLIB_ALL_IMAGES, write_flags,
                                            &stream_list, &lookup_table_list,
                                            &filter_ctx);
        if (ret)
-               return ret;
+               goto out_restore_memory_hdr;
 
        ret = open_wim_writable(wim, wim->filename, O_RDWR);
        if (ret)
-               return ret;
+               goto out_restore_memory_hdr;
 
        ret = lock_wim(wim, wim->out_fd.fd);
        if (ret)
                goto out_close_wim;
 
-       /* Save original header so it can be restored in case of error  */
-       memcpy(&hdr_save, &wim->hdr, sizeof(struct wim_header));
-
        /* Set WIM_HDR_FLAG_WRITE_IN_PROGRESS flag in header. */
        wim->hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
        ret = write_wim_header_flags(wim->hdr.flags, &wim->out_fd);
        if (ret) {
                ERROR_WITH_ERRNO("Error updating WIM header flags");
-               goto out_restore_memory_hdr;
+               goto out_unlock_wim;
        }
 
        if (filedes_seek(&wim->out_fd, old_wim_end) == -1) {
@@ -2843,7 +2862,8 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
        if (ret)
                goto out_truncate;
 
-       goto out_unlock_wim;
+       wim->wim_locked = 0;
+       return 0;
 
 out_truncate:
        if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
@@ -2855,12 +2875,12 @@ out_truncate:
        }
 out_restore_physical_hdr:
        (void)write_wim_header_flags(hdr_save.flags, &wim->out_fd);
-out_restore_memory_hdr:
-       memcpy(&wim->hdr, &hdr_save, sizeof(struct wim_header));
-out_close_wim:
-       (void)close_wim_writable(wim, write_flags);
 out_unlock_wim:
        wim->wim_locked = 0;
+out_close_wim:
+       (void)close_wim_writable(wim, write_flags);
+out_restore_memory_hdr:
+       memcpy(&wim->hdr, &hdr_save, sizeof(struct wim_header));
        return ret;
 }
 
@@ -2930,15 +2950,10 @@ can_overwrite_wim_inplace(const WIMStruct *wim, int write_flags)
        if (wim_is_pipable(wim) || (write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
                return false;
 
-       if (wim->hdr.wim_version != WIM_VERSION_PACKED_STREAMS) {
-               if (wim->compression_type != wim->out_compression_type)
-                       return false;
-               if (wim->chunk_size != wim->out_chunk_size)
-                       return false;
-       } else {
-               if (write_flags & WIMLIB_WRITE_FLAG_NO_PACK_STREAMS)
-                       return false;
-       }
+       if (wim->compression_type != wim->out_compression_type)
+               return false;
+       if (wim->chunk_size != wim->out_chunk_size)
+               return false;
 
        return true;
 }