+ do_print_lookup_table_entry,
+ NULL);
+}
+
+/*
+ * Looks up an entry in the lookup table.
+ */
+struct lookup_table_entry *
+__lookup_resource(const struct lookup_table *table, const u8 hash[])
+{
+ size_t i;
+ struct lookup_table_entry *lte;
+ struct hlist_node *pos;
+
+ i = *(size_t*)hash % table->capacity;
+ hlist_for_each_entry(lte, pos, &table->array[i], hash_list)
+ if (hashes_equal(hash, lte->hash))
+ return lte;
+ return NULL;
+}
+
+/*
+ * Finds the dentry, lookup table entry, and stream index for a WIM file stream,
+ * given a path name.
+ *
+ * This is only for pre-resolved inodes.
+ */
+int lookup_resource(WIMStruct *w, const char *path,
+ int lookup_flags,
+ struct dentry **dentry_ret,
+ struct lookup_table_entry **lte_ret,
+ unsigned *stream_idx_ret)
+{
+ struct dentry *dentry;
+ struct lookup_table_entry *lte;
+ unsigned stream_idx;
+ const char *stream_name = NULL;
+ struct inode *inode;
+ char *p = NULL;
+
+ if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
+ stream_name = path_stream_name(path);
+ if (stream_name) {
+ p = (char*)stream_name - 1;
+ *p = '\0';
+ }
+ }
+
+ dentry = get_dentry(w, path);
+ if (p)
+ *p = ':';
+ if (!dentry)
+ return -ENOENT;
+
+ inode = dentry->inode;
+
+ wimlib_assert(inode->resolved);
+
+ if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
+ && inode_is_directory(inode))
+ return -EISDIR;
+
+ lte = inode->lte;
+ stream_idx = 0;
+ if (stream_name) {
+ size_t stream_name_len = strlen(stream_name);
+ for (u16 i = 0; i < inode->num_ads; i++) {
+ if (ads_entry_has_name(inode->ads_entries[i],
+ stream_name,
+ stream_name_len))
+ {
+ stream_idx = i + 1;
+ lte = inode->ads_entries[i]->lte;
+ goto out;
+ }
+ }
+ return -ENOENT;
+ }
+out:
+ if (dentry_ret)
+ *dentry_ret = dentry;
+ if (lte_ret)
+ *lte_ret = lte;
+ if (stream_idx_ret)
+ *stream_idx_ret = stream_idx;
+ return 0;
+}
+
+static int inode_resolve_ltes(struct inode *inode, struct lookup_table *table)
+{
+ struct lookup_table_entry *lte;
+
+ /* Resolve the default file stream */
+ lte = __lookup_resource(table, inode->hash);
+ if (lte)
+ list_add(&inode->lte_group_list.list, <e->lte_group_list);
+ else
+ INIT_LIST_HEAD(&inode->lte_group_list.list);
+ inode->lte = lte;
+ inode->lte_group_list.type = STREAM_TYPE_NORMAL;
+ inode->resolved = true;
+
+ /* Resolve the alternate data streams */
+ for (u16 i = 0; i < inode->num_ads; i++) {
+ struct ads_entry *cur_entry = inode->ads_entries[i];
+
+ lte = __lookup_resource(table, cur_entry->hash);
+ if (lte)
+ list_add(&cur_entry->lte_group_list.list,
+ <e->lte_group_list);
+ else
+ INIT_LIST_HEAD(&cur_entry->lte_group_list.list);
+ cur_entry->lte = lte;
+ cur_entry->lte_group_list.type = STREAM_TYPE_ADS;
+ }
+ return 0;