diff mbox

[[PATCH,RFC,2] 21/63] Y2038: add function __utimensat64

Message ID 20180418201819.15952-22-albert.aribaud@3adev.fr
State New
Headers show

Commit Message

Albert ARIBAUD April 18, 2018, 8:17 p.m. UTC
---
 io/utimensat.c                      |  9 ++++++
 sysdeps/unix/sysv/linux/utimensat.c | 58 +++++++++++++++++++++++++++++++++++++
 time/Versions                       |  1 +
 3 files changed, 68 insertions(+)
diff mbox

Patch

diff --git a/io/utimensat.c b/io/utimensat.c
index 6b67a52e9e..2116b3d0a3 100644
--- a/io/utimensat.c
+++ b/io/utimensat.c
@@ -30,3 +30,12 @@  utimensat (int fd, const char *file, const struct timespec tsp[2],
   return -1;
 }
 stub_warning (utimensat)
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utimensat64)
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 108d3bc55b..bef4765e0c 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -34,3 +34,61 @@  utimensat (int fd, const char *file, const struct timespec tsp[2],
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  struct timespec ts32[2], *ts32p = NULL;
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat64
+  struct __timespec64 ts64[2], *ts64p = NULL;
+  int res;
+#endif
+
+  if (file == NULL)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat64
+  if (__y2038_linux_support)
+    {
+      if (tsp)
+        {
+          ts64[0].tv_sec = tsp[0].tv_sec;
+          ts64[0].tv_nsec = tsp[0].tv_nsec;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tsp[1].tv_sec;
+          ts64[1].tv_nsec = tsp[1].tv_nsec;
+          ts64[1].tv_pad = 0;
+          ts64p = ts64;
+        }
+
+      res = INLINE_SYSCALL (utimensat64, 4, fd, file, ts64p, flags);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+    }
+#endif
+
+  if (tsp)
+    {
+      if (! timespec64_to_timespec(&tsp[0], &ts32[0]))
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+
+      if (! timespec64_to_timespec(&tsp[1], &ts32[1]))
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      ts32p = ts32;
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, file, ts32p, flags);
+}
diff --git a/time/Versions b/time/Versions
index 6105da5cb9..e41c661970 100644
--- a/time/Versions
+++ b/time/Versions
@@ -80,5 +80,6 @@  libc {
     __clock_nanosleep64;
     __timespec_get64;
     __futimens64;
+    __utimensat64;
   }
 }