- /* 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 |
- WIMLIB_WRITE_FLAG_STREAMS_OK;
-
- /* Make sure that the integrity table (if present) is after the XML
- * data, and that there are no stream resources, metadata resources, or
- * lookup tables after the XML data. Otherwise, these data would be
- * overwritten. */
- old_xml_begin = wim->hdr.xml_data_reshdr.offset_in_wim;
- old_xml_end = old_xml_begin + wim->hdr.xml_data_reshdr.size_in_wim;
- old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
- wim->hdr.lookup_table_reshdr.size_in_wim;
- 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");
- 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");
- ret = WIMLIB_ERR_RESOURCE_ORDER;
- goto out_restore_memory_hdr;
- }
-
- /* Set @old_wim_end, which indicates the point beyond which we don't
- * allow any file and metadata resources to appear without returning
- * WIMLIB_ERR_RESOURCE_ORDER (due to the fact that we would otherwise
- * overwrite these resources). */
- if (!wim->deletion_occurred && !any_images_modified(wim)) {
- /* If no images have been modified and no images have been
- * deleted, a new lookup table does not need to be written. We
- * shall write the new XML data and optional integrity table
- * immediately after the lookup table. Note that this may
- * overwrite an existing integrity table. */
- DEBUG("Skipping writing lookup table "
- "(no images modified or deleted)");
- old_wim_end = old_lookup_table_end;
- write_flags |= WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE |
- WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML;
- } else if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0) {
- /* Old WIM has an integrity table; begin writing new streams
- * after it. */
- old_wim_end = wim->hdr.integrity_table_reshdr.offset_in_wim +
- wim->hdr.integrity_table_reshdr.size_in_wim;
+ /* Start preparing the updated file header. */
+ memcpy(&wim->out_hdr, &wim->hdr, sizeof(wim->out_hdr));
+
+ /* If using solid compression, the version number must be set to
+ * WIM_VERSION_SOLID. */
+ if (write_flags & WIMLIB_WRITE_FLAG_SOLID)
+ wim->out_hdr.wim_version = WIM_VERSION_SOLID;
+
+ /* Default to solid compression if it is valid in the chosen WIM file
+ * format and the WIMStruct references any solid resources. This is
+ * useful when updating a solid WIM. */
+ if (should_default_to_solid_compression(wim, write_flags))
+ write_flags |= WIMLIB_WRITE_FLAG_SOLID;
+
+ if (unlikely(write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)) {
+
+ /* In-place compaction */
+
+ WARNING("The WIM file \"%"TS"\" is being compacted in place.\n"
+ " Do *not* interrupt the operation, or else "
+ "the WIM file will be\n"
+ " corrupted!", wim->filename);
+ wim->being_compacted = 1;
+ old_wim_end = WIM_HEADER_DISK_SIZE;
+
+ ret = prepare_blob_list_for_write(wim, WIMLIB_ALL_IMAGES,
+ write_flags, &blob_list,
+ &blob_table_list, &filter_ctx);
+ if (ret)
+ goto out;
+
+ if (wim_has_metadata(wim)) {
+ /* Add existing metadata resources to be compacted along
+ * with the file resources. */
+ for (int i = 0; i < wim->hdr.image_count; i++) {
+ struct wim_image_metadata *imd = wim->image_metadata[i];
+ if (!imd->modified) {
+ fully_reference_blob_for_write(imd->metadata_blob,
+ &blob_list);
+ }
+ }
+ }