+
+/*
+ * Looks up an entry in the lookup table.
+ */
+struct lookup_table_entry *
+__lookup_resource(const struct lookup_table *lookup_table, const u8 hash[])
+{
+ size_t pos;
+ struct lookup_table_entry *lte;
+
+ pos = *(size_t*)hash % lookup_table->capacity;
+ lte = lookup_table->array[pos];
+ while (lte) {
+ if (memcmp(hash, lte->hash, WIM_HASH_SIZE) == 0)
+ return lte;
+ lte = lte->next;
+ }
+ return NULL;
+}
+
+/* Only for resolved lte's */
+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;
+ dentry = get_dentry(w, path);
+ if (!dentry)
+ return -ENOENT;
+
+ wimlib_assert(dentry->resolved);
+
+ lte = dentry->lte;
+ if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
+ && dentry_is_directory(dentry))
+ return -EISDIR;
+ stream_idx = 0;
+ if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
+ const char *stream_name = path_stream_name(path);
+ if (stream_name) {
+ size_t stream_name_len = strlen(stream_name);
+ for (u16 i = 0; i < dentry->num_ads; i++) {
+ if (ads_entry_has_name(&dentry->ads_entries[i],
+ stream_name,
+ stream_name_len))
+ {
+ stream_idx = i + 1;
+ lte = dentry->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;
+}
+
+/* Resolve a dentry's lookup table entries */
+static int dentry_resolve_ltes(struct dentry *dentry, void *__table)
+{
+ struct lookup_table *table = __table;
+ struct lookup_table_entry *lte;
+
+ /* Default file stream */
+ lte = __lookup_resource(table, dentry->hash);
+ if (lte)
+ list_add(&dentry->lte_group_list.list, <e->lte_group_list);
+ else
+ INIT_LIST_HEAD(&dentry->lte_group_list.list);
+ dentry->lte = lte;
+ dentry->lte_group_list.type = STREAM_TYPE_NORMAL;
+ dentry->resolved = true;
+
+ /* Alternate data streams */
+ if (dentry->link_group_master_status != GROUP_SLAVE) {
+ for (u16 i = 0; i < dentry->num_ads; i++) {
+ struct ads_entry *cur_entry = &dentry->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;
+}
+
+/* Resolve all the lookup table entries of a dentry tree */
+void resolve_lookup_table_entries(struct dentry *root, struct lookup_table *table)
+{
+ for_dentry_in_tree(root, dentry_resolve_ltes, table);
+}