From 13858c2e061870d963856ddce3943e9703f50638 Mon Sep 17 00:00:00 2001 From: Tomasz Konojacki Date: Sat, 3 Apr 2021 23:47:27 +0200 Subject: [PATCH] Time::HiRes: implement utime() for win32 --- dist/Time-HiRes/HiRes.pm | 2 +- dist/Time-HiRes/HiRes.xs | 74 +++++++++++++++++++++++++++++++++++++ dist/Time-HiRes/Makefile.PL | 3 ++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/dist/Time-HiRes/HiRes.pm b/dist/Time-HiRes/HiRes.pm index 9377c3479fbd..c75f5cd28843 100644 --- a/dist/Time-HiRes/HiRes.pm +++ b/dist/Time-HiRes/HiRes.pm @@ -50,7 +50,7 @@ our @EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval stat lstat utime ); -our $VERSION = '1.9767'; +our $VERSION = '1.9768'; our $XS_VERSION = $VERSION; $VERSION = eval $VERSION; diff --git a/dist/Time-HiRes/HiRes.xs b/dist/Time-HiRes/HiRes.xs index 1b97962b3a6e..6f09283b63dc 100644 --- a/dist/Time-HiRes/HiRes.xs +++ b/dist/Time-HiRes/HiRes.xs @@ -186,11 +186,21 @@ START_MY_CXT # undef clock_getres # define clock_getres(clock_id, tp) _clock_getres(clock_id, tp) +# undef futimens +# define futimens(fd, times) _futimens(aTHX_ fd, times) + +# undef utimensat +# define utimensat(dirfd, path, times, flags) _utimensat(aTHX_ dirfd, path, times, flags) + # ifndef CLOCK_REALTIME # define CLOCK_REALTIME 1 # define CLOCK_MONOTONIC 2 # endif +# ifndef AT_FDCWD +# define AT_FDCWD -100 +# endif + /* If the performance counter delta drifts more than 0.5 seconds from the * system time then we recalibrate to the system time. This means we may * move *backwards* in time! */ @@ -320,6 +330,70 @@ _clock_getres(clockid_t clock_id, struct timespec *tp) return 0; } +static int +_futimens(pTHX_ int fd, const struct timespec times[2]) +{ + size_t i; + HANDLE h; + FT_t ft_times[2]; + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + for (i = 0; i < 2; ++i) { + if (!times) + GetSystemTimePreciseAsFileTime(&ft_times[i].ft_val); + else { + if (times[i].tv_sec < 0 || times[i].tv_nsec < 0 || + times[i].tv_nsec >= IV_1E9) + { + errno = EINVAL; + return -1; + } + + ft_times[i].ft_i64 = EPOCH_BIAS + + ((__int64)times[i].tv_sec * IV_1E7) + (times[i].tv_nsec / 100); + } + } + + if(!SetFileTime(h, NULL, &ft_times[0].ft_val, &ft_times[1].ft_val)) { + if (GetLastError() == ERROR_ACCESS_DENIED) + errno = EACCES; + else + errno = EINVAL; + + return -1; + } + + return 0; +} + +static int +_utimensat(pTHX_ int dirfd, const char *path, const struct timespec times[2], + int flags) +{ + int fd, ret; + + /* Time::HiRes doesn't need those things, so we didn't implement them */ + if (dirfd != AT_FDCWD || flags) { + errno = EINVAL; + return -1; + } + + fd = _open(path, _O_WRONLY); + if (fd == -1) + return -1; + + ret = futimens(fd, times); + + _close(fd); + + return ret; +} + #endif /* #if defined(WIN32) || defined(CYGWIN_WITH_W32API) */ /* Do not use H A S _ N A N O S L E E P diff --git a/dist/Time-HiRes/Makefile.PL b/dist/Time-HiRes/Makefile.PL index c918cd14545b..0969928d27e9 100644 --- a/dist/Time-HiRes/Makefile.PL +++ b/dist/Time-HiRes/Makefile.PL @@ -1023,6 +1023,9 @@ sub main { # we provide our own implementations of those functions on win32 DEFINE('TIME_HIRES_CLOCK_GETTIME'); DEFINE('TIME_HIRES_CLOCK_GETRES'); + DEFINE('TIME_HIRES_UTIME'); + DEFINE('HAS_FUTIMENS'); + DEFINE('HAS_UTIMENSAT'); $LIBS = []; print "System is $^O, skipping full configure...\n"; open(XDEFINE, '>', 'xdefine') or die "$0: Cannot create xdefine: $!\n";