+dir_exists:
+ ret = 0;
+#ifndef __WIN32__
+ if (dentry) {
+ struct wimlib_unix_data unix_data;
+ ret = inode_get_unix_data(dentry->d_inode, &unix_data, NULL);
+ if (ret > 0)
+ ;
+ else if (ret < 0)
+ ret = 0;
+ else
+ ret = dir_apply_unix_data(output_path, &unix_data);
+ }
+#endif
+ return ret;
+}
+
+#ifndef __WIN32__
+static int unix_do_apply_dentry(const mbchar *output_path,
+ size_t output_path_len,
+ struct wim_dentry *dentry,
+ struct apply_args *args)
+{
+ const struct wim_inode *inode = dentry->d_inode;
+
+ if (inode_is_symlink(inode))
+ return extract_symlink(dentry, args, output_path);
+ else if (inode_is_directory(inode))
+ return extract_directory((args->extract_flags &
+ WIMLIB_EXTRACT_FLAG_UNIX_DATA) ? dentry : NULL,
+ output_path, false);
+ else
+ return extract_regular_file(dentry, args, output_path);
+}
+
+static int
+unix_do_apply_dentry_timestamps(const mbchar *output_path,
+ size_t output_path_len,
+ const struct wim_dentry *dentry,
+ struct apply_args *args)
+{
+ int ret;
+ const struct wim_inode *inode = dentry->d_inode;
+
+#ifdef HAVE_UTIMENSAT
+ /* Convert the WIM timestamps, which are accurate to 100 nanoseconds,
+ * into `struct timespec's for passing to utimensat(), which is accurate
+ * to 1 nanosecond. */
+
+ struct timespec ts[2];
+ ts[0] = wim_timestamp_to_timespec(inode->i_last_access_time);
+ ts[1] = wim_timestamp_to_timespec(inode->i_last_write_time);
+ ret = utimensat(AT_FDCWD, output_path, ts, AT_SYMLINK_NOFOLLOW);
+ if (ret)
+ ret = errno;
+#else
+ ret = ENOSYS;
+#endif
+
+ if (ret == ENOSYS) {
+ /* utimensat() not implemented or not available */
+ #ifdef HAVE_LUTIMES
+ /* Convert the WIM timestamps, which are accurate to 100
+ * nanoseconds, into `struct timeval's for passing to lutimes(),
+ * which is accurate to 1 microsecond. */
+ struct timeval tv[2];
+ tv[0] = wim_timestamp_to_timeval(inode->i_last_access_time);
+ tv[1] = wim_timestamp_to_timeval(inode->i_last_write_time);
+ ret = lutimes(output_path, tv);
+ if (ret)
+ ret = errno;
+ #endif
+ }
+
+ if (ret == ENOSYS) {
+ /* utimensat() and lutimes() both not implemented or not
+ * available */
+ #ifdef HAVE_UTIME
+ /* Convert the WIM timestamps, which are accurate to 100
+ * nanoseconds, into a `struct utimbuf's for passing to
+ * utime(), which is accurate to 1 second. */
+ struct utimbuf buf;
+ buf.actime = wim_timestamp_to_unix(inode->i_last_access_time);
+ buf.modtime = wim_timestamp_to_unix(inode->i_last_write_time);
+ ret = utime(output_path, &buf);
+ #endif
+ }
+ if (ret && args->num_utime_warnings < 10) {
+ WARNING_WITH_ERRNO("Failed to set timestamp on file `%s'",
+ output_path);
+ args->num_utime_warnings++;
+ }