CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV)
CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME)
CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS)
+CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT)
CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK)
CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
AC_CHECK_FUNCS([lutimes memmove memset mkdir mkfifo mknod])
AC_CHECK_FUNCS([nl_langinfo pipe poll readlink select setenv setlocale])
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
-AC_CHECK_FUNCS([tzset unsetenv utime utimes vfork])
+AC_CHECK_FUNCS([tzset unsetenv utime futimens utimensat utimes vfork])
AC_CHECK_FUNCS([wcrtomb wcscpy wcslen wctomb wmemcmp wmemcpy])
# detects cygwin-1.7, as opposed to older versions
AC_CHECK_FUNCS([cygwin_conv_path])
return (ARCHIVE_WARN);
}
-#ifdef HAVE_UTIMES
+
+#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
+/*
+ * utimensat() and futimens() are defined in POSIX.1-2008. They provide ns
+ * resolution and setting times on fd and on symlinks, too.
+ */
+static int
+set_time(int fd, int mode, const char *name,
+ time_t atime, long atime_nsec,
+ time_t mtime, long mtime_nsec)
+{
+ struct timespec ts[2];
+ ts[0].tv_sec = atime;
+ ts[0].tv_nsec = atime_nsec;
+ ts[1].tv_sec = mtime;
+ ts[1].tv_nsec = mtime_nsec;
+ if (fd >= 0)
+ return futimens(fd, ts);
+ return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
+}
+#elif HAVE_UTIMES
/*
- * The utimes()-family functions provide high resolution and
+ * The utimes()-family functions provide µs-resolution and
* a way to set time on an fd or a symlink. We prefer them
- * when they're available.
+ * when they're available and utimensat/futimens aren't there.
*/
static int
set_time(int fd, int mode, const char *name,