+static mode_t
+fuse_mask_mode(mode_t mode, struct fuse_context *fuse_ctx)
+{
+#if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
+ mode &= ~fuse_ctx->umask;
+#endif
+ return mode;
+}
+
+/*
+ * Add a new dentry with a new inode to a WIM image.
+ *
+ * Returns 0 on success, or negative error number on failure.
+ */
+static int
+create_dentry(struct fuse_context *fuse_ctx, const char *path,
+ mode_t mode, int attributes, struct wim_dentry **dentry_ret)
+{
+ struct wim_dentry *parent;
+ struct wim_dentry *new;
+ const char *basename;
+ struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
+ int ret;
+
+ parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
+ if (!parent)
+ return -errno;
+
+ if (!dentry_is_directory(parent))
+ return -ENOTDIR;
+
+ basename = path_basename(path);
+ if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
+ return -EEXIST;
+
+ ret = new_dentry_with_inode(basename, &new);
+ if (ret)
+ return -ENOMEM;
+
+ new->d_inode->i_resolved = 1;
+ new->d_inode->i_ino = wimfs_ctx->next_ino++;
+ new->d_inode->i_attributes = attributes;
+
+ if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
+ if (inode_set_unix_data(new->d_inode,
+ fuse_ctx->uid,
+ fuse_ctx->gid,
+ fuse_mask_mode(mode, fuse_ctx),
+ wimfs_ctx->wim->lookup_table,
+ UNIX_DATA_ALL | UNIX_DATA_CREATE))
+ {
+ free_dentry(new);
+ return -ENOMEM;
+ }
+ }
+ dentry_add_child(parent, new);
+ list_add_tail(&new->d_inode->i_list, wimfs_ctx->image_inode_list);
+ if (dentry_ret)
+ *dentry_ret = new;
+ return 0;
+}
+
+static struct wim_inode *
+wim_pathname_to_inode(WIMStruct *wim, const tchar *path)
+{
+ struct wim_dentry *dentry;
+ dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
+ if (dentry)
+ return dentry->d_inode;
+ else
+ return NULL;
+}
+
+/* Remove a dentry from a mounted WIM image; i.e. remove an alias for the
+ * corresponding inode.