+/* Returns true if the specified blob, which was written as a non-solid
+ * resource, should be truncated from the WIM file and re-written uncompressed.
+ * blob->out_reshdr must be filled in from the initial write of the blob. */
+static bool
+should_rewrite_blob_uncompressed(const struct write_blobs_ctx *ctx,
+ const struct blob_descriptor *blob)
+{
+ /* If the compressed data is smaller than the uncompressed data, prefer
+ * the compressed data. */
+ if (blob->out_reshdr.size_in_wim < blob->out_reshdr.uncompressed_size)
+ return false;
+
+ /* If we're not actually writing compressed data, then there's no need
+ * for re-writing. */
+ if (!ctx->compressor)
+ return false;
+
+ /* If writing a pipable WIM, everything we write to the output is final
+ * (it might actually be a pipe!). */
+ if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE)
+ return false;
+
+ /* If the blob that would need to be re-read is located in a solid
+ * resource in another WIM file, then re-reading it would be costly. So
+ * don't do it.
+ *
+ * Exception: if the compressed size happens to be *exactly* the same as
+ * the uncompressed size, then the blob *must* be written uncompressed
+ * in order to remain compatible with the Windows Overlay Filesystem
+ * Filter Driver (WOF).
+ *
+ * TODO: we are currently assuming that the optimization for
+ * single-chunk resources in maybe_rewrite_blob_uncompressed() prevents
+ * this case from being triggered too often. To fully prevent excessive
+ * decompressions in degenerate cases, we really should obtain the
+ * uncompressed data by decompressing the compressed data we wrote to
+ * the output file.
+ */
+ if (blob->blob_location == BLOB_IN_WIM &&
+ blob->size != blob->rdesc->uncompressed_size &&
+ blob->size != blob->out_reshdr.size_in_wim)
+ return false;
+
+ return true;
+}
+
+static int
+maybe_rewrite_blob_uncompressed(struct write_blobs_ctx *ctx,
+ struct blob_descriptor *blob)
+{
+ if (!should_rewrite_blob_uncompressed(ctx, blob))
+ return 0;
+
+ /* Regular (non-solid) WIM resources with exactly one chunk and
+ * compressed size equal to uncompressed size are exactly the same as
+ * the corresponding compressed data --- since there must be 0 entries
+ * in the chunk table and the only chunk must be stored uncompressed.
+ * In this case, there's no need to rewrite anything. */
+ if (ctx->chunk_index == 1 &&
+ blob->out_reshdr.size_in_wim == blob->out_reshdr.uncompressed_size)
+ {
+ blob->out_reshdr.flags &= ~WIM_RESHDR_FLAG_COMPRESSED;
+ return 0;
+ }
+
+ return write_blob_uncompressed(blob, ctx->out_fd);
+}
+