diff options
author | Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr> | 2017-09-08 00:41:43 +0200 |
---|---|---|
committer | Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr> | 2018-10-24 12:53:27 +0200 |
commit | cc5b45f0c65fce2acd7323c3ead44aca1613a783 (patch) | |
tree | 8300ec02bb472f1e7af371b600f6d78a0efe0b58 /sysdeps | |
parent | 8ea072767dc028b00062944d79c9d1fcee44c676 (diff) | |
download | glibc-cc5b45f0c65fce2acd7323c3ead44aca1613a783.zip glibc-cc5b45f0c65fce2acd7323c3ead44aca1613a783.tar.gz glibc-cc5b45f0c65fce2acd7323c3ead44aca1613a783.tar.bz2 |
Y2038: add function __futimes64
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/unix/sysv/linux/futimes.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c index 9e6267c..c3d7678 100644 --- a/sysdeps/unix/sysv/linux/futimes.c +++ b/sysdeps/unix/sysv/linux/futimes.c @@ -24,6 +24,7 @@ #include <sys/time.h> #include <_itoa.h> #include <fcntl.h> +#include <y2038-support.h> /* Change the access time of the file associated with FD to TVP[0] and @@ -49,3 +50,61 @@ __futimes (int fd, const struct timeval tvp[2]) return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0); } weak_alias (__futimes, futimes) + +/* 64-bit time version */ + +int +__futimes64 (int fd, const struct __timeval64 tvp[2]) +{ + struct timespec ts32[2], *ts32p = NULL; +/* Only try and use this syscall if defined by kernel */ +#ifdef __NR_utimensat_time64 + /* The utimensat system call expects timespec not timeval. */ + struct __timespec64 ts64[2], *ts64p = NULL; + int result; +#endif + +/* Only try and use this syscall if defined by kernel */ +#ifdef __NR_utimensat_time64 + if (__y2038_linux_support > 0) + { + if (tvp != NULL) + { + if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 + || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); + + ts64[0].tv_sec = tvp[0].tv_sec; + ts64[0].tv_nsec = tvp[0].tv_usec * 1000; + ts64[0].tv_pad = 0; + ts64[1].tv_sec = tvp[1].tv_sec; + ts64[1].tv_nsec = tvp[1].tv_usec * 1000; + ts64[1].tv_pad = 0; + ts64p = ts64; + } + + result = INLINE_SYSCALL (utimensat_time64, 4, fd, NULL, ts64p, 0); + if (result == 0 || errno != ENOSYS) + return result; + __y2038_linux_support = -1; + } +#endif + + if (tvp != NULL) + { + if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 + || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); + + if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX) + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); + + ts32[0].tv_sec = tvp[0].tv_sec; + ts32[0].tv_nsec = tvp[0].tv_usec * 1000; + ts32[1].tv_sec = tvp[1].tv_sec; + ts32[1].tv_nsec = tvp[1].tv_usec * 1000; + ts32p = ts32; + } + + return INLINE_SYSCALL (utimensat, 4, fd, NULL, ts32p, 0); +} |