From: Eric Biggers Date: Sun, 27 Apr 2014 05:03:51 +0000 (-0500) Subject: Handle inconsistent uncompressed resources in same way as WIMGAPI X-Git-Tag: v1.7.0~260 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=b24275706ca80ffd423fbb91557199f7289191ac Handle inconsistent uncompressed resources in same way as WIMGAPI --- diff --git a/src/lookup_table.c b/src/lookup_table.c index 2cca979c..1058bf26 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -684,9 +684,27 @@ read_wim_lookup_table(WIMStruct *wim) if (!(reshdr.flags & (WIM_RESHDR_FLAG_PACKED_STREAMS | WIM_RESHDR_FLAG_COMPRESSED))) { if (reshdr.uncompressed_size != reshdr.size_in_wim) { - ERROR("Invalid resource entry!"); - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto err; + /* So ... This is an uncompressed resource, but + * its uncompressed size is NOT the same as its + * "compressed" size (size_in_wim). What to do + * with it? + * + * Based on a simple test, WIMGAPI seems to + * handle this as follows: + * + * if (size_in_wim > uncompressed_size) { + * Ignore uncompressed_size; use + * size_in_wim instead. + * } else { + * Honor uncompressed_size, but treat the + * part of the file data above size_in_wim + * as all zeros. + * } + * + * So we will do the same. + */ + if (reshdr.size_in_wim > reshdr.uncompressed_size) + reshdr.uncompressed_size = reshdr.size_in_wim; } } diff --git a/src/resource.c b/src/resource.c index b45db597..b5db1452 100644 --- a/src/resource.c +++ b/src/resource.c @@ -562,6 +562,28 @@ read_error: goto out_free_memory; } +static int +fill_zeroes(u64 size, consume_data_callback_t cb, void *cb_ctx) +{ + if (unlikely(size)) { + u8 buf[min(size, BUFFER_SIZE)]; + + memset(buf, 0, sizeof(buf)); + + do { + size_t len; + int ret; + + len = min(size, BUFFER_SIZE); + ret = cb(buf, len, cb_ctx); + if (ret) + return ret; + size -= len; + } while (size); + } + return 0; +} + /* Read raw data from a file descriptor at the specified offset, feeding the * data it in chunks into the specified callback function. */ static int @@ -654,11 +676,37 @@ read_partial_wim_resource(const struct wim_resource_spec *rspec, return read_compressed_wim_resource(rspec, &range, 1, cb, cb_ctx); } else { - return read_raw_file_data(&rspec->wim->in_fd, - rspec->offset_in_wim + offset, - size, - cb, - cb_ctx); + /* Reading uncompressed resource. For completeness, handle the + * weird case where size_in_wim < uncompressed_size. */ + + u64 read_size; + u64 zeroes_size; + int ret; + + if (likely(offset + size <= rspec->size_in_wim) || + rspec->is_pipable) + { + read_size = size; + zeroes_size = 0; + } else { + if (offset >= rspec->size_in_wim) { + read_size = 0; + zeroes_size = size; + } else { + read_size = rspec->size_in_wim - offset; + zeroes_size = offset + size - rspec->size_in_wim; + } + } + + ret = read_raw_file_data(&rspec->wim->in_fd, + rspec->offset_in_wim + offset, + read_size, + cb, + cb_ctx); + if (ret) + return ret; + + return fill_zeroes(zeroes_size, cb, cb_ctx); } }