From 8974b8ff33855b088a8675b656557989d48a8cd1 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 1 May 2017 11:50:08 +0200 Subject: [PATCH] utimens: Add support for native Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * lib/utimens.c: Include , 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 . --- ChangeLog | 9 ++++++ lib/utimens.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ modules/utimens | 2 ++ 3 files changed, 93 insertions(+) diff --git a/ChangeLog b/ChangeLog index a3b8f5ed38..3f42ffa05c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2017-04-30 Bruno Haible + + utimens: Add support for native Windows. + * lib/utimens.c: Include , 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 . + 2017-04-30 Bruno Haible wcsftime: New module. diff --git a/lib/utimens.c b/lib/utimens.c index 3b45119335..0b3b8e2f3a 100644 --- a/lib/utimens.c +++ b/lib/utimens.c @@ -35,6 +35,12 @@ #include "stat-time.h" #include "timespec.h" +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# 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 + + */ + 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 + . + It would be overkill to use + GetSystemTimePreciseAsFileTime + . */ + GetSystemTimeAsFileTime (¤t_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. */ diff --git a/modules/utimens b/modules/utimens index c8167ced2b..dbe24df161 100644 --- a/modules/utimens +++ b/modules/utimens @@ -14,11 +14,13 @@ fcntl-h fstat lstat gettime +msvc-nothrow stat-time stdbool sys_stat sys_time time +utime utime-h configure.ac: -- 2.39.5