diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-05-01 15:33:06 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-05-01 15:33:26 -0700 |
commit | 634d0a907ff7ba5901dfe3624e58d718f3f37cec (patch) | |
tree | 6bf86cf04d8b28a79693df9cdef1063c9b06ca76 /lib/utimens.c | |
parent | 16b49e214ad828de29ceb57ad1b443eece9bba03 (diff) | |
download | emacs-634d0a907ff7ba5901dfe3624e58d718f3f37cec.tar.gz |
Merge from gnulib
This incorporates:
2017-05-01 New module 'localtime-buffer'
2017-04-30 utimens: Add support for native Windows
* admin/merge-gnulib (AVOIDED_MODULES): Add tzset.
* configure.ac (tzset): No need for Emacs itself to check now.
* lib/gettimeofday.c, lib/time.in.h, lib/time_rz.c, lib/utimens.c:
* m4/gettimeofday.m4, m4/time_h.m4, m4/time_rz.m4: Copy from gnulib.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/localtime-buffer.c, lib/localtime-buffer.h:
* m4/localtime-buffer.m4: New files, copied from gnulib.
* src/editfns.c (init_editfns): Assume tzset is callable.
Diffstat (limited to 'lib/utimens.c')
-rw-r--r-- | lib/utimens.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/utimens.c b/lib/utimens.c index 3b451193350..0b3b8e2f3af 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 <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 (¤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. */ |