+/* Can look up named data stream with colon syntax */
+#define LOOKUP_FLAG_ADS_OK 0x01
+
+/* Can look up directory (otherwise get -ENOTDIR) */
+#define LOOKUP_FLAG_DIRECTORY_OK 0x02
+
+/* Get the data stream of the specified name from the specified inode. Returns
+ * NULL with errno set if not found. */
+static struct wim_inode_stream *
+inode_get_data_stream_tstr(const struct wim_inode *inode,
+ const char *stream_name)
+{
+ struct wim_inode_stream *strm;
+
+ if (!stream_name || !*stream_name) {
+ strm = inode_get_unnamed_data_stream(inode);
+ } else {
+ const utf16lechar *uname;
+
+ if (tstr_get_utf16le(stream_name, &uname))
+ return NULL;
+ strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname);
+ tstr_put_utf16le(uname);
+ }
+ if (!strm)
+ errno = ENOENT;
+ return strm;
+}
+
+/*
+ * Translate a path into the corresponding dentry and stream in the mounted WIM
+ * image.
+ *
+ * Returns 0 or a -errno code. @dentry_ret and @strm_ret are both optional.
+ */
+static int
+wim_pathname_to_stream(const struct wimfs_context *ctx,
+ const char *path,
+ int lookup_flags,
+ struct wim_dentry **dentry_ret,
+ struct wim_inode_stream **strm_ret)
+{
+ WIMStruct *wim = ctx->wim;
+ struct wim_dentry *dentry;
+ struct wim_inode *inode;
+ struct wim_inode_stream *strm;
+ const char *stream_name = NULL;
+ char *p = NULL;
+
+ lookup_flags |= ctx->default_lookup_flags;
+
+ 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(wim, path, WIMLIB_CASE_SENSITIVE);
+ if (p)
+ *p = ':';
+ if (!dentry)
+ return -errno;
+
+ inode = dentry->d_inode;
+
+ if (inode_resolve_streams(inode, wim->blob_table, false))
+ return -EIO;
+
+ if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
+ && inode_is_directory(inode))
+ return -EISDIR;
+
+ strm = inode_get_data_stream_tstr(inode, stream_name);
+ if (!strm) {
+ /* Force creation of an unnamed data stream */
+ if (!stream_name)
+ strm = inode_add_stream(inode, STREAM_TYPE_DATA,
+ NO_STREAM_NAME, NULL);
+ if (!strm)
+ return -errno;
+ }
+
+ if (dentry_ret)
+ *dentry_ret = dentry;
+ if (strm_ret)
+ *strm_ret = strm;
+ return 0;
+}
+