u8 hash[SHA1_HASH_SIZE];
} _packed_attribute;
+#define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50
+
/*
* Reads the lookup table from a WIM file.
*
* image_metadata array).
*/
int
-read_lookup_table(WIMStruct *w)
+read_lookup_table(WIMStruct *wim)
{
int ret;
size_t num_entries;
struct wim_lookup_table_entry_disk
table_buf[BUFFER_SIZE / sizeof(struct wim_lookup_table_entry_disk)]
_aligned_attribute(8);
+
+ BUILD_BUG_ON(sizeof(struct wim_lookup_table_entry_disk) !=
+ WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE);
+
off_t offset;
size_t buf_entries_remaining;
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++)
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 "
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
* 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:
out_free_lookup_table:
free_lookup_table(table);
out:
- w->current_image = 0;
+ wim->current_image = 0;
return ret;
}
/* 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;
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;
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);
}
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)
{
}
/*
- * 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);
}
* 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,
}
}
- dentry = get_dentry(w, path);
+ dentry = get_dentry(wim, path);
if (p)
*p = T(':');
if (!dentry)
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))
}
#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
* 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
*lte_ret = lte;
return 0;
}
-