]> wimlib.net Git - wimlib/blobdiff - src/write.c
header cleanups
[wimlib] / src / write.c
index 7da18891132f466374a1cd72766e27f7758ade82..f3c12ffe4cbc8ffacced2e635ff3a352c773a21f 100644 (file)
 #  include <sys/file.h>
 #endif
 
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "wimlib/alloca.h"
+#include "wimlib/assert.h"
 #include "wimlib/chunk_compressor.h"
 #include "wimlib/endianness.h"
 #include "wimlib/error.h"
 #include "wimlib/write.h"
 #include "wimlib/xml.h"
 
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef HAVE_ALLOCA_H
-#  include <alloca.h>
-#endif
 
 /* wimlib internal flags used when writing resources.  */
 #define WRITE_RESOURCE_FLAG_RECOMPRESS         0x00000001
@@ -517,8 +516,8 @@ end_chunk_table(struct write_streams_ctx *ctx, u64 res_actual_size,
                                                0 != (ctx->write_resource_flags &
                                                      WRITE_RESOURCE_FLAG_PACK_STREAMS));
 
-       typedef le64 __attribute__((may_alias)) aliased_le64_t;
-       typedef le32 __attribute__((may_alias)) aliased_le32_t;
+       typedef le64 _may_alias_attribute aliased_le64_t;
+       typedef le32 _may_alias_attribute aliased_le32_t;
 
        if (chunk_entry_size == 4) {
                aliased_le32_t *entries = (aliased_le32_t*)ctx->chunk_csizes;
@@ -882,7 +881,15 @@ should_rewrite_stream_uncompressed(const struct write_streams_ctx *ctx,
         * Exception: if the compressed size happens to be *exactly* the same as
         * the uncompressed size, then the stream *must* be written uncompressed
         * in order to remain compatible with the Windows Overlay Filesystem
-        * Filter Driver (WOF).  */
+        * Filter Driver (WOF).
+        *
+        * TODO: we are currently assuming that the optimization for
+        * single-chunk resources in maybe_rewrite_stream_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 ((lte->flags & WIM_RESHDR_FLAG_PACKED_STREAMS) &&
            (lte->out_reshdr.size_in_wim != lte->out_reshdr.uncompressed_size))
                return false;
@@ -890,6 +897,28 @@ should_rewrite_stream_uncompressed(const struct write_streams_ctx *ctx,
        return true;
 }
 
+static int
+maybe_rewrite_stream_uncompressed(struct write_streams_ctx *ctx,
+                                 struct wim_lookup_table_entry *lte)
+{
+       if (!should_rewrite_stream_uncompressed(ctx, lte))
+               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 &&
+           lte->out_reshdr.size_in_wim == lte->out_reshdr.uncompressed_size)
+       {
+               lte->out_reshdr.flags &= ~WIM_RESHDR_FLAG_COMPRESSED;
+               return 0;
+       }
+
+       return write_stream_uncompressed(lte, ctx->out_fd);
+}
+
 /* Write the next chunk of (typically compressed) data to the output WIM,
  * handling the writing of the chunk table.  */
 static int
@@ -996,14 +1025,10 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk,
                        if (ctx->compressor != NULL)
                                lte->out_reshdr.flags |= WIM_RESHDR_FLAG_COMPRESSED;
 
-                       if (should_rewrite_stream_uncompressed(ctx, lte)) {
-                               DEBUG("Stream of size %"PRIu64" did not compress to "
-                                     "less than original size; writing uncompressed.",
-                                     lte->size);
-                               ret = write_stream_uncompressed(lte, ctx->out_fd);
-                               if (ret)
-                                       return ret;
-                       }
+                       ret = maybe_rewrite_stream_uncompressed(ctx, lte);
+                       if (ret)
+                               return ret;
+
                        wimlib_assert(lte->out_reshdr.uncompressed_size == lte->size);
 
                        ctx->cur_write_stream_offset = 0;
@@ -3222,7 +3247,7 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, unsigned num_threads)
         * 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 (!wim->image_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
@@ -3379,8 +3404,9 @@ can_overwrite_wim_inplace(const WIMStruct *wim, int write_flags)
        if (write_flags & WIMLIB_WRITE_FLAG_REBUILD)
                return false;
 
-       /* Deletions cause full rebuild by default.  */
-       if (wim->deletion_occurred && !(write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE))
+       /* Image deletions cause full rebuild by default.  */
+       if (wim->image_deletion_occurred &&
+           !(write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE))
                return false;
 
        /* Pipable WIMs cannot be updated in place, nor can a non-pipable WIM be