X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Flookup_table.c;h=d155ceb0dfece101c11b55654ee57d754d9461a9;hp=a24cf68887d40a4246d3a29ad7639e29f67fb506;hb=1a8b4a9f6e24d3ebbd75a86f73955e0f3f5e1785;hpb=19fd5bbc4f64cc8bf735f7c2c0bb864876998cf4 diff --git a/src/lookup_table.c b/src/lookup_table.c index a24cf688..d155ceb0 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -375,7 +375,7 @@ struct wim_lookup_table_entry_disk { * image_metadata array). */ int -read_lookup_table(WIMStruct *w) +read_lookup_table(WIMStruct *wim) { int ret; size_t num_entries; @@ -393,23 +393,26 @@ read_lookup_table(WIMStruct *w) const struct wim_lookup_table_entry_disk *disk_entry; DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"", - w->hdr.lookup_table_res_entry.offset, - w->hdr.lookup_table_res_entry.original_size); + wim->hdr.lookup_table_res_entry.offset, + wim->hdr.lookup_table_res_entry.original_size); - if (resource_is_compressed(&w->hdr.lookup_table_res_entry)) { + if (resource_is_compressed(&wim->hdr.lookup_table_res_entry)) { ERROR("Didn't expect a compressed lookup table!"); ERROR("Ask the author to implement support for this."); return WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE; } - num_entries = w->hdr.lookup_table_res_entry.size / + num_entries = wim->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; + wim->current_image = 0; + offset = wim->hdr.lookup_table_res_entry.offset; buf_entries_remaining = 0; for (; num_entries != 0; num_entries--, buf_entries_remaining--, disk_entry++) @@ -419,7 +422,7 @@ read_lookup_table(WIMStruct *w) entries_to_read = min(ARRAY_LEN(table_buf), num_entries); bytes_to_read = entries_to_read * sizeof(struct wim_lookup_table_entry_disk); - if (full_pread(w->in_fd, table_buf, + if (full_pread(wim->in_fd, table_buf, bytes_to_read, offset) != bytes_to_read) { ERROR_WITH_ERRNO("Error reading lookup table " @@ -437,65 +440,79 @@ read_lookup_table(WIMStruct *w) goto out_free_lookup_table; } - cur_entry->wim = w; + cur_entry->wim = wim; cur_entry->resource_location = RESOURCE_IN_WIM; get_resource_entry(&disk_entry->resource_entry, &cur_entry->resource_entry); cur_entry->part_number = le16_to_cpu(disk_entry->part_number); cur_entry->refcnt = le32_to_cpu(disk_entry->refcnt); copy_hash(cur_entry->hash, disk_entry->hash); - 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; + if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) + cur_entry->compression_type = wim->compression_type; + else + BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0); + + if (cur_entry->part_number != wim->hdr.part_number) { + WARNING("A lookup table entry in part %hu of the WIM " + "points to part %hu (ignoring it)", + wim->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; + if (wim->hdr.part_number != 1) { + 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; + if (wim->current_image == wim->hdr.image_count) { + WARNING("The WIM header says there are %u images " + "in the WIM, but we found more metadata " + "resources than this (ignoring the extra)", + wim->hdr.image_count); + free_lookup_table_entry(cur_entry); + continue; } /* Notice very carefully: We are assigning the metadata @@ -507,40 +524,43 @@ read_lookup_table(WIMStruct *w) * written in the XML data. */ DEBUG("Found metadata resource for image %u at " "offset %"PRIu64".", - w->current_image + 1, + wim->current_image + 1, cur_entry->resource_entry.offset); - w->image_metadata[ - w->current_image++]->metadata_lte = cur_entry; + wim->image_metadata[ + wim->current_image++]->metadata_lte = cur_entry; } else { /* Lookup table entry for a stream that is not a * 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 (wim->hdr.part_number == 1 && wim->current_image != wim->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.", + wim->filename, wim->hdr.image_count, + wim->current_image, wim->current_image); + for (int i = wim->current_image; i < wim->hdr.image_count; i++) + put_image_metadata(wim->image_metadata[i], NULL); + wim->hdr.image_count = wim->current_image; } DEBUG("Done reading lookup table."); - w->lookup_table = table; + wim->lookup_table = table; ret = 0; goto out; out_free_cur_entry: @@ -548,7 +568,7 @@ out_free_cur_entry: out_free_lookup_table: free_lookup_table(table); out: - w->current_image = 0; + wim->current_image = 0; return ret; } @@ -626,7 +646,7 @@ append_lookup_table_entry(struct wim_lookup_table_entry *lte, void *_list) /* Writes the WIM lookup table to the output file. */ int -write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry) +write_lookup_table(WIMStruct *wim, int image, struct resource_entry *out_res_entry) { LIST_HEAD(stream_list); int start_image; @@ -634,7 +654,7 @@ write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry if (image == WIMLIB_ALL_IMAGES) { start_image = 1; - end_image = w->hdr.image_count; + end_image = wim->hdr.image_count; } else { start_image = image; end_image = image; @@ -643,16 +663,16 @@ write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry for (int i = start_image; i <= end_image; i++) { struct wim_lookup_table_entry *metadata_lte; - metadata_lte = w->image_metadata[i - 1]->metadata_lte; + metadata_lte = wim->image_metadata[i - 1]->metadata_lte; metadata_lte->out_refcnt = 1; metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA; append_lookup_table_entry(metadata_lte, &stream_list); } - for_lookup_table_entry(w->lookup_table, + for_lookup_table_entry(wim->lookup_table, append_lookup_table_entry, &stream_list); return write_lookup_table_from_stream_list(&stream_list, - w->out_fd, + wim->out_fd, out_res_entry); } @@ -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); } @@ -792,7 +866,7 @@ __lookup_resource(const struct wim_lookup_table *table, const u8 hash[]) * This is only for pre-resolved inodes. */ int -lookup_resource(WIMStruct *w, +lookup_resource(WIMStruct *wim, const tchar *path, int lookup_flags, struct wim_dentry **dentry_ret, @@ -814,7 +888,7 @@ lookup_resource(WIMStruct *w, } } - dentry = get_dentry(w, path); + dentry = get_dentry(wim, path); if (p) *p = T(':'); if (!dentry) @@ -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, wim->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; } -