[RFC,17/52] Y2038: add function __lutimes64

Message ID 20170907224219.12483-18-albert.aribaud@3adev.fr
State New
Headers show
Series
  • Make GLIBC Y2038-proof
Related show

Commit Message

Albert ARIBAUD Sept. 7, 2017, 10:41 p.m.
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 misc/lutimes.c                       |  8 ++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/lutimes.c    | 53 ++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

Patch

diff --git a/misc/lutimes.c b/misc/lutimes.c
index c4cce8f3b6..e01b5c996a 100644
--- a/misc/lutimes.c
+++ b/misc/lutimes.c
@@ -31,3 +31,11 @@  __lutimes (const char *file, const struct timeval tvp[2])
 weak_alias (__lutimes, lutimes)
 
 stub_warning (lutimes)
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__lutimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 155b7889eb..edac9cf007 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -37,5 +37,6 @@  libc {
     __utimensat64;
     __sigtimedwait64;
     __futimes64;
+    __lutimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 433fb06701..c94273abf5 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -42,3 +42,56 @@  lutimes (const char *file, const struct timeval tvp[2])
   return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
 			 AT_SYMLINK_NOFOLLOW);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  /* The system call expects timespec, not timeval.  */
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (__y2038_linux_support)
+    {
+      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;
+        
+          return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, &ts64,
+  	  		     AT_SYMLINK_NOFOLLOW);
+        }
+    
+      return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, NULL,
+  			   AT_SYMLINK_NOFOLLOW);
+    }
+
+  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);
+    
+      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;
+    
+      return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, &ts32,
+                             AT_SYMLINK_NOFOLLOW);
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, NULL,
+                         AT_SYMLINK_NOFOLLOW);
+}