+#endif
+
+void inode_resolve_ltes(struct inode *inode, struct lookup_table *table)
+{
+ struct lookup_table_entry *lte;
+
+ wimlib_assert(!inode->resolved);
+
+ /* Resolve the default file stream */
+ lte = __lookup_resource(table, inode->hash);
+ inode->lte = lte;
+ 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);
+ cur_entry->lte = lte;
+ }
+}
+
+static void inode_unresolve_ltes(struct inode *inode)
+{
+ wimlib_assert(inode->resolved);
+ if (inode->lte)
+ copy_hash(inode->hash, inode->lte->hash);
+ else
+ zero_out_hash(inode->hash);
+
+ for (u16 i = 0; i < inode->num_ads; i++) {
+ if (inode->ads_entries[i].lte)
+ copy_hash(inode->ads_entries[i].hash,
+ inode->ads_entries[i].lte->hash);
+ else
+ zero_out_hash(inode->ads_entries[i].hash);
+ }
+ inode->resolved = false;
+}
+
+/* Resolve a dentry's lookup table entries
+ *
+ * This replaces the SHA1 hash fields (which are used to lookup an entry in the
+ * lookup table) with pointers directly to the lookup table entries. A circular
+ * linked list of streams sharing the same lookup table entry is created.
+ *
+ * This function always succeeds; unresolved lookup table entries are given a
+ * NULL pointer.
+ */
+int dentry_resolve_ltes(struct dentry *dentry, void *table)
+{
+ if (!dentry->d_inode->resolved)
+ inode_resolve_ltes(dentry->d_inode, table);
+ return 0;
+}
+
+int dentry_unresolve_ltes(struct dentry *dentry, void *ignore)
+{
+ if (dentry->d_inode->resolved)
+ inode_unresolve_ltes(dentry->d_inode);
+ return 0;
+}
+
+/*
+ * Returns the lookup table entry for stream @stream_idx of the inode, where
+ * stream_idx = 0 means the default un-named file stream, and stream_idx >= 1
+ * corresponds to an alternate data stream.
+ *
+ * This works for both resolved and un-resolved dentries.
+ */
+struct lookup_table_entry *
+inode_stream_lte(const struct inode *inode, unsigned stream_idx,
+ const struct lookup_table *table)
+{
+ if (inode->resolved)
+ return inode_stream_lte_resolved(inode, stream_idx);
+ else
+ return inode_stream_lte_unresolved(inode, stream_idx, table);
+}
+
+
+/* Return the lookup table entry for the unnamed data stream of an inode, or
+ * NULL if there is none.
+ *
+ * You'd think this would be easier than it actually is, since the unnamed data
+ * stream should be the one referenced from the inode itself. Alas, if there
+ * are named data streams, Microsoft's "imagex.exe" program will put the unnamed
+ * data stream in one of the alternate data streams instead of inside the WIM
+ * dentry itself. So we need to check the alternate data streams too.
+ *
+ * Also, note that a dentry may appear to have more than one unnamed stream, but
+ * if the SHA1 message digest is all 0's then the corresponding stream does not
+ * really "count" (this is the case for the inode's own file stream when the
+ * file stream that should be there is actually in one of the alternate stream
+ * entries.). This is despite the fact that we may need to extract such a
+ * missing entry as an empty file or empty named data stream.
+ */
+struct lookup_table_entry *
+inode_unnamed_lte(const struct inode *inode,
+ const struct lookup_table *table)
+{
+ if (inode->resolved)
+ return inode_unnamed_lte_resolved(inode);
+ else
+ return inode_unnamed_lte_unresolved(inode, table);
+}
+
+static int lte_add_stream_size(struct lookup_table_entry *lte,
+ void *total_bytes_p)
+{
+ *(u64*)total_bytes_p += lte->resource_entry.size;
+ return 0;
+}
+
+u64 lookup_table_total_stream_size(struct lookup_table *table)
+{
+ u64 total_size = 0;
+ for_lookup_table_entry(table, lte_add_stream_size, &total_size);
+ return total_size;
+}