Empty file fix
authorEric Biggers <ebiggers3@gmail.com>
Sun, 20 May 2012 15:53:02 +0000 (10:53 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 20 May 2012 15:53:02 +0000 (10:53 -0500)
imagex.exe expects empty files to have a zeroed-out hash (despite the fact this
isn't actually the hash of the empty file) and no lookup table entry.  This
patch makes this the case for the WIMs that wimlib writes.

src/dentry.c
src/lookup_table.c
src/resource.c
src/sha1.c
src/sha1.h

index 6f6822ed03a4e748185e8e816560ed9ea7a254ab..7f418539a0e932ebfa9b4d96b652d6a87b4030df 100644 (file)
@@ -32,6 +32,7 @@
 #include "io.h"
 #include "timestamp.h"
 #include "lookup_table.h"
+#include "sha1.h"
 #include <unistd.h>
 #include <sys/stat.h>
 
@@ -750,7 +751,11 @@ static u8 *write_dentry(const struct dentry *dentry, u8 *p)
        p = put_u64(p, dentry->creation_time);
        p = put_u64(p, dentry->last_access_time);
        p = put_u64(p, dentry->last_write_time);
-       p = put_bytes(p, WIM_HASH_SIZE, dentry->hash);
+       if (!is_empty_file_hash(dentry->hash))
+               memcpy(p, dentry->hash, WIM_HASH_SIZE);
+       else
+               printf("zero hash for %s\n", dentry->file_name_utf8);
+       p += WIM_HASH_SIZE;
        p = put_u32(p, 0); /* reparse_tag */
        p = put_u64(p, dentry->hard_link);
        p = put_u16(p, 0); /*streams */
index 3bb77a4b221ed57fe0c746fc8a8be99c5b746bf5..46ab456198dba57caf6a88b77e73caa1953343bd 100644 (file)
@@ -264,14 +264,17 @@ int write_lookup_table_entry(struct lookup_table_entry *lte, void *__out)
 
        out = __out;
 
+       /* do not write lookup table entries for empty files */
+       if (lte->output_resource_entry.original_size == 0)
+               return 0;
+
        /* Don't write entries that have not had file resources or metadata
         * resources written for them. */
        if (lte->out_refcnt == 0)
                return 0;
 
-       if (lte->output_resource_entry.flags & WIM_RESHDR_FLAG_METADATA) {
+       if (lte->output_resource_entry.flags & WIM_RESHDR_FLAG_METADATA)
                DEBUG("Writing metadata entry at %lu\n", ftello(out));
-       }
 
        p = put_resource_entry(buf, &lte->output_resource_entry);
        p = put_u16(p, lte->part_number);
index b525f22873e0acec892296e970ad54c7eff9c3f9..e29434fc295bee0592bf09205ff0748b839f3ee6 100644 (file)
@@ -1112,8 +1112,6 @@ int write_file_resource(struct dentry *dentry, void *wim_p)
        struct lookup_table_entry *lte;
        int in_wim_ctype;
        int out_wim_ctype;
-       int input_res_ctype;
-       struct resource_entry *input_res_entry;
        struct resource_entry *output_res_entry;
        u64 len;
        int ret;
@@ -1138,6 +1136,10 @@ int write_file_resource(struct dentry *dentry, void *wim_p)
        out_wim_ctype = wimlib_get_compression_type(w);
        output_res_entry = &lte->output_resource_entry;
 
+       /* do not write empty resources */
+       if (lte->resource_entry.original_size == 0)
+               return 0;
+
        /* Figure out if we can read the resource from the WIM file, or
         * if we have to read it from the filesystem outside. */
        if (lte->file_on_disk) {
@@ -1175,15 +1177,14 @@ int write_file_resource(struct dentry *dentry, void *wim_p)
                        in = w->fp;
                        in_wim_ctype = out_wim_ctype;
                }
-               input_res_entry = &lte->resource_entry;
-               input_res_ctype = resource_compression_type(
+               int input_res_ctype = resource_compression_type(
                                        in_wim_ctype, 
-                                       input_res_entry->flags);
+                                       lte->resource_entry.flags);
 
                ret = transfer_file_resource(in, 
-                                       input_res_entry->size,
-                                       input_res_entry->original_size, 
-                                       input_res_entry->offset,
+                                       lte->resource_entry.size,
+                                       lte->resource_entry.original_size, 
+                                       lte->resource_entry.offset,
                                        input_res_ctype, 
                                        out, 
                                        out_wim_ctype,
index b0746bce507610aa14af6a7f46a21d67ef91ff05..ff582ed9da50ccaa2429b3ae6a6e2ce145ccc284 100644 (file)
 #error "invalid BLOCKSIZE"
 #endif
 
+const u8 empty_file_sha1sum[SHA1_HASH_SIZE] = {
+       0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 
+       0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09,
+};
+
 
 #ifdef WITH_LIBCRYPTO
 
index e73b62a87881ad16f1ae19d1ce6cd0e33d6b5677..7ec8456d20cee8cf633c51ef04617bfa1024cdf0 100644 (file)
@@ -4,6 +4,16 @@
 #include "config.h"
 #include <stdio.h>
 #include <stddef.h>
+#include "string.h"
+
+#define SHA1_HASH_SIZE 20
+
+extern const u8 empty_file_sha1sum[SHA1_HASH_SIZE];
+
+static inline bool is_empty_file_hash(const u8 hash[SHA1_HASH_SIZE])
+{
+       return memcmp(hash, empty_file_sha1sum, SHA1_HASH_SIZE) == 0;
+}
 
 /* Compute SHA1 message digest for bytes read from STREAM.  The
    resulting message digest number will be written into the 20 bytes