X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Flookup_table.c;h=66ff69dd8fae2b3fe62adad8759f1f15b1609463;hp=a24cf68887d40a4246d3a29ad7639e29f67fb506;hb=bb11c4650a416d1eaf6c8f8385c3c6e4d5e0eff3;hpb=19fd5bbc4f64cc8bf735f7c2c0bb864876998cf4 diff --git a/src/lookup_table.c b/src/lookup_table.c index a24cf688..66ff69dd 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -405,8 +405,11 @@ read_lookup_table(WIMStruct *w) num_entries = w->hdr.lookup_table_res_entry.size / sizeof(struct wim_lookup_table_entry_disk); table = new_lookup_table(num_entries * 2 + 1); - if (!table) + if (!table) { + ERROR("Failed to allocate stream hash table of size %zu", + num_entries * 2 + 1); return WIMLIB_ERR_NOMEM; + } w->current_image = 0; offset = w->hdr.lookup_table_res_entry.offset; @@ -444,58 +447,72 @@ read_lookup_table(WIMStruct *w) cur_entry->refcnt = le32_to_cpu(disk_entry->refcnt); copy_hash(cur_entry->hash, disk_entry->hash); + if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) + cur_entry->compression_type = w->compression_type; + else + BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0); + if (cur_entry->part_number != w->hdr.part_number) { - ERROR("A lookup table entry in part %hu of the WIM " - "points to part %hu", - w->hdr.part_number, cur_entry->part_number); - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + WARNING("A lookup table entry in part %hu of the WIM " + "points to part %hu (ignoring it)", + w->hdr.part_number, cur_entry->part_number); + free_lookup_table_entry(cur_entry); + continue; } if (is_zero_hash(cur_entry->hash)) { - ERROR("The WIM lookup table contains an entry with a " - "SHA1 message digest of all 0's"); - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + WARNING("The WIM lookup table contains an entry with a " + "SHA1 message digest of all 0's (ignoring it)"); + free_lookup_table_entry(cur_entry); + continue; } if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) && (cur_entry->resource_entry.size != cur_entry->resource_entry.original_size)) { - #ifdef ENABLE_ERROR_MESSAGES - 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, stderr); - #endif - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + if (wimlib_print_errors) { + WARNING("Found uncompressed resource with " + "original size (%"PRIu64") not the same " + "as compressed size (%"PRIu64")", + cur_entry->resource_entry.original_size, + cur_entry->resource_entry.size); + if (cur_entry->resource_entry.original_size) { + WARNING("Overriding compressed size with original size."); + cur_entry->resource_entry.size = + cur_entry->resource_entry.original_size; + } else { + WARNING("Overriding original size with compressed size"); + cur_entry->resource_entry.original_size = + cur_entry->resource_entry.size; + } + } } if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) { /* Lookup table entry for a metadata resource */ if (cur_entry->refcnt != 1) { - #ifdef ENABLE_ERROR_MESSAGES - ERROR("Found metadata resource with refcnt != 1:"); - print_lookup_table_entry(cur_entry, stderr); - #endif + if (wimlib_print_errors) { + ERROR("Found metadata resource with refcnt != 1:"); + print_lookup_table_entry(cur_entry, stderr); + } ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; goto out_free_cur_entry; } if (w->hdr.part_number != 1) { - ERROR("Found a metadata resource in a " - "non-first part of the split WIM!"); - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + WARNING("Ignoring metadata resource found in a " + "non-first part of the split WIM"); + free_lookup_table_entry(cur_entry); + continue; } if (w->current_image == w->hdr.image_count) { - ERROR("The WIM header says there are %u images " - "in the WIM, but we found more metadata " - "resources than this", w->hdr.image_count); - ret = WIMLIB_ERR_IMAGE_COUNT; - goto out_free_cur_entry; + WARNING("The WIM header says there are %u images " + "in the WIM, but we found more metadata " + "resources than this (ignoring the extra)", + w->hdr.image_count); + free_lookup_table_entry(cur_entry); + continue; } /* Notice very carefully: We are assigning the metadata @@ -516,28 +533,31 @@ read_lookup_table(WIMStruct *w) * metadata resource */ duplicate_entry = __lookup_resource(table, cur_entry->hash); if (duplicate_entry) { - #ifdef ENABLE_ERROR_MESSAGES - 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, stderr); - ERROR("The second entry is:"); - print_lookup_table_entry(cur_entry, stderr); - #endif - ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY; - goto out_free_cur_entry; + if (wimlib_print_errors) { + WARNING("The WIM lookup table contains two entries with the " + "same SHA1 message digest!"); + WARNING("The first entry is:"); + print_lookup_table_entry(duplicate_entry, stderr); + WARNING("The second entry is:"); + print_lookup_table_entry(cur_entry, stderr); + } + free_lookup_table_entry(cur_entry); + continue; + } else { + lookup_table_insert(table, cur_entry); } - lookup_table_insert(table, cur_entry); } } - if (w->hdr.part_number == 1 && w->current_image != w->hdr.image_count) - { - ERROR("The WIM header says there are %u images " - "in the WIM, but we only found %d metadata " - "resources!", w->hdr.image_count, w->current_image); - ret = WIMLIB_ERR_IMAGE_COUNT; - goto out_free_lookup_table; + if (w->hdr.part_number == 1 && w->current_image != w->hdr.image_count) { + WARNING("The header of \"%"TS"\" says there are %u images in\n" + " the WIM, but we only found %d metadata resources! Acting as if\n" + " the header specified only %d images instead.", + w->filename, w->hdr.image_count, + w->current_image, w->current_image); + for (int i = w->current_image; i < w->hdr.image_count; i++) + put_image_metadata(w->image_metadata[i], NULL); + w->hdr.image_count = w->current_image; } DEBUG("Done reading lookup table."); w->lookup_table = table; @@ -747,6 +767,58 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) tputc(T('\n'), out); } +void +lte_to_wimlib_resource_entry(const struct wim_lookup_table_entry *lte, + struct wimlib_resource_entry *wentry) +{ + wentry->uncompressed_size = lte->resource_entry.original_size; + wentry->compressed_size = lte->resource_entry.size; + wentry->offset = lte->resource_entry.offset; + copy_hash(wentry->sha1_hash, lte->hash); + wentry->part_number = lte->part_number; + wentry->reference_count = lte->refcnt; + wentry->is_compressed = (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) != 0; + wentry->is_metadata = (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) != 0; + wentry->is_free = (lte->resource_entry.flags & WIM_RESHDR_FLAG_FREE) != 0; + wentry->is_spanned = (lte->resource_entry.flags & WIM_RESHDR_FLAG_SPANNED) != 0; +} + +struct iterate_lte_context { + wimlib_iterate_lookup_table_callback_t cb; + void *user_ctx; +}; + +static int +do_iterate_lte(struct wim_lookup_table_entry *lte, void *_ctx) +{ + struct iterate_lte_context *ctx = _ctx; + struct wimlib_resource_entry entry; + + lte_to_wimlib_resource_entry(lte, &entry); + return (*ctx->cb)(&entry, ctx->user_ctx); +} + +WIMLIBAPI int +wimlib_iterate_lookup_table(WIMStruct *wim, int flags, + wimlib_iterate_lookup_table_callback_t cb, + void *user_ctx) +{ + struct iterate_lte_context ctx = { + .cb = cb, + .user_ctx = user_ctx, + }; + if (wim->hdr.part_number == 1) { + int ret; + for (int i = 0; i < wim->hdr.image_count; i++) { + ret = do_iterate_lte(wim->image_metadata[i]->metadata_lte, + &ctx); + if (ret) + return ret; + } + } + return for_lookup_table_entry(wim->lookup_table, do_iterate_lte, &ctx); +} + static int do_print_lookup_table_entry(struct wim_lookup_table_entry *lte, void *fp) { @@ -755,12 +827,14 @@ do_print_lookup_table_entry(struct wim_lookup_table_entry *lte, void *fp) } /* - * Prints the lookup table of a WIM file. + * Deprecated */ WIMLIBAPI void -wimlib_print_lookup_table(WIMStruct *w) +wimlib_print_lookup_table(WIMStruct *wim) { - for_lookup_table_entry(w->lookup_table, + for (int i = 0; i < wim->hdr.image_count; i++) + print_lookup_table_entry(wim->image_metadata[i]->metadata_lte, stdout); + for_lookup_table_entry(wim->lookup_table, do_print_lookup_table_entry, stdout); } @@ -822,7 +896,9 @@ lookup_resource(WIMStruct *w, inode = dentry->d_inode; - wimlib_assert(inode->i_resolved); + if (!inode->i_resolved) + if (inode_resolve_ltes(inode, w->lookup_table)) + return -EIO; if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK) && inode_is_directory(inode)) @@ -855,19 +931,6 @@ out: } #endif -/* - * XXX Probably should store the compression type directly in the lookup table - * entry - */ -int -wim_resource_compression_type(const struct wim_lookup_table_entry *lte) -{ - if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) - || lte->resource_location != RESOURCE_IN_WIM) - return WIMLIB_COMPRESSION_TYPE_NONE; - return wimlib_get_compression_type(lte->wim); -} - /* Resolve an inode's lookup table entries * * This replaces the SHA1 hash fields (which are used to lookup an entry in the @@ -877,24 +940,52 @@ wim_resource_compression_type(const struct wim_lookup_table_entry *lte) * This function always succeeds; unresolved lookup table entries are given a * NULL pointer. */ -void +int inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table) { + const u8 *hash; if (!inode->i_resolved) { - struct wim_lookup_table_entry *lte; + struct wim_lookup_table_entry *lte, *ads_lte; + /* Resolve the default file stream */ - lte = __lookup_resource(table, inode->i_hash); - inode->i_lte = lte; - inode->i_resolved = 1; + lte = NULL; + hash = inode->i_hash; + if (!is_zero_hash(hash)) { + lte = __lookup_resource(table, hash); + if (unlikely(!lte)) + goto resource_not_found; + } /* Resolve the alternate data streams */ + struct wim_lookup_table_entry *ads_ltes[inode->i_num_ads]; for (u16 i = 0; i < inode->i_num_ads; i++) { - struct wim_ads_entry *cur_entry = &inode->i_ads_entries[i]; - lte = __lookup_resource(table, cur_entry->hash); - cur_entry->lte = lte; + struct wim_ads_entry *cur_entry; + + ads_lte = NULL; + cur_entry = &inode->i_ads_entries[i]; + hash = cur_entry->hash; + if (!is_zero_hash(hash)) { + ads_lte = __lookup_resource(table, hash); + if (unlikely(!ads_lte)) + goto resource_not_found; + } + ads_ltes[i] = ads_lte; } + inode->i_lte = lte; + for (u16 i = 0; i < inode->i_num_ads; i++) + inode->i_ads_entries[i].lte = ads_ltes[i]; + inode->i_resolved = 1; } + return 0; +resource_not_found: + if (wimlib_print_errors) { + ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode)); + tfprintf(stderr, T(" SHA-1 message digest of missing resource:\n ")); + print_hash(hash, stderr); + tputc(T('\n'), stderr); + } + return WIMLIB_ERR_RESOURCE_NOT_FOUND; } void @@ -1078,4 +1169,3 @@ hash_unhashed_stream(struct wim_lookup_table_entry *lte, *lte_ret = lte; return 0; } -