From 83b989ecee478be083db8dc0cc7a5387615bd3cb Mon Sep 17 00:00:00 2001
From: Andrey Semashev <andrey.semashev@gmail.com>
Date: Wed, 31 Jul 2019 16:28:05 +0300
Subject: [PATCH] Added support for utimensat for better POSIX.1-2008
 compliance.

POSIX.1-2008 marks utime as obsolete and replaces it with utimensat.
uClibc-ng has an option for removing utime, including the corresponding
header.

Closes https://github.com/boostorg/filesystem/pull/115.
---
 libs/filesystem/src/operations.cpp | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/operations.cpp b/src/operations.cpp
index 9bba1cf7a..038109d35 100644
--- a/libs/filesystem/src/operations.cpp
+++ b/libs/filesystem/src/operations.cpp
@@ -62,7 +62,7 @@
 #endif
 
 #ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r()needs this
+# define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r() needs this
 #endif
 
 #include <boost/filesystem/operations.hpp>
@@ -119,7 +119,9 @@ using std::wstring;
 #   include <dirent.h>
 #   include <unistd.h>
 #   include <fcntl.h>
-#   include <utime.h>
+#   if _POSIX_C_SOURCE < 200809L
+#     include <utime.h>
+#   endif
 #   include "limits.h"
 
 # else // BOOST_WINDOW_API
@@ -1451,6 +1453,22 @@ namespace detail
                         system::error_code* ec)
   {
 #   ifdef BOOST_POSIX_API
+#     if _POSIX_C_SOURCE >= 200809L
+
+    struct timespec times[2] = {};
+
+    // Keep the last access time unchanged
+    times[0].tv_nsec = UTIME_OMIT;
+
+    times[1].tv_sec = new_time;
+
+    if (BOOST_UNLIKELY(::utimensat(AT_FDCWD, p.c_str(), times, 0) != 0))
+    {
+      error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time");
+      return;
+    }
+
+#     else // _POSIX_C_SOURCE >= 200809L
 
     struct stat path_stat;
     if (error(::stat(p.c_str(), &path_stat)!= 0,
@@ -1462,6 +1480,8 @@ namespace detail
     error(::utime(p.c_str(), &buf)!= 0 ? BOOST_ERRNO : 0,
       p, ec, "boost::filesystem::last_write_time");
 
+#     endif // _POSIX_C_SOURCE >= 200809L
+
 #   else
 
     handle_wrapper hw(
