+ free_dentry(dentry);
+}
+
+static mode_t
+inode_default_unix_mode(const struct wim_inode *inode)
+{
+ if (inode_is_symlink(inode))
+ return S_IFLNK | 0777;
+ else if (inode_is_directory(inode))
+ return S_IFDIR | 0777;
+ else
+ return S_IFREG | 0777;
+}
+
+/* Transfers file attributes from a struct wim_inode to a `stat' buffer.
+ *
+ * The lookup table entry tells us which stream in the inode we are statting.
+ * For a named data stream, everything returned is the same as the unnamed data
+ * stream except possibly the size and block count. */
+static int
+inode_to_stbuf(const struct wim_inode *inode,
+ const struct wim_lookup_table_entry *lte,
+ struct stat *stbuf)
+{
+ const struct wimfs_context *ctx = wimfs_get_context();
+
+ memset(stbuf, 0, sizeof(struct stat));
+ stbuf->st_mode = inode_default_unix_mode(inode);
+ stbuf->st_uid = ctx->default_uid;
+ stbuf->st_gid = ctx->default_gid;
+ if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
+ struct wimlib_unix_data unix_data;
+ if (inode_get_unix_data(inode, &unix_data, NULL) == 0) {
+ stbuf->st_uid = unix_data.uid;
+ stbuf->st_gid = unix_data.gid;
+ stbuf->st_mode = unix_data.mode;
+ }
+ }
+ stbuf->st_ino = (ino_t)inode->i_ino;
+ stbuf->st_nlink = inode->i_nlink;
+ if (lte)
+ stbuf->st_size = wim_resource_size(lte);
+ else
+ stbuf->st_size = 0;
+#ifdef HAVE_STAT_NANOSECOND_PRECISION
+ stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
+ stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
+ stbuf->st_ctim = stbuf->st_mtim;
+#else
+ stbuf->st_atime = wim_timestamp_to_unix(inode->i_last_access_time);
+ stbuf->st_mtime = wim_timestamp_to_unix(inode->i_last_write_time);
+ stbuf->st_ctime = stbuf->st_mtime;
+#endif
+ stbuf->st_blocks = (stbuf->st_size + 511) / 512;
+ return 0;
+}
+
+static void
+touch_inode(struct wim_inode *inode)
+{
+ u64 now = get_wim_timestamp();
+ inode->i_last_access_time = now;
+ inode->i_last_write_time = now;