From: Eric Biggers Date: Sun, 20 May 2012 15:53:02 +0000 (-0500) Subject: Empty file fix X-Git-Tag: v0.7.1~6 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=751a849fe04a9230a661e38429ff4d971f74bdbf;hp=f988d892c603e72d1c0a722c2b02b2418ff68c1e Empty file fix 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. --- diff --git a/src/dentry.c b/src/dentry.c index 6f6822ed..7f418539 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -32,6 +32,7 @@ #include "io.h" #include "timestamp.h" #include "lookup_table.h" +#include "sha1.h" #include #include @@ -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 */ diff --git a/src/lookup_table.c b/src/lookup_table.c index 3bb77a4b..46ab4561 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -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, <e->output_resource_entry); p = put_u16(p, lte->part_number); diff --git a/src/resource.c b/src/resource.c index b525f228..e29434fc 100644 --- a/src/resource.c +++ b/src/resource.c @@ -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 = <e->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 = <e->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, diff --git a/src/sha1.c b/src/sha1.c index b0746bce..ff582ed9 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -38,6 +38,11 @@ #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 diff --git a/src/sha1.h b/src/sha1.h index e73b62a8..7ec8456d 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -4,6 +4,16 @@ #include "config.h" #include #include +#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