]> wimlib.net Git - wimlib/blobdiff - src/write.c
write.c: send first WRITE_STREAMS message before writing raw copy blobs
[wimlib] / src / write.c
index 0a899945620acd59f04ddc6239fb2d37abdebd91..bc7b6ebde872159d997dee3a08fa48a377cfdc91 100644 (file)
@@ -1340,17 +1340,6 @@ validate_blob_list(struct list_head *blob_list)
        }
 }
 
-static inline bool
-blob_is_in_file(const struct blob_descriptor *blob)
-{
-       return blob->blob_location == BLOB_IN_FILE_ON_DISK
-#ifdef __WIN32__
-           || blob->blob_location == BLOB_IN_WINNT_FILE_ON_DISK
-           || blob->blob_location == BLOB_WIN32_ENCRYPTED
-#endif
-          ;
-}
-
 static void
 init_done_with_file_info(struct list_head *blob_list)
 {
@@ -1551,21 +1540,12 @@ write_blob_list(struct list_head *blob_list,
                                               out_ctype, out_chunk_size,
                                               &raw_copy_blobs);
 
-       /* Copy any compressed resources for which the raw data can be reused
-        * without decompression.  */
-       ret = write_raw_copy_resources(&raw_copy_blobs, ctx.out_fd,
-                                      &ctx.progress_data);
-
-       if (ret || num_nonraw_bytes == 0)
-               goto out_destroy_context;
-
-       /* Unless uncompressed output was required, allocate a chunk_compressor
-        * to do compression.  There are serial and parallel implementations of
-        * the chunk_compressor interface.  We default to parallel using the
+       /* Unless no data needs to be compressed, allocate a chunk_compressor to
+        * do compression.  There are serial and parallel implementations of the
+        * chunk_compressor interface.  We default to parallel using the
         * specified number of threads, unless the upper bound on the number
         * bytes needing to be compressed is less than a heuristic value.  */
-       if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) {
-
+       if (num_nonraw_bytes != 0 && out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) {
        #ifdef ENABLE_MULTITHREADED_COMPRESSION
                if (num_nonraw_bytes > max(2000000, out_chunk_size)) {
                        ret = new_parallel_chunk_compressor(out_ctype,
@@ -1593,9 +1573,6 @@ write_blob_list(struct list_head *blob_list,
        else
                ctx.progress_data.progress.write_streams.num_threads = 1;
 
-       INIT_LIST_HEAD(&ctx.blobs_being_compressed);
-       INIT_LIST_HEAD(&ctx.blobs_in_solid_resource);
-
        ret = call_progress(ctx.progress_data.progfunc,
                            WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
                            &ctx.progress_data.progress,
@@ -1603,7 +1580,20 @@ write_blob_list(struct list_head *blob_list,
        if (ret)
                goto out_destroy_context;
 
+       /* Copy any compressed resources for which the raw data can be reused
+        * without decompression.  */
+       ret = write_raw_copy_resources(&raw_copy_blobs, ctx.out_fd,
+                                      &ctx.progress_data);
+
+       if (ret || num_nonraw_bytes == 0)
+               goto out_destroy_context;
+
+       INIT_LIST_HEAD(&ctx.blobs_being_compressed);
+
        if (write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
+
+               INIT_LIST_HEAD(&ctx.blobs_in_solid_resource);
+
                ret = begin_write_resource(&ctx, num_nonraw_bytes);
                if (ret)
                        goto out_destroy_context;
@@ -2639,6 +2629,25 @@ should_default_to_solid_compression(WIMStruct *wim, int write_flags)
                wim_has_solid_resources(wim);
 }
 
+/* Update the images' filecount/bytecount stats (in the XML info) to take into
+ * account any recent modifications.  */
+static int
+update_image_stats(WIMStruct *wim)
+{
+       if (!wim_has_metadata(wim))
+               return 0;
+       for (int i = 0; i < wim->hdr.image_count; i++) {
+               struct wim_image_metadata *imd = wim->image_metadata[i];
+               if (imd->stats_outdated) {
+                       int ret = xml_update_image_info(wim, i + 1);
+                       if (ret)
+                               return ret;
+                       imd->stats_outdated = false;
+               }
+       }
+       return 0;
+}
+
 /* Write a standalone WIM or split WIM (SWM) part to a new file or to a file
  * descriptor.  */
 int
@@ -2786,6 +2795,11 @@ write_wim_part(WIMStruct *wim,
                        wim->out_hdr.boot_idx = 1;
        }
 
+       /* Update image stats if needed.  */
+       ret = update_image_stats(wim);
+       if (ret)
+               return ret;
+
        /* Set up the output file descriptor.  */
        if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) {
                /* File descriptor was explicitly provided.  */
@@ -2937,6 +2951,20 @@ check_resource_offsets(WIMStruct *wim, off_t end_offset)
        return 0;
 }
 
+static int
+free_blob_if_invalidated(struct blob_descriptor *blob, void *_wim)
+{
+       const WIMStruct *wim = _wim;
+
+       if (!blob->will_be_in_output_wim &&
+           blob->blob_location == BLOB_IN_WIM && blob->rdesc->wim == wim)
+       {
+               blob_table_unlink(wim->blob_table, blob);
+               free_blob_descriptor(blob);
+       }
+       return 0;
+}
+
 /*
  * Overwrite a WIM, possibly appending new resources to it.
  *
@@ -3053,6 +3081,11 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, unsigned num_threads)
                if (ret)
                        goto out;
 
+               /* Prevent new files from being deduplicated with existing blobs
+                * in the WIM that we haven't decided to write.  Such blobs will
+                * be overwritten during the compaction.  */
+               for_blob_in_table(wim->blob_table, free_blob_if_invalidated, wim);
+
                if (wim_has_metadata(wim)) {
                        /* Add existing metadata resources to be compacted along
                         * with the file resources.  */
@@ -3130,6 +3163,11 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, unsigned num_threads)
                        wimlib_assert(list_empty(&blob_list));
        }
 
+       /* Update image stats if needed.  */
+       ret = update_image_stats(wim);
+       if (ret)
+               goto out;
+
        ret = open_wim_writable(wim, wim->filename, O_RDWR);
        if (ret)
                goto out;