diff options
-rw-r--r-- | include/time.h | 12 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/utimensat.c | 65 |
2 files changed, 73 insertions, 4 deletions
diff --git a/include/time.h b/include/time.h index 000672e3bc..7debf9f9cc 100644 --- a/include/time.h +++ b/include/time.h @@ -146,6 +146,18 @@ extern int __clock_getres64 (clockid_t clock_id, libc_hidden_proto (__clock_getres64); #endif +#if __TIMESIZE == 64 +# define __utimensat64 __utimensat +#else +extern int __utimensat64 (int fd, const char *file, + const struct __timespec64 tsp[2], int flags); +libc_hidden_proto (__utimensat64); +#endif + +extern int __utimensat64_helper (int fd, const char *file, + const struct __timespec64 tsp[2], int flags); +libc_hidden_proto (__utimensat64_helper); + /* Compute the `struct tm' representation of T, offset OFFSET seconds east of UTC, and store year, yday, mon, mday, wday, hour, min, sec into *TP. diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c index 3bffa7d22a..1515749f05 100644 --- a/sysdeps/unix/sysv/linux/utimensat.c +++ b/sysdeps/unix/sysv/linux/utimensat.c @@ -19,18 +19,75 @@ #include <errno.h> #include <sys/stat.h> #include <sysdep.h> +#include <time.h> +#include <kernel-features.h> +/* Helper function defined for easy reusage of the code which calls utimensat + and utimensat_time64 syscall. */ +int +__utimensat64_helper (int fd, const char *file, + const struct __timespec64 tsp64[2], int flags) +{ +#ifdef __ASSUME_TIME64_SYSCALLS +# ifndef __NR_utimensat_time64 +# define __NR_utimensat_time64 __NR_utimensat +# endif + return INLINE_SYSCALL (utimensat_time64, 4, fd, file, &tsp64[0], flags); +#else +# ifdef __NR_utimensat_time64 + int ret = INLINE_SYSCALL (utimensat_time64, 4, fd, file, &tsp64[0], flags); + if (ret == 0 || errno != ENOSYS) + return ret; +# endif + if (tsp64 + && (! in_time_t_range (tsp64[0].tv_sec) + || ! in_time_t_range (tsp64[1].tv_sec))) + { + __set_errno (EOVERFLOW); + return -1; + } + + struct timespec tsp32[2]; + if (tsp64) + { + tsp32[0] = valid_timespec64_to_timespec (tsp64[0]); + tsp32[1] = valid_timespec64_to_timespec (tsp64[1]); + } + + return INLINE_SYSCALL (utimensat, 4, fd, file, tsp64 ? &tsp32[0] : NULL, + flags); +#endif + +} +libc_hidden_def (__utimensat64_helper) /* Change the access time of FILE to TSP[0] and the modification time of FILE to TSP[1]. Starting with 2.6.22 the Linux kernel has the utimensat syscall. */ int -utimensat (int fd, const char *file, const struct timespec tsp[2], - int flags) +__utimensat64 (int fd, const char *file, const struct __timespec64 tsp64[2], + int flags) { if (file == NULL) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); - /* Avoid implicit array coercion in syscall macros. */ - return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags); + + return __utimensat64_helper (fd, file, &tsp64[0], flags); +} + +#if __TIMESIZE != 64 +int +__utimensat (int fd, const char *file, const struct timespec tsp[2], + int flags) +{ + struct __timespec64 tsp64[2]; + if (tsp) + { + tsp64[0] = valid_timespec_to_timespec64 (tsp[0]); + tsp64[1] = valid_timespec_to_timespec64 (tsp[1]); + } + + return __utimensat64 (fd, file, tsp ? &tsp64[0] : NULL, flags); } +#endif +weak_alias (__utimensat, utimensat) |