- read_lookup_table(): It is now an error if uncompressed resources have
different compressed and uncompressed size.
- read_lookup_table(): It is now an error if two lookup table entries have the
same SHA1 message digest.
- write_metadata_resource(): Append 20 random bytes to the end of the metadata
resource to make the metadata resource unique even if we capture exactly the
same image again.
while (num_entries--) {
const u8 *p;
while (num_entries--) {
const u8 *p;
- struct lookup_table_entry *cur_entry;
+ struct lookup_table_entry *cur_entry, *duplicate_entry;
if (fread(buf, 1, sizeof(buf), w->fp) != sizeof(buf)) {
if (feof(w->fp)) {
if (fread(buf, 1, sizeof(buf), w->fp) != sizeof(buf)) {
if (feof(w->fp)) {
p = get_u16(p, &cur_entry->part_number);
p = get_u32(p, &cur_entry->refcnt);
p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
p = get_u16(p, &cur_entry->part_number);
p = get_u32(p, &cur_entry->refcnt);
p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
+
+ duplicate_entry = __lookup_resource(table, cur_entry->hash);
+ if (duplicate_entry) {
+ ERROR("The WIM lookup table contains two entries with the "
+ "same SHA1 message digest!");
+ ERROR("The first entry is:");
+ print_lookup_table_entry(duplicate_entry);
+ ERROR("The second entry is:");
+ print_lookup_table_entry(cur_entry);
+ ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+ goto out;
+ }
lookup_table_insert(table, cur_entry);
lookup_table_insert(table, cur_entry);
+
+ if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED)
+ && (cur_entry->resource_entry.size !=
+ cur_entry->resource_entry.original_size))
+ {
+ ERROR("Found uncompressed resource with original size "
+ "not the same as compressed size");
+ ERROR("The lookup table entry for the resource is as follows:");
+ print_lookup_table_entry(cur_entry);
+ ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+ goto out;
+ }
}
DEBUG("Done reading lookup table.");
w->lookup_table = table;
}
DEBUG("Done reading lookup table.");
w->lookup_table = table;
wimlib_assert(lte->wim->fp);
ctype = wim_resource_compression_type(lte);
wimlib_assert(lte->wim->fp);
ctype = wim_resource_compression_type(lte);
- /* XXX This check should be moved elsewhere */
- if (ctype == WIM_COMPRESSION_TYPE_NONE &&
- lte->resource_entry.original_size !=
- lte->resource_entry.size) {
- ERROR("WIM resource at offset %"PRIu64", size %"PRIu64
- "has an original size of %"PRIu64", but is "
- "uncompressed",
- lte->resource_entry.offset,
- lte->resource_entry.size,
- lte->resource_entry.original_size);
- return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
- }
+ wimlib_assert(ctype != WIM_COMPRESSION_TYPE_NONE ||
+ (lte->resource_entry.original_size ==
+ lte->resource_entry.size));
if (raw || ctype == WIM_COMPRESSION_TYPE_NONE)
return read_uncompressed_resource(lte->wim->fp,
if (raw || ctype == WIM_COMPRESSION_TYPE_NONE)
return read_uncompressed_resource(lte->wim->fp,
int ret;
u64 subdir_offset;
struct dentry *root;
int ret;
u64 subdir_offset;
struct dentry *root;
- struct lookup_table_entry *lte;
+ struct lookup_table_entry *lte, *duplicate_lte;
u64 metadata_original_size;
u64 metadata_original_size;
+ /*
+ * We append 20 random bytes to the metadata resource so that we don't
+ * have identical metadata resources if we happen to append exactly the
+ * same image twice without any changes in timestamps. If this were to
+ * happen, it would cause confusion about the number and order of images
+ * in the WIM.
+ */
+ const unsigned random_tail_len = 20;
+
DEBUG("Writing metadata resource for image %d", w->current_image);
root = wim_root_dentry(w);
DEBUG("Writing metadata resource for image %d", w->current_image);
root = wim_root_dentry(w);
else
subdir_offset = 8 + root->length + 8;
calculate_subdir_offsets(root, &subdir_offset);
else
subdir_offset = 8 + root->length + 8;
calculate_subdir_offsets(root, &subdir_offset);
- metadata_original_size = subdir_offset;
+ metadata_original_size = subdir_offset + random_tail_len;
buf = MALLOC(metadata_original_size);
if (!buf) {
ERROR("Failed to allocate %"PRIu64" bytes for "
buf = MALLOC(metadata_original_size);
if (!buf) {
ERROR("Failed to allocate %"PRIu64" bytes for "
DEBUG("Writing dentry tree.");
p = write_dentry_tree(root, p);
DEBUG("Writing dentry tree.");
p = write_dentry_tree(root, p);
- wimlib_assert(p - buf == metadata_original_size);
+ randomize_byte_array(p, random_tail_len);
+ wimlib_assert(p - buf + random_tail_len == metadata_original_size);
lte = wim_metadata_lookup_table_entry(w);
lte = wim_metadata_lookup_table_entry(w);
wimlib_get_compression_type(w),
<e->output_resource_entry,
lte->hash);
wimlib_get_compression_type(w),
<e->output_resource_entry,
lte->hash);
lookup_table_unlink(w->lookup_table, lte);
lookup_table_insert(w->lookup_table, lte);
lookup_table_unlink(w->lookup_table, lte);
lookup_table_insert(w->lookup_table, lte);
+ wimlib_assert(lte->out_refcnt == 0);
lte->out_refcnt++;
lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA;
lte->out_refcnt++;
lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA;
= "Tried to select an image that does not exist in the WIM",
[WIMLIB_ERR_INVALID_INTEGRITY_TABLE]
= "The WIM's integrity table is invalid",
= "Tried to select an image that does not exist in the WIM",
[WIMLIB_ERR_INVALID_INTEGRITY_TABLE]
= "The WIM's integrity table is invalid",
+ [WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY]
+ = "An entry in the WIM's lookup table is invalid",
[WIMLIB_ERR_INVALID_PARAM]
= "An invalid parameter was given",
[WIMLIB_ERR_INVALID_RESOURCE_HASH]
[WIMLIB_ERR_INVALID_PARAM]
= "An invalid parameter was given",
[WIMLIB_ERR_INVALID_RESOURCE_HASH]
WIMLIB_ERR_INVALID_HEADER_SIZE,
WIMLIB_ERR_INVALID_IMAGE,
WIMLIB_ERR_INVALID_INTEGRITY_TABLE,
WIMLIB_ERR_INVALID_HEADER_SIZE,
WIMLIB_ERR_INVALID_IMAGE,
WIMLIB_ERR_INVALID_INTEGRITY_TABLE,
+ WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY,
WIMLIB_ERR_INVALID_PARAM,
WIMLIB_ERR_INVALID_RESOURCE_HASH,
WIMLIB_ERR_INVALID_RESOURCE_SIZE,
WIMLIB_ERR_INVALID_PARAM,
WIMLIB_ERR_INVALID_RESOURCE_HASH,
WIMLIB_ERR_INVALID_RESOURCE_SIZE,