]> Savannah Git Hosting - gnulib.git/commitdiff
utimens: Add support for native Windows.
authorBruno Haible <bruno@clisp.org>
Mon, 1 May 2017 09:50:08 +0000 (11:50 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 1 May 2017 09:50:08 +0000 (11:50 +0200)
* lib/utimens.c: Include <windows.h>, msvc-nothrow.h.
(fdutimens): Provide a native Windows implementation, like utime.c with
added tv_nsec support.
* modules/utimens (Depends-on): Add msvc-nothrow, utime.
Suggested by Tim Rühsen <tim.ruehsen@gmx.de>.

ChangeLog
lib/utimens.c
modules/utimens

index a3b8f5ed38a118f052014f1b15cb8b0b268fb929..3f42ffa05c598bbc84ef09657728ea87b72f483f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2017-04-30  Bruno Haible  <bruno@clisp.org>
+
+       utimens: Add support for native Windows.
+       * lib/utimens.c: Include <windows.h>, msvc-nothrow.h.
+       (fdutimens): Provide a native Windows implementation, like utime.c with
+       added tv_nsec support.
+       * modules/utimens (Depends-on): Add msvc-nothrow, utime.
+       Suggested by Tim Rühsen <tim.ruehsen@gmx.de>.
+
 2017-04-30  Bruno Haible  <bruno@clisp.org>
 
        wcsftime: New module.
index 3b4511933504d2c8c78720908151c854d32d4b60..0b3b8e2f3afeb336c05b08226a31f5cb3fb73dd9 100644 (file)
 #include "stat-time.h"
 #include "timespec.h"
 
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include "msvc-nothrow.h"
+#endif
+
 /* Avoid recursion with rpl_futimens or rpl_utimensat.  */
 #undef futimens
 #undef utimensat
@@ -271,6 +277,82 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
   lutimensat_works_really = -1;
 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
 
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* On native Windows, use SetFileTime(). See
+     <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
+     <https://msdn.microsoft.com/en-us/library/ms724284.aspx>  */
+  if (0 <= fd)
+    {
+      HANDLE handle;
+      FILETIME current_time;
+      FILETIME last_access_time;
+      FILETIME last_write_time;
+
+      handle = (HANDLE) _get_osfhandle (fd);
+      if (handle == INVALID_HANDLE_VALUE)
+        {
+          errno = EBADF;
+          return -1;
+        }
+
+      if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
+        {
+          /* GetSystemTimeAsFileTime
+             <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
+             It would be overkill to use
+             GetSystemTimePreciseAsFileTime
+             <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.  */
+          GetSystemTimeAsFileTime (&current_time);
+        }
+
+      if (ts == NULL || ts[0].tv_nsec == UTIME_NOW)
+        {
+          last_access_time = current_time;
+        }
+      else if (ts[0].tv_nsec == UTIME_OMIT)
+        {
+          last_access_time.dwLowDateTime = 0;
+          last_access_time.dwHighDateTime = 0;
+        }
+      else
+        {
+          ULONGLONG time_since_16010101 =
+            (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL;
+          last_access_time.dwLowDateTime = (DWORD) time_since_16010101;
+          last_access_time.dwHighDateTime = time_since_16010101 >> 32;
+        }
+
+      if (ts == NULL || ts[1].tv_nsec == UTIME_NOW)
+        {
+          last_write_time = current_time;
+        }
+      else if (ts[1].tv_nsec == UTIME_OMIT)
+        {
+          last_write_time.dwLowDateTime = 0;
+          last_write_time.dwHighDateTime = 0;
+        }
+      else
+        {
+          ULONGLONG time_since_16010101 =
+            (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL;
+          last_write_time.dwLowDateTime = (DWORD) time_since_16010101;
+          last_write_time.dwHighDateTime = time_since_16010101 >> 32;
+        }
+
+      if (SetFileTime (handle, NULL, &last_access_time, &last_write_time))
+        return 0;
+      else
+        {
+          #if 0
+          DWORD sft_error = GetLastError ();
+          fprintf (stderr, "utime SetFileTime error 0x%x\n", (unsigned int) sft_error);
+          #endif
+          errno = EINVAL;
+          return -1;
+        }
+    }
+#endif
+
   /* The platform lacks an interface to set file timestamps with
      nanosecond resolution, so do the best we can, discarding any
      fractional part of the timestamp.  */
index c8167ced2b84b4b048063618dc13d7893464ca52..dbe24df1612ace422745b5698f3be3d8d72e5a8f 100644 (file)
@@ -14,11 +14,13 @@ fcntl-h
 fstat
 lstat
 gettime
+msvc-nothrow
 stat-time
 stdbool
 sys_stat
 sys_time
 time
+utime
 utime-h
 
 configure.ac: