[RFC,24/52] Y2038: add function __fstat64_t64 (and __fxstat64_t64)

Message ID 20170907224219.12483-25-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.
There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h                 |  2 ++
 io/Versions                        |  7 ++++++
 io/fstat64.c                       |  7 ++++++
 sysdeps/unix/sysv/linux/fxstat64.c | 50 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+)

Patch

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 300cf8bbc4..2961849e35 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -37,6 +37,8 @@  extern __mode_t __umask (__mode_t __mask);
 extern int __mkdir (const char *__path, __mode_t __mode);
 extern int __mknod (const char *__path,
 		    __mode_t __mode, __dev_t __dev);
+extern int __fxstat64_t64 (int __ver, int __fildes,
+                           struct __stat64_t64 *__stat_buf);
 #if IS_IN (libc) || IS_IN (rtld)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 64316cd025..747ae5d9d6 100644
--- a/io/Versions
+++ b/io/Versions
@@ -125,4 +125,11 @@  libc {
   GLIBC_2.23 {
     fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __fxstat64_t64;
+  }
 }
diff --git a/io/fstat64.c b/io/fstat64.c
index 69c80e5e45..a972304c0a 100644
--- a/io/fstat64.c
+++ b/io/fstat64.c
@@ -50,3 +50,10 @@  fstat64 (int fd, struct stat64 *buf)
 {
   return __fxstat64 (_STAT_VER, fd, buf);
 }
+
+int
+attribute_hidden
+__fstat64_t64 (int fd, struct __stat64_t64 *buf)
+{
+  return __fxstat64_t64 (_STAT_VER, fd, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 8a59d86d31..6097257b2a 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -24,6 +24,8 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file FD in BUF.  */
@@ -51,3 +53,51 @@  hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__fxstat64_t64 (int vers, int fd, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscalls when they become available
+    }
+
+  result = INLINE_SYSCALL (fstat64, 2, fd, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+      buf->__pad1		     = st64.__pad1;
+    
+      buf->__st_ino        = st64.__st_ino;
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->__pad2          = st64.__pad2;
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}