+
+/*
+ * 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;
+}
+
+int lookup_resource(WIMStruct *w, const char *path,
+ int lookup_flags,
+ struct dentry **dentry_ret,
+ struct lookup_table_entry **lte_ret,
+ u8 **hash_ret)
+{
+ struct dentry *dentry = get_dentry(w, path);
+ struct lookup_table_entry *lte;
+ u8 *hash;
+ if (!dentry)
+ return -ENOENT;
+ if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
+ && dentry_is_directory(dentry))
+ return -EISDIR;
+ 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))
+ {
+ hash = dentry->ads_entries[i].hash;
+ goto do_lookup;
+ }
+ }
+ return -ENOENT;
+ }
+ }
+ hash = dentry->hash;
+do_lookup:
+ lte = __lookup_resource(w->lookup_table, hash);
+ if (dentry_ret)
+ *dentry_ret = dentry;
+ if (lte_ret)
+ *lte_ret = lte;
+ if (hash_ret)
+ *hash_ret = hash;
+ return 0;
+}