This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch aaribaud/y2038-2.25 created. glibc-2.25-28-g760dff1


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, aaribaud/y2038-2.25 has been created
        at  760dff1905b7388242bad9e1724f58bf7a75030a (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=760dff1905b7388242bad9e1724f58bf7a75030a

commit 760dff1905b7388242bad9e1724f58bf7a75030a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 10:27:17 2017 +0200

    Y2038: implement Y2038-ready fstatat64, fxstatat (WIP)
    
    WIP: 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

diff --git a/io/Versions b/io/Versions
index c02e9ca..03d621b 100644
--- a/io/Versions
+++ b/io/Versions
@@ -133,5 +133,6 @@ libc {
     __xstat64_t64;
     __fxstat64_t64;
     __lxstat64_t64;
+    __fxstatat64_t64;
   }
 }
diff --git a/io/fstatat64.c b/io/fstatat64.c
index 13a9ebc..4e13f07 100644
--- a/io/fstatat64.c
+++ b/io/fstatat64.c
@@ -50,3 +50,10 @@ fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
 {
   return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
 }
+
+int
+attribute_hidden
+__fstatat64_t64 (int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  return __fxstatat64_t64 (_STAT_VER, fd, file, buf, flag);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 68fa91c..b60a5ef 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -443,6 +443,10 @@ extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64_t64)
      __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
+					const char *__filename,
+					struct stat *__stat_buf, int __flag),
+			   __fxstatat64_t64) __nonnull ((3, 4));
 #  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
@@ -453,11 +457,11 @@ extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
-#  endif
 extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
 			   __fxstatat64) __nonnull ((3, 4));
+#  endif
 
 # else
 #  ifdef __USE_TIME_BITS64
@@ -488,6 +492,9 @@ extern int __lxstat64_t64 (int __ver, const char *__filename,
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
 			 struct stat64 *__stat_buf, int __flag)
      __THROW __nonnull ((3, 4));
+extern int __fxstatat64_t64 (int __ver, int __fildes, const char *__filename,
+			 struct __stat64_t64 *__stat_buf, int __flag)
+     __THROW __nonnull ((3, 4));
 #endif
 extern int __xmknod (int __ver, const char *__path, __mode_t __mode,
 		     __dev_t *__dev) __THROW __nonnull ((2, 4));
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index ef1e132..c3631b6 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -26,6 +26,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 /* Get information about the file NAME in BUF.  */
 
 int
@@ -45,3 +47,46 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 								      err));
 }
 libc_hidden_def (__fxstatat64)
+
+int
+__fxstatat64_t64 (int vers, int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  if (__glibc_unlikely (vers != _STAT_VER_LINUX))
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  int result;
+  struct stat64 st64;
+  INTERNAL_SYSCALL_DECL (err);
+
+  result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
+  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
+  {
+    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 0;
+  }
+  else
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
+								      err));
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b44d8568b89b12da83da1354077075b64037f159

commit b44d8568b89b12da83da1354077075b64037f159
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 08:51:53 2017 +0200

    Y2038: implement Y2038-ready lstat64, lxstat64 (WIP)
    
    WIP: 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

diff --git a/io/Versions b/io/Versions
index 2f0e137..c02e9ca 100644
--- a/io/Versions
+++ b/io/Versions
@@ -132,5 +132,6 @@ libc {
   GLIBC_Y2038 {
     __xstat64_t64;
     __fxstat64_t64;
+    __lxstat64_t64;
   }
 }
diff --git a/io/lstat64.c b/io/lstat64.c
index c29492a..50bf7df 100644
--- a/io/lstat64.c
+++ b/io/lstat64.c
@@ -50,3 +50,10 @@ lstat64 (const char *file, struct stat64 *buf)
 {
   return __lxstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__lstat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __lxstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index ef72e07..68fa91c 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -440,6 +440,9 @@ extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64_t64)
      __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
+				      struct stat *__stat_buf), __lxstat64_t64)
+     __nonnull ((2, 3));
 #  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
@@ -447,10 +450,10 @@ extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64)
      __nonnull ((2, 3));
-#  endif
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
+#  endif
 extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
@@ -460,11 +463,12 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 #  ifdef __USE_TIME_BITS64
 #   define __fxstat __fxstat64_t64
 #   define __xstat __xstat64_t64
+#   define __lxstat __lxstat64_t64
 #  else
 #   define __fxstat __fxstat64
 #   define __xstat __xstat64
+#   define __lxstat __lxstat64
 #  endif
-#  define __lxstat __lxstat64
 # endif
 #endif
 
@@ -479,6 +483,8 @@ extern int __xstat64_t64 (int __ver, const char *__filename,
 		      struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __lxstat64 (int __ver, const char *__filename,
 		       struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
+extern int __lxstat64_t64 (int __ver, const char *__filename,
+		       struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
 			 struct stat64 *__stat_buf, int __flag)
      __THROW __nonnull ((3, 4));
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 9bc548f..814fcbc 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -50,3 +52,41 @@ hidden_ver (___lxstat64, __lxstat64)
 strong_alias (___lxstat64, __lxstat64);
 hidden_def (__lxstat64)
 #endif
+
+int
+__lxstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+  result = INLINE_SYSCALL (lstat64, 2, name, &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;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c5cde9ee91b673c61b2b6d510ba6a7cab21bdcc0

commit c5cde9ee91b673c61b2b6d510ba6a7cab21bdcc0
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue May 23 23:15:15 2017 +0200

    Y2038: implement Y2038 stat64, fstat64, xstat64, fxstat64 (WIP)
    
    WIP: 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

diff --git a/io/Versions b/io/Versions
index 64316cd..2f0e137 100644
--- a/io/Versions
+++ b/io/Versions
@@ -125,4 +125,12 @@ 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 {
+    __xstat64_t64;
+    __fxstat64_t64;
+  }
 }
diff --git a/io/fstat64.c b/io/fstat64.c
index 69c80e5..a972304 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/io/stat64.c b/io/stat64.c
index 704cbb3..22fc0db 100644
--- a/io/stat64.c
+++ b/io/stat64.c
@@ -50,3 +50,10 @@ stat64 (const char *file, struct stat64 *buf)
 {
   return __xstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__stat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __xstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 3e546b5..ef72e07 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -210,14 +210,27 @@ extern int stat (const char *__restrict __file,
 extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
+				  struct stat *__restrict __buf), __stat64_t64)
+     __nonnull ((1, 2));
+extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), __fstat64_t64)
+     __nonnull ((2));
+#  else
 extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
 				  struct stat *__restrict __buf), stat64)
      __nonnull ((1, 2));
 extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64)
      __nonnull ((2));
+#  endif
 # else
-#  define stat stat64
-#  define fstat fstat64
+#  ifdef __USE_TIME_BITS64
+#   define stat stat64_t64
+#   define fstat fstat64_t64
+#  else
+#   define stat stat64
+#   define fstat fstat64
+#  endif
 # endif
 #endif
 #ifdef __USE_LARGEFILE64
@@ -420,12 +433,21 @@ extern int __fxstatat (int __ver, int __fildes, const char *__filename,
      __THROW __nonnull ((3, 4));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
+				      struct stat *__stat_buf), __fxstat64_t64)
+     __nonnull ((3));
+extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
+				     struct stat *__stat_buf), __xstat64_t64)
+     __nonnull ((2, 3));
+#  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
      __nonnull ((3));
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64)
      __nonnull ((2, 3));
+#  endif
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
@@ -435,8 +457,13 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 			   __fxstatat64) __nonnull ((3, 4));
 
 # else
-#  define __fxstat __fxstat64
-#  define __xstat __xstat64
+#  ifdef __USE_TIME_BITS64
+#   define __fxstat __fxstat64_t64
+#   define __xstat __xstat64_t64
+#  else
+#   define __fxstat __fxstat64
+#   define __xstat __xstat64
+#  endif
 #  define __lxstat __lxstat64
 # endif
 #endif
@@ -444,8 +471,12 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 #ifdef __USE_LARGEFILE64
 extern int __fxstat64 (int __ver, int __fildes, struct stat64 *__stat_buf)
      __THROW __nonnull ((3));
+extern int __fxstat64_t64 (int __ver, int __fildes, struct __stat64_t64 *__stat_buf)
+     __THROW __nonnull ((3));
 extern int __xstat64 (int __ver, const char *__filename,
 		      struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
+extern int __xstat64_t64 (int __ver, const char *__filename,
+		      struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __lxstat64 (int __ver, const char *__filename,
 		       struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 8a59d86..18bc209 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,41 @@ hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+int
+__fxstat64_t64 (int vers, int fd, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+  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;
+}
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index b3fbe6a..809d6dd 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -52,3 +54,41 @@ hidden_ver (___xstat64, __xstat64)
 strong_alias (___xstat64, __xstat64)
 hidden_def (__xstat64)
 #endif
+
+int
+__xstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+  result = INLINE_SYSCALL (stat64, 2, name, &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_ctim.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;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1467823311f27fe6575ace7a716abe7f2e6507af

commit 1467823311f27fe6575ace7a716abe7f2e6507af
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 08:44:49 2017 +0200

    Y2038: implement struct stat

diff --git a/sysdeps/unix/sysv/linux/bits/stat.h b/sysdeps/unix/sysv/linux/bits/stat.h
index 187590e..3d690b9 100644
--- a/sysdeps/unix/sysv/linux/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/bits/stat.h
@@ -128,6 +128,30 @@ struct stat64
 # endif
     __ino64_t st_ino;			/* File serial number.		*/
   };
+
+#  include <include/time.h>
+
+struct __stat64_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+    unsigned int __pad1;
+
+    __ino_t __st_ino;			/* 32bit file serial number.	*/
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    unsigned int __pad2;
+    __off64_t st_size;			/* Size of file, in bytes.  */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+    struct __timespec64 st_atim;		/* Time of last access.  */
+    struct __timespec64 st_mtim;		/* Time of last modification.  */
+    struct __timespec64 st_ctim;		/* Time of last status change.  */
+    __ino64_t st_ino;			/* File serial number.		*/
+  };
 #endif
 
 /* Tell code we have these members.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9858590638cb41007178439b7f552cb8b1c41328

commit 9858590638cb41007178439b7f552cb8b1c41328
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 3 12:12:17 2017 +0200

    Y2038: implement Y2038-proof timerfd_gettime, timerfd_settime
    
    Note: this tests the return value of function __y2038_kernel_support()
    rather than the value of variable __y2038_linux_upport, because the
    latter cannot be accessed from librt while the former can.

diff --git a/rt/Makefile b/rt/Makefile
index 5283839..4713497 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -32,7 +32,8 @@ clock-routines := get_clockfreq clock_getcpuclockid			\
 		  clock_getres clock_gettime clock_settime		\
 		  clock_nanosleep
 timer-routines := timer_create timer_delete timer_getoverr		\
-		  timer_gettime timer_settime
+		  timer_gettime timer_settime                           \
+		  timerfd_gettime64 timerfd_settime64
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
diff --git a/rt/Versions b/rt/Versions
index 7377976..d14a87f 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -43,5 +43,6 @@ librt {
 
   GLIBC_Y2038 {
     __timer_gettime64; __timer_settime64;
+    __timerfd_gettime64; __timerfd_settime64;
   }
 }
diff --git a/rt/timerfd_gettime64.c b/rt/timerfd_gettime64.c
new file mode 100644
index 0000000..9496fca
--- /dev/null
+++ b/rt/timerfd_gettime64.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+/* Get current value of timer TIMERID and store it in VLAUE.  */
+int
+__timerfd_gettime64 (int fd, struct itimerspec *value)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_gettime64)
diff --git a/rt/timerfd_settime64.c b/rt/timerfd_settime64.c
new file mode 100644
index 0000000..8551c7a
--- /dev/null
+++ b/rt/timerfd_settime64.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+/* Set timer TIMERID to VALUE, returning old value in OVLAUE.  */
+int
+__timerfd_settime64 (int fd, int flags, const struct itimerspec *value,
+	       struct itimerspec *ovalue)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_settime64)
diff --git a/sysdeps/unix/sysv/linux/sys/timerfd.h b/sysdeps/unix/sysv/linux/sys/timerfd.h
index 6899b5e..78d8fae 100644
--- a/sysdeps/unix/sysv/linux/sys/timerfd.h
+++ b/sysdeps/unix/sysv/linux/sys/timerfd.h
@@ -41,11 +41,30 @@ extern int timerfd_create (__clockid_t __clock_id, int __flags) __THROW;
 /* Set next expiration time of interval timer source UFD to UTMR.  If
    FLAGS has the TFD_TIMER_ABSTIME flag set the timeout value is
    absolute.  Optionally return the old expiration time in OTMR.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_settime, (int __ufd, int __flags,
+                       const struct itimerspec *__utmr,
+                       struct itimerspec *__otmr),__timerfd_settime64)
+                       __THROW;
+# else
+# define timerfd_settime __timerfd_settime64
+# endif
+#endif
 extern int timerfd_settime (int __ufd, int __flags,
 			    const struct itimerspec *__utmr,
 			    struct itimerspec *__otmr) __THROW;
 
 /* Return the next expiration time of UFD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_gettime, (int __ufd,
+                       struct itimerspec *__otmr),__timerfd_gettime64)
+                       __THROW;
+# else
+# define timerfd_gettime __timerfd_gettime64
+# endif
+#endif
 extern int timerfd_gettime (int __ufd, struct itimerspec *__otmr) __THROW;
 
 __END_DECLS
diff --git a/sysdeps/unix/sysv/linux/timerfd_gettime64.c b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
new file mode 100644
index 0000000..5c2105c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_gettime64 (int fd, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timerfd_gettime64, 2, fd, value);
+
+  int res = INLINE_SYSCALL (timerfd_gettime, 2, fd, &value32);
+
+  if (res == 0)
+  {
+    value->it_value.tv_sec = value32.it_value.tv_sec;
+    value->it_value.tv_nsec = value32.it_value.tv_nsec;
+    value->it_interval.tv_sec = value32.it_interval.tv_sec;
+    value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+  }
+
+  return res;
+}
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime64.c b/sysdeps/unix/sysv/linux/timerfd_settime64.c
new file mode 100644
index 0000000..b20f0e1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_settime64.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
+	             struct __itimerspec64 *ovalue)
+{
+  int res;
+  struct __itimerspec64 value64;
+  struct itimerspec value32;
+  struct itimerspec ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+  {
+    value64.it_value.tv_sec = value->it_value.tv_sec;
+    value64.it_value.tv_nsec = value->it_value.tv_nsec;
+    value64.it_value.tv_pad = 0;
+    value64.it_interval.tv_sec = value->it_interval.tv_sec;
+    value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+    value64.it_interval.tv_pad = 0;
+    
+    return INLINE_SYSCALL (timerfd_settime64, 4, fd, flags,
+                           &value64, ovalue);
+  }
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    return EOVERFLOW;
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  res = INLINE_SYSCALL (timerfd_settime, 4, fd, flags,
+                        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+  {
+    ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+    ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+    ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+    ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+  }
+
+  return res;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=dc8f23b1d6b29afe6264a456e0efe0e0af9baf31

commit dc8f23b1d6b29afe6264a456e0efe0e0af9baf31
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 3 09:19:14 2017 +0200

    Y2038: implement Y2038-proof timer_gettime, timer_settime

diff --git a/rt/Versions b/rt/Versions
index 91e3fd2..7377976 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,11 @@ librt {
   GLIBC_2.7 {
    __mq_open_2;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timer_gettime64; __timer_settime64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 849c56a..48e16fa 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -39,3 +39,27 @@ timer_gettime (timer_t timerid, struct itimerspec *value)
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+  struct timer *kt = (struct timer *) timerid;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+
+  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &value32);
+
+  if (res == 0)
+  {
+    value->it_value.tv_sec = value32.it_value.tv_sec;
+    value->it_value.tv_nsec = value32.it_value.tv_nsec;
+    value->it_interval.tv_sec = value32.it_interval.tv_sec;
+    value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+  }
+
+  return res;
+}
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index ba35036..e3caa7f 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -41,3 +41,52 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_settime64 (timer_t timerid, int flags, const struct itimerspec *value,
+	       struct itimerspec *ovalue)
+{
+  struct timer *kt = (struct timer *) timerid;
+  struct __itimerspec64 value64;
+  struct itimerspec value32, ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+  {
+    value64.it_value.tv_sec = value->it_value.tv_sec;
+    value64.it_value.tv_nsec = value->it_value.tv_nsec;
+    value64.it_value.tv_pad = 0;
+    value64.it_interval.tv_sec = value->it_interval.tv_sec;
+    value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+    value64.it_interval.tv_pad = 0;
+
+    return INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
+			    &value64, ovalue);
+  }
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    return EOVERFLOW;
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+  {
+    ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+    ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+    ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+    ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+  }
+
+  return res;
+}
diff --git a/time/time.h b/time/time.h
index dd9fff6..8b2954f 100644
--- a/time/time.h
+++ b/time/time.h
@@ -364,11 +364,29 @@ extern int timer_create (clockid_t __clock_id,
 extern int timer_delete (timer_t __timerid) __THROW;
 
 /* Set timer TIMERID to VALUE, returning old value in OVALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_settime, (timer_t __timerid, int __flags,
+			  const struct itimerspec *__restrict __value,
+			  struct itimerspec *__restrict __ovalue),
+                          __timer_settime64) __THROW;
+# else
+# define timer_settime __timer_settime64
+# endif
+#endif
 extern int timer_settime (timer_t __timerid, int __flags,
 			  const struct itimerspec *__restrict __value,
 			  struct itimerspec *__restrict __ovalue) __THROW;
 
 /* Get current value of timer TIMERID and store it in VALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_gettime, (timer_t __timerid, struct
+     itimerspec *__value), __timer_gettime64) __THROW __nonnull ((1));
+# else
+# define timer_gettime __timer_gettime64
+# endif
+#endif
 extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
      __THROW;
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=675c5d3c79e7587a24396957396a3d33e5ef48b4

commit 675c5d3c79e7587a24396957396a3d33e5ef48b4
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 12 23:41:11 2017 +0200

    Y2038: implement Y2038-proof struct itimerspec
    
    When time_t was introduced, all time_t based types were modified
    to use a 64-bit time_t. This is indirectly the case for struct
    itimespec too, which contains two struct timerspec fields, it_interval
    and it_value.

diff --git a/include/time.h b/include/time.h
index 06f4084..e7dc9ea 100644
--- a/include/time.h
+++ b/include/time.h
@@ -49,6 +49,12 @@ struct __timeval64
   __int64_t tv_usec;		/* Microseconds */
 };
 
+struct __itimerspec64
+{
+  struct __timespec64 it_interval;
+  struct __timespec64 it_value;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=35464f8f047248b0fe6c5927fc9e37f9264ea3f2

commit 35464f8f047248b0fe6c5927fc9e37f9264ea3f2
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 26 00:35:05 2017 +0200

    Y2038: implement Y2038-proof lutimes

diff --git a/misc/lutimes.c b/misc/lutimes.c
index c4cce8f..e01b5c9 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 3179a00..2679ec3 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -36,5 +36,6 @@ libc {
     __utimensat64;
     __sigtimedwait64;
     __futimes64;
+    __lutimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 433fb06..bf87f58 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);
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index 78fa3f3..c179227 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -137,6 +137,14 @@ extern int utimes (const char *__file, const struct timeval __tvp[2])
 
 #ifdef __USE_MISC
 /* Same as `utimes', but does not follow symbolic links.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (lutimes, (const char *__file,
+       const struct timeval __tvp[2]), __lutimes64) __THROW;
+# else
+# define lutimes __lutimes64
+# endif
+#endif
 extern int lutimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=00f4e4e8557dc6606de26a5aad3fd0387093e3bf

commit 00f4e4e8557dc6606de26a5aad3fd0387093e3bf
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 26 00:03:32 2017 +0200

    Y2038: implement Y2038-proof futimes

diff --git a/include/time.h b/include/time.h
index 18f223a..06f4084 100644
--- a/include/time.h
+++ b/include/time.h
@@ -43,6 +43,12 @@ struct __timespec64
 };
 #endif
 
+struct __timeval64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __int64_t tv_usec;		/* Microseconds */
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
diff --git a/misc/futimes.c b/misc/futimes.c
index 6dad999..e4c9ee2 100644
--- a/misc/futimes.c
+++ b/misc/futimes.c
@@ -30,3 +30,12 @@ __futimes (int fd, const struct timeval tvp[2])
 weak_alias (__futimes, futimes)
 
 stub_warning (futimes)
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__futimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 3217f00..3179a00 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -35,5 +35,6 @@ libc {
     __futimens64;
     __utimensat64;
     __sigtimedwait64;
+    __futimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index af79cb1..1043d03 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -49,3 +49,55 @@ __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 */
+
+extern int __y2038_linux_support;
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  /* The utimensat 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, fd, NULL, &ts64, 0);
+    }
+
+    return INLINE_SYSCALL (utimensat64, 4, fd, NULL, NULL, 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);
+
+    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;
+
+    return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32, 0);
+  }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, NULL, 0);
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index 165296a..78fa3f3 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -141,6 +141,14 @@ extern int lutimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 
 /* Same as `utimes', but takes an open file descriptor instead of a name.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimes, (int __fd, const struct timeval __tvp[2]),
+     __futimes64) __THROW;
+# else
+# define futimes __futimes64
+# endif
+#endif
 extern int futimes (int __fd, const struct timeval __tvp[2]) __THROW;
 #endif
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=972127f35f7ebfb1086923563e069af356a9be23

commit 972127f35f7ebfb1086923563e069af356a9be23
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Apr 25 23:21:28 2017 +0200

    Y2038: implement Y2038-proof sigtimedwait

diff --git a/signal/signal.h b/signal/signal.h
index 2c7f9e1..bec7ca6 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -280,6 +280,16 @@ extern int sigwaitinfo (const sigset_t *__restrict __set,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (sigtimedwait, (const sigset_t *__restrict __set,
+			 siginfo_t *__restrict __info,
+			 const struct timespec *__restrict __timeout),
+     __sigtimedwait64) __nonnull ((1));
+# else
+# define sigtimedwait __sigtimedwait64
+# endif
+#endif
 extern int sigtimedwait (const sigset_t *__restrict __set,
 			 siginfo_t *__restrict __info,
 			 const struct timespec *__restrict __timeout)
diff --git a/signal/sigtimedwait.c b/signal/sigtimedwait.c
index 3b42003..c1e0d43 100644
--- a/signal/sigtimedwait.c
+++ b/signal/sigtimedwait.c
@@ -30,3 +30,13 @@ libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
 
 stub_warning (sigtimedwait)
+
+int
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__sigtimedwait64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 3f514b5..3217f00 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -34,5 +34,6 @@ libc {
     __clock_nanosleep64;
     __futimens64;
     __utimensat64;
+    __sigtimedwait64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index ab1a84e..77339ea 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+#include <stdint.h>
 
 #include <nptl/pthreadP.h>
 #include <sysdep-cancel.h>
@@ -64,6 +65,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  int result;
+  struct __timespec64 ts64;
+  struct timespec ts32;
+
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+
+  if (__y2038_linux_support)
+  {
+    if (timeout)
+    {
+      ts64.tv_sec = timeout->tv_sec;
+      ts64.tv_nsec = timeout->tv_nsec;
+      ts64.tv_pad = 0;
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts64, _NSIG / 8);
+    }
+    else
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+  }
+  else
+  {
+    if (timeout)
+    {
+      if (timeout->tv_sec > INT32_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      ts32.tv_sec = timeout->tv_sec;
+      ts32.tv_nsec = timeout->tv_nsec;
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts32, _NSIG / 8);
+    }
+    else
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+  }
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
 #else
 # include <signal/sigtimedwait.c>
 #endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c442b9bb215b22ab56dea05f28ec2d03943a272e

commit c442b9bb215b22ab56dea05f28ec2d03943a272e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Apr 20 09:17:50 2017 +0200

    Y2038: implement Y2038-proof utimensat

diff --git a/io/sys/stat.h b/io/sys/stat.h
index f58d05c..3e546b5 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -357,6 +357,15 @@ extern int mkfifoat (int __fd, const char *__path, __mode_t __mode)
 #ifdef __USE_ATFILE
 /* Set file access and modification times relative to directory file
    descriptor.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utimensat, (int __fd, const char *__path,
+           const struct timespec __times[2], int __flags),
+           __utimensat64) __THROW __nonnull((2));
+# else
+# define utimensat __utimensat64
+# endif
+#endif
 extern int utimensat (int __fd, const char *__path,
 		      const struct timespec __times[2],
 		      int __flags)
diff --git a/io/utimensat.c b/io/utimensat.c
index f45eb73..6b9cf43 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/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 5e33f9c..3f514b5 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -33,5 +33,6 @@ libc {
     __vdso_clock_gettime64;
     __clock_nanosleep64;
     __futimens64;
+    __utimensat64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 87f1ef0..eb382b1 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sysdep.h>
+#include <stdio.h>
 
 
 /* Change the access time of FILE to TSP[0] and
@@ -34,3 +35,38 @@ 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 __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (file == NULL)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  if (!tsp)
+    return INLINE_SYSCALL (utimensat64, 4, fd, file, NULL, flags);
+
+  if (__y2038_linux_support)
+  {
+    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;
+    return INLINE_SYSCALL (utimensat64, 4, fd, file, &ts64, flags);
+  }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, file, &ts32, flags);
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7b09a425780f6fdd0ded56de6cb0f90aad6ea056

commit 7b09a425780f6fdd0ded56de6cb0f90aad6ea056
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 19 10:02:59 2017 +0200

    Y2038: implement Y2038-proof futimens

diff --git a/io/futimens.c b/io/futimens.c
index 27fc1ae..516e64e 100644
--- a/io/futimens.c
+++ b/io/futimens.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <time.h>
 #include <sysdep.h>
+#include <kernel_timespec.h>
 
 
 /* Change the access time of the file associated with FD to TSP[0] and
@@ -32,3 +33,11 @@ futimens (int fd, const struct timespec tsp[2])
   return -1;
 }
 stub_warning (futimens)
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__futimens64)
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 2ada4a5..f58d05c 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -365,6 +365,14 @@ extern int utimensat (int __fd, const char *__path,
 
 #ifdef __USE_XOPEN2K8
 /* Set file access and modification times of the file associated with FD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimens, (int __fd, const struct timespec __times[2]),
+           __futimens64) __THROW;
+# else
+# define futimens __futimens64
+# endif
+#endif
 extern int futimens (int __fd, const struct timespec __times[2]) __THROW;
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index a5abd71..5e33f9c 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -32,5 +32,6 @@ libc {
     __clock_gettime64; __clock_settime64; __clock_getres64;
     __vdso_clock_gettime64;
     __clock_nanosleep64;
+    __futimens64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index b4985e0..e2f5d28 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -36,3 +36,41 @@ futimens (int fd, const struct timespec tsp[2])
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (fd < 0)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+
+  if (__y2038_linux_support)
+  {
+    if (fd < 0)
+      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+    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;
+    return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64[0], 0);
+  }
+
+  if (tsp[0].tv_sec > INT_MAX || tsp[1].tv_sec > INT_MAX)
+  {
+    return EOVERFLOW;
+  }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32[0], 0);
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=ea72a71578cabc5cc58ed0db0c1a050cc4d30b55

commit ea72a71578cabc5cc58ed0db0c1a050cc4d30b55
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jun 21 01:04:02 2017 +0200

    Y2038: implement Y2038-proof timespec_get

diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 1f63e57..b43b5ae 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -44,3 +44,38 @@ timespec_get (struct timespec *ts, int base)
 
   return base;
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__timespec_get64 (struct __timespec64 *ts, int base)
+{
+  switch (base)
+    {
+      int res;
+      INTERNAL_SYSCALL_DECL (err);
+    case TIME_UTC:
+      if (__y2038_linux_support)
+      {
+        res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+      }
+      else
+      {
+        struct timespec ts32;
+        res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts32);
+        if (INTERNAL_SYSCALL_ERROR_P (res, err))
+	  return 0;
+        ts->tv_sec = ts32.tv_sec;
+        ts->tv_nsec = ts32.tv_nsec;
+        ts->tv_pad = 0;
+      }
+      break;
+
+    default:
+      return 0;
+    }
+
+  return base;
+}
diff --git a/time/Versions b/time/Versions
index fd83818..3fe8608 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,4 +65,11 @@ libc {
   GLIBC_2.16 {
     timespec_get;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timespec_get64;
+  }
 }
diff --git a/time/time.h b/time/time.h
index 69eac79..dd9fff6 100644
--- a/time/time.h
+++ b/time/time.h
@@ -379,6 +379,14 @@ extern int timer_getoverrun (timer_t __timerid) __THROW;
 
 #ifdef __USE_ISOC11
 /* Set TS to calendar time based in time base BASE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timespec_get, (struct timespec *__ts, int __base),
+     __timespec_get64) __THROW __nonnull ((1));
+# else
+# define timespec_get __timespec_get64
+# endif
+#endif
 extern int timespec_get (struct timespec *__ts, int __base)
      __THROW __nonnull ((1));
 #endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=934f6ef8acfb77fe6eac237fbc88ce566fc2285c

commit 934f6ef8acfb77fe6eac237fbc88ce566fc2285c
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Apr 11 22:35:48 2017 +0200

    Y2038: implement Y2038-proof clock_nanosleep

diff --git a/include/time.h b/include/time.h
index 9b29235..18f223a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -51,6 +51,9 @@ extern int __clock_gettime64 (clockid_t __clock_id, struct __timespec64 *__tp) _
 extern __typeof (clock_settime) __clock_settime;
 extern int __clock_settime64 (clockid_t __clock_id, const struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+			    const struct __timespec64 *__req,
+			    struct __timespec64 *__rem);
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
 /* Now define the internal interfaces.  */
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index e3cd16d..a5abd71 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -31,5 +31,6 @@ libc {
     __timegm64;
     __clock_gettime64; __clock_settime64; __clock_getres64;
     __vdso_clock_gettime64;
+    __clock_nanosleep64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93bc4cf..479619e 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -21,7 +21,6 @@
 #include <sysdep-cancel.h>
 #include "kernel-posix-cpu-timers.h"
 
-
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
@@ -52,3 +51,89 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+		   const struct __timespec64 *req,
+                   struct __timespec64 *rem)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  int r;
+  struct __timespec64 req64;
+  struct timespec req32, rem32;
+
+  if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+    return EINVAL;
+  if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+    clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
+  if (SINGLE_THREAD_P)
+  {
+    if (__y2038_linux_support)
+    {
+      req64.tv_sec = req->tv_sec;
+      req64.tv_nsec = req->tv_nsec;
+      req64.tv_pad = 0;
+      r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                            &req64, rem);
+    }
+    else if (req->tv_sec > INT_MAX)
+      r = EOVERFLOW;
+    else
+    {
+      req32.tv_sec = req->tv_sec;
+      req32.tv_nsec = req->tv_nsec;
+      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                            &req32, &rem32);
+      if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+      {
+        rem->tv_sec = rem32.tv_sec;
+        rem->tv_nsec = rem32.tv_nsec;
+        rem->tv_pad = 0;
+      }
+    }
+  }
+  else
+    {
+      int oldstate = LIBC_CANCEL_ASYNC ();
+
+      if (__y2038_linux_support)
+      {
+        req64.tv_sec = req->tv_sec;
+        req64.tv_nsec = req->tv_nsec;
+        req64.tv_pad = 0;
+        r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                              &req64, rem);
+      }
+      else if (req->tv_sec > INT_MAX)
+        r = EOVERFLOW;
+      else
+      {
+        req32.tv_sec = req->tv_sec;
+        req32.tv_nsec = req->tv_nsec;
+        r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                              &req32, &rem32);
+        if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+        {
+          rem->tv_sec = rem32.tv_sec;
+          rem->tv_nsec = rem32.tv_nsec;
+          rem->tv_pad = 0;
+        }
+      }
+      
+      LIBC_CANCEL_RESET (oldstate);
+    }
+
+  if (INTERNAL_SYSCALL_ERROR_P (r, err))
+  {
+    return INTERNAL_SYSCALL_ERRNO (r, err);
+  }
+  else
+  {
+    return 0;
+  }
+}
diff --git a/time/time.h b/time/time.h
index 07ad045..69eac79 100644
--- a/time/time.h
+++ b/time/time.h
@@ -337,6 +337,15 @@ extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_nanosleep, (clockid_t __clock_id, int __flags,
+     const struct timespec *__req, struct timespec *__rem),
+     __clock_nanosleep64) __THROW;
+# else
+# define clock_nanosleep __clock_nanosleep64
+# endif
+#endif
 extern int clock_nanosleep (clockid_t __clock_id, int __flags,
 			    const struct timespec *__req,
 			    struct timespec *__rem);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=99b7ec1e4f2bb9ceaa7f5e51c0a8943681cd113f

commit 99b7ec1e4f2bb9ceaa7f5e51c0a8943681cd113f
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Jun 20 23:37:11 2017 +0200

    Y2038: implement Y2038-proof clock_gettime, clock_settime, and clock_getres

diff --git a/include/time.h b/include/time.h
index 3f4a4c3..9b29235 100644
--- a/include/time.h
+++ b/include/time.h
@@ -22,6 +22,11 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+/* Indicates whether the underlying kernel has 64-bit time support.
+   This is required for e.g. librt, which cannot directly check the
+   flag variable that init-first.c sets when detecting support. */
+extern int __y2038_kernel_support (void);
+
 #if BYTE_ORDER == BIG_ENDIAN
 struct __timespec64
 {
@@ -40,8 +45,11 @@ struct __timespec64
 
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
+extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
 libc_hidden_proto (__clock_gettime)
+extern int __clock_gettime64 (clockid_t __clock_id, struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_settime) __clock_settime;
+extern int __clock_settime64 (clockid_t __clock_id, const struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index b6248be..3b74014 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -23,7 +23,6 @@
 #include <sys/param.h>
 #include <libc-internal.h>
 
-
 #if HP_TIMING_AVAIL
 static long int nsec;		/* Clock frequency of the processor.  */
 
@@ -53,6 +52,33 @@ hp_timing_getres (struct timespec *res)
 
   return 0;
 }
+
+static int
+hp_timing_getres64 (struct __timespec64 *res)
+{
+  if (__glibc_unlikely (nsec == 0))
+    {
+      hp_timing_t freq;
+
+      /* This can only happen if we haven't initialized the `nsec'
+	 variable yet.  Do this now.  We don't have to protect this
+	 code against multiple execution since all of them should
+	 lead to the same result.  */
+      freq = __get_clockfreq ();
+      if (__glibc_unlikely (freq == 0))
+	/* Something went wrong.  */
+	return -1;
+
+      nsec = MAX (UINT64_C (1000000000) / freq, 1);
+    }
+
+  /* Fill in the values.
+     The seconds are always zero (unless we have a 1Hz machine).  */
+  res->tv_sec = 0;
+  res->tv_nsec = nsec;
+
+  return 0;
+}
 #endif
 
 static inline int
@@ -73,6 +99,24 @@ realtime_getres (struct timespec *res)
   return -1;
 }
 
+static inline int
+realtime_getres64 (struct __timespec64 *res)
+{
+  long int clk_tck = sysconf (_SC_CLK_TCK);
+
+  if (__glibc_likely (clk_tck != -1))
+    {
+      /* This implementation assumes that the realtime clock has a
+	 resolution higher than 1 second.  This is the case for any
+	 reasonable implementation.  */
+      res->tv_sec = 0;
+      res->tv_nsec = 1000000000 / clk_tck;
+      return 0;
+    }
+
+  return -1;
+}
+
 
 /* Get resolution of clock.  */
 int
@@ -116,3 +160,44 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
   return retval;
 }
 weak_alias (__clock_getres, clock_getres)
+
+int
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETRES64
+      SYSDEP_GETRES64;
+#endif
+
+#ifndef HANDLED_REALTIME64
+    case CLOCK_REALTIME64:
+      retval = realtime_getres64 (res);
+      break;
+#endif	/* handled REALTIME */
+
+    default:
+#ifdef SYSDEP_GETRES_CPU64
+      SYSDEP_GETRES_CPU64;
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_getres64 (res);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+    case CLOCK_THREAD_CPUTIME_ID:
+      retval = hp_timing_getres64 (res);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 5262066..ac224c9 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -134,3 +134,49 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+/* Get current value of CLOCK and store it in TP, 64-bit version.  */
+int
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETTIME64
+      SYSDEP_GETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      {
+	struct timeval tv;
+	retval = gettimeofday (&tv, NULL);
+	if (retval == 0)
+	  TIMEVAL_TO_TIMESPEC (&tv, tp);
+      }
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_GETTIME64_CPU
+      SYSDEP_GETTIME64_CPU (clock_id, tp);
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_gettime (clock_id, tp);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+      retval = hp_timing_gettime (clock_id, tp);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 957a4b1..3c08558 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -69,8 +69,62 @@ hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
 }
 #endif
 
+/* Set CLOCK to value TP, 64-bit Y2038-safe version.  */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+  int retval = EOVERFLOW;
+
+  /* Make sure the time cvalue is OK.  */
+  if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  switch (clock_id)
+    {
+#define HANDLE_REALTIME \
+      do {								      \
+	struct timeval tv;						      \
+	TIMESPEC_TO_TIMEVAL (&tv, tp);					      \
+									      \
+	retval = settimeofday (&tv, NULL);				      \
+      } while (0)
+
+#ifdef SYSDEP_SETTIME64
+      SYSDEP_SETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      HANDLE_REALTIME;
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_SETTIME64_CPU
+      SYSDEP_SETTIME64_CPU;
+#endif
+#ifndef HANDLED_CPUTIME
+# if HP_TIMING_AVAIL
+      if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
+	  || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_settime (clock_id, tp);
+      else
+# endif
+	{
+	  __set_errno (EINVAL);
+	  retval = -1;
+	}
+#endif
+      break;
+    }
+
+  return retval;
+}
 
-/* Set CLOCK to value TP.  */
+/* Set CLOCK to value TP, 64-bit Y2038-unsafe version.  */
 int
 __clock_settime (clockid_t clock_id, const struct timespec *tp)
 {
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index f7feda3..e3cd16d 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -15,6 +15,8 @@ libc {
     __default_sa_restorer; __default_rt_sa_restorer;
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
+    # __y2038_kernel_support is used by e.g. librt
+    __y2038_kernel_support;
   }
 
   # Y2038 symbols are given their own version until they can be put in
@@ -27,5 +29,7 @@ libc {
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
     __timegm64;
+    __clock_gettime64; __clock_settime64; __clock_getres64;
+    __vdso_clock_gettime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/init-first.c b/sysdeps/unix/sysv/linux/arm/init-first.c
index 3c289c2..61c01a5 100644
--- a/sysdeps/unix/sysv/linux/arm/init-first.c
+++ b/sysdeps/unix/sysv/linux/arm/init-first.c
@@ -23,6 +23,14 @@
 
 int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *) attribute_hidden;
 int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
+
+int __y2038_linux_support;
+
+int __y2038_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -36,6 +44,13 @@ _libc_vdso_platform_setup (void)
   p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
   PTR_MANGLE (p);
   VDSO_SYMBOL (clock_gettime) = p;
+
+  /* (aaribaud) TODO: map to version where clock_gettime64 officially appears */
+  p = _dl_vdso_vsym ("__vdso_clock_gettime64", NULL);
+  PTR_MANGLE (p);
+  VDSO_SYMBOL (clock_gettime64) = p;
+
+  __y2038_linux_support = (p != NULL) ? 1 : 0;
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup
diff --git a/sysdeps/unix/sysv/linux/arm/libc-vdso.h b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
index ae37b57..ee0e594 100644
--- a/sysdeps/unix/sysv/linux/arm/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
@@ -27,6 +27,7 @@
 extern int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *)
    attribute_hidden;
 extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+extern long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
 
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 2b7bb65..3da8c0e 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -48,4 +48,44 @@
 #define SYSDEP_GETRES_CPU SYSCALL_GETRES
 #define SYSDEP_GETRES_CPUTIME	/* Default catches them too.  */
 
+/* The 64-bit version */
+
+extern int __y2038_linux_support;
+
+#define SYSCALL_GETRES64 \
+  if (__y2038_linux_support)						      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_getres64, 2, clock_id, res);  	      \
+  }									      \
+  else									      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);	      \
+    if (retval==0)							      \
+    {									      \
+      res->tv_sec = ts32.tv_sec;		                	      \
+      res->tv_nsec = ts32.tv_nsec;					      \
+      res->tv_pad = 0;				                	      \
+    }									      \
+  }									      \
+  break
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETRES64							      \
+  SYSDEP_GETRES_CPUTIME64							      \
+  case CLOCK_REALTIME:							      \
+  case CLOCK_MONOTONIC:							      \
+  case CLOCK_MONOTONIC_RAW:						      \
+  case CLOCK_REALTIME_COARSE:						      \
+  case CLOCK_MONOTONIC_COARSE:						      \
+    SYSCALL_GETRES64
+
+/* We handled the REALTIME clock here.  */
+#define HANDLED_REALTIME64	1
+#define HANDLED_CPUTIME64	1
+
+#define SYSDEP_GETRES_CPU64 SYSCALL_GETRES64
+#define SYSDEP_GETRES_CPUTIME64 \
+  struct timespec ts32;
+ 
 #include <sysdeps/posix/clock_getres.c>
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index e232f69..30d3e12 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -44,4 +44,48 @@
   break
 #define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
 
+/* 64-bit versions */
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETTIME64 \
+  SYSDEP_GETTIME64_CPUTIME;						      \
+  case CLOCK_REALTIME:							      \
+  case CLOCK_MONOTONIC:							      \
+    if (__y2038_linux_support)						      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+    }									      \
+    else								      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+      if (retval==0)							      \
+      {									      \
+        tp->tv_sec = ts32.tv_sec;					      \
+        tp->tv_nsec = ts32.tv_nsec;					      \
+        tp->tv_pad = 0;							      \
+      }									      \
+    }									      \
+    break
+
+#define SYSDEP_GETTIME64_CPU(clock_id, tp) \
+  if (__y2038_linux_support)						      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+  }									      \
+  else									      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+    if (retval==0)							      \
+    {									      \
+      tp->tv_sec = ts32.tv_sec;						      \
+      tp->tv_nsec = ts32.tv_nsec;					      \
+      tp->tv_pad = 0;							      \
+    }									      \
+  }									      \
+  break
+#define SYSDEP_GETTIME64_CPUTIME \
+  struct timespec ts32;							      \
+  extern int __y2038_linux_support;
+
 #include <sysdeps/unix/clock_gettime.c>
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 058c518..2821956 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -35,4 +35,27 @@
 #define SYSDEP_SETTIME_CPU \
   retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
 
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+#define SYSDEP_SETTIME64 \
+  case CLOCK_REALTIME:							      \
+    if (__y2038_linux_support)						      \
+    {									      \
+      struct __timespec64 ts64;						      \
+      ts64.tv_sec = tp->tv_sec;						      \
+      ts64.tv_nsec = tp->tv_nsec;					      \
+      ts64.tv_pad = 0;							      \
+      retval = INLINE_SYSCALL (clock_settime64, 2, clock_id, &ts64);	      \
+    }									      \
+    else if (tp->tv_sec <= INT_MAX)					      \
+    {									      \
+      struct timespec ts32;						      \
+      ts32.tv_sec = tp->tv_sec;						      \
+      ts32.tv_nsec = tp->tv_nsec;					      \
+      retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32);	      \
+    }									      \
+    break
+
 #include <sysdeps/unix/clock_settime.c>
diff --git a/time/time.h b/time/time.h
index f89884d..07ad045 100644
--- a/time/time.h
+++ b/time/time.h
@@ -299,12 +299,36 @@ extern int nanosleep (const struct timespec *__requested_time,
 
 
 /* Get resolution of clock CLOCK_ID.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_getres, (clockid_t __clock_id, struct
+     timespec *__res), __clock_getres64) __THROW;
+# else
+# define clock_getres __clock_getres64
+# endif
+#endif
 extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW;
 
 /* Get current value of clock CLOCK_ID and store it in TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_gettime, (clockid_t __clock_id, struct
+     timespec *__tp), __clock_gettime64) __THROW;
+# else
+# define clock_gettime __clock_gettime64
+# endif
+#endif
 extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
 
 /* Set clock CLOCK_ID to value TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_settime, (clockid_t __clock_id, const struct
+     timespec *__tp), __clock_settime64) __THROW;
+# else
+# define clock_settime __clock_settime64
+# endif
+#endif
 extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
      __THROW;
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9c54cb17448d742145d828081f3d16484bf5be5b

commit 9c54cb17448d742145d828081f3d16484bf5be5b
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 12 23:23:27 2017 +0200

    Y2038: implement Y2038-proof struct timespec
    
    When time_t was introduced, all time_t based types were modified
    to use a 64-bit time_t. This is the case for struct timespec too,
    which made its Y2038-proof variant contain a 64-bit tv_sec field
    and a long (32-bit) tv_nsec field.
    
    While this definition would be compatible with Posix requirements,
    it would result in the GLIBC struct timespec being binary-incompatible
    with the Linux struct timespec, which contains a 64-bit, ot 32-bit,
    signed tv_nsec field.
    
    In order to maintain Posix compatibility yet simplify conversion
    between Posix and Linux struct timespec values, the Y2038-proof
    struct time stores its tv_nsec field as a 32-bit signed integer
    plus a padding which can serve as a 64-bit sign extension. This
    both meets Posix requirements and makes the GLIBC and Linux
    struct timespec binary compatible.
    
    This change provides both an API (public) and implementation
    (private) version of struct timespec, so that in the API version,
    the padding is made 'invisible' by defining it as an anonymous
    bitfield; whereas the private struct timespec has a named field
    for the padding, allowing implementations to test or set it.

diff --git a/include/time.h b/include/time.h
index f995a2a..3f4a4c3 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,8 @@
 #ifndef _ISOMAC
 # include <xlocale.h>
 
+#include <endian.h>
+
 __BEGIN_DECLS
 
 extern __typeof (strftime_l) __strftime_l;
@@ -20,6 +22,22 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+#if BYTE_ORDER == BIG_ENDIAN
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+};
+#else
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+};
+#endif
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 644db9f..9f75a6d 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -2,13 +2,30 @@
 #define __timespec_defined 1
 
 #include <bits/types.h>
+#include <endian.h>
 
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
+# ifndef __USE_TIME_BITS64
 struct timespec
 {
   __time_t tv_sec;		/* Seconds.  */
   __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
 };
+# elif BYTE_ORDER == BIG_ENDIAN
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  int: 32;			/* Hidden padding */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+};
+# else
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+  int: 32;			/* Hidden padding */
+};
+# endif
 
 #endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=386a72c3a395d282df0b2ef810d59be9fa493cbc

commit 386a72c3a395d282df0b2ef810d59be9fa493cbc
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 5 22:51:34 2017 +0200

    Y2038: implement Y2038-proof timegm
    
    The __timegm64' implementation is based on the same __mktime64_internal
    function which was introduced in the 'mktime' implementation change.
    
    Again, the implementation does not require a Y2038-proof kernel.

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 546d7c6..f7feda3 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -26,5 +26,6 @@ libc {
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
+    __timegm64;
   }
 }
diff --git a/time/time.h b/time/time.h
index 7260d28..f89884d 100644
--- a/time/time.h
+++ b/time/time.h
@@ -265,6 +265,13 @@ extern int stime (const time_t *__when) __THROW;
    localtime package.  These are included only for compatibility.  */
 
 /* Like `mktime', but for TP represents Universal Time, not local time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timegm, (struct tm *__tp), __timegm64) __THROW;
+# else
+# define timegm __timegm64
+# endif
+#endif
 extern time_t timegm (struct tm *__tp) __THROW;
 
 /* Another name for `mktime'.  */
diff --git a/time/timegm.c b/time/timegm.c
index b0f5d16..89fac10 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -36,6 +36,9 @@
 time_t __mktime_internal (struct tm *,
 			  struct tm * (*) (time_t const *, struct tm *),
 			  time_t *);
+__time64_t __mktime64_internal (struct tm *,
+			  struct tm * (*) (__time64_t const *, struct tm *),
+			  __time64_t *);
 #endif
 
 time_t
@@ -45,3 +48,11 @@ timegm (struct tm *tmp)
   tmp->tm_isdst = 0;
   return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
 }
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+  static __time64_t gmtime64_offset;
+  tmp->tm_isdst = 0;
+  return __mktime64_internal (tmp, __gmtime64_r, &gmtime64_offset);
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2dbd80866fee7ba40690d73b826e0252aa07db76

commit 2dbd80866fee7ba40690d73b826e0252aa07db76
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Feb 7 22:21:14 2017 +0100

    Y2038: implement Y2038-proof mktime (and timelocal)
    
    API 'mktime' (aka 'timelocal') is implemented by function __mktime64.
    
    __mktime64 is designed similar to mktime, including checks on (64-bit)
    integer limits, and respects the same Posix requirements as __mktime does,
    i.e. calls tzset().
    
    Also, the implementation does not require a Y2038-proof kernel.

diff --git a/include/time.h b/include/time.h
index 09c92e5..f995a2a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -63,6 +63,15 @@ extern time_t __mktime_internal (struct tm *__tp,
 				 struct tm *(*__func) (const time_t *,
 						       struct tm *),
 				 time_t *__offset);
+
+/* Subroutine of `__mktime64'.  Return the `__time64_t' representation of TP and
+   normalize TP, given that a `struct tm *' maps to a `__time64_t' as performed
+   by FUNC.  Keep track of next guess for __time64_t offset in *OFFSET.  */
+extern __time64_t __mktime64_internal (struct tm *__tp,
+				 struct tm *(*__func) (const __time64_t *,
+						       struct tm *),
+				 __time64_t *__offset);
+
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index dd6a160..546d7c6 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -25,5 +25,6 @@ libc {
     __ctime64; __ctime64_r;
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
+    __mktime64; __timelocal64_r;
   }
 }
diff --git a/time/mktime.c b/time/mktime.c
index 4c48d35..3bd2631 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -599,6 +599,412 @@ weak_alias (mktime, timelocal)
 libc_hidden_def (mktime)
 libc_hidden_weak (timelocal)
 #endif
+
+/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
+   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
+   were not adjusted between the time stamps.
+
+   The YEAR values uses the same numbering as TP->tm_year.  Values
+   need not be in the usual range.  However, YEAR1 must not be less
+   than 2 * INT_MIN or greater than 2 * INT_MAX.
+
+   The result may overflow.  It is the caller's responsibility to
+   detect overflow.  */
+
+static __time64_t
+ydhms64_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
+	    int year0, int yday0, int hour0, int min0, int sec0)
+{
+  verify (C99_integer_division, -1 / 2 == 0);
+
+  /* Compute intervening leap days correctly even if year is negative.
+     Take care to avoid integer overflow here.  */
+  int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
+  int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+  int a100 = a4 / 25 - (a4 % 25 < 0);
+  int b100 = b4 / 25 - (b4 % 25 < 0);
+  int a400 = SHR (a100, 2);
+  int b400 = SHR (b100, 2);
+  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+
+  /* Compute the desired time in __time64_t precision.  Overflow might
+     occur here.  */
+  __time64_t tyear1 = year1;
+  __time64_t years = tyear1 - year0;
+  __time64_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+  __time64_t hours = 24 * days + hour1 - hour0;
+  __time64_t minutes = 60 * hours + min1 - min0;
+  __time64_t seconds = 60 * minutes + sec1 - sec0;
+  return seconds;
+}
+
+/* Return the average of A and B, even if A + B would overflow.  */
+static __time64_t
+time64_t_avg (__time64_t a, __time64_t b)
+{
+  return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
+}
+
+/* Return 1 if A + B does not overflow.  If __time64_t is unsigned and if
+   B's top bit is set, assume that the sum represents A - -B, and
+   return 1 if the subtraction does not wrap around.  */
+static int
+time64_t_add_ok (__time64_t a, __time64_t b)
+{
+  if (! TYPE_SIGNED (__time64_t))
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (TIME_T_MIDPOINT <= b);
+    }
+  else if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      __time64_t avg = time64_t_avg (a, b);
+      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+    }
+}
+
+/* Return 1 if A + B does not overflow.  */
+static int
+time64_t_int_add_ok (__time64_t a, int b)
+{
+  verify (int_no_wider_than_time64_t, INT_MAX <= TIME_T_MAX);
+  if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      int a_odd = a & 1;
+      __time64_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+    }
+}
+
+/* Return a __time64_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+   assuming that *T corresponds to *TP and that no clock adjustments
+   occurred between *TP and the desired time.
+   If TP is null, return a value not equal to *T; this avoids false matches.
+   If overflow occurs, yield the minimal or maximal value, except do not
+   yield a value equal to *T.  */
+static __time64_t
+guess_time64_tm (long_int year, long_int yday, int hour, int min, int sec,
+	       const __time64_t *t, const struct tm *tp)
+{
+  if (tp)
+    {
+      __time64_t d = ydhms64_diff (year, yday, hour, min, sec,
+			     tp->tm_year, tp->tm_yday,
+			     tp->tm_hour, tp->tm_min, tp->tm_sec);
+      if (time64_t_add_ok (*t, d))
+	return *t + d;
+    }
+
+  /* Overflow occurred one way or another.  Return the nearest result
+     that is actually in range, except don't report a zero difference
+     if the actual difference is nonzero, as that would cause a false
+     match; and don't oscillate between two values, as that would
+     confuse the spring-forward gap detector.  */
+  return (*t < TIME_T_MIDPOINT
+	  ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+	  : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+   If *T is out of range for conversion, adjust it so that
+   it is the nearest in-range value and then convert that.  */
+static struct tm *
+ranged64_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
+		__time64_t *t, struct tm *tp)
+{
+  struct tm *r = convert (t, tp);
+
+  if (!r && *t)
+    {
+      __time64_t bad = *t;
+      __time64_t ok = 0;
+
+      /* BAD is a known unconvertible __time64_t, and OK is a known good one.
+	 Use binary search to narrow the range between BAD and OK until
+	 they differ by 1.  */
+      while (bad != ok + (bad < 0 ? -1 : 1))
+	{
+	  __time64_t mid = *t = time64_t_avg (ok, bad);
+	  r = convert (t, tp);
+	  if (r)
+	    ok = mid;
+	  else
+	    bad = mid;
+	}
+
+      if (!r && ok)
+	{
+	  /* The last conversion attempt failed;
+	     revert to the most recent successful attempt.  */
+	  *t = ok;
+	  r = convert (t, tp);
+	}
+    }
+
+  return r;
+}
+
+
+/* Convert *TP to a __time64_t value, inverting
+   the monotonic and mostly-unit-linear conversion function CONVERT.
+   Use *OFFSET to keep track of a guess at the offset of the result,
+   compared to what the result would be for UTC without leap seconds.
+   If *OFFSET's guess is correct, only one CONVERT call is needed.
+   This function is external because it is used also by timegm.c.  */
+__time64_t
+__mktime64_internal (struct tm *tp,
+		   struct tm *(*convert) (const __time64_t *, struct tm *),
+		   __time64_t *offset)
+{
+  __time64_t t, gt, t0, t1, t2;
+  struct tm tm;
+
+  /* The maximum number of probes (calls to CONVERT) should be enough
+     to handle any combinations of time zone rule changes, solar time,
+     leap seconds, and oscillations around a spring-forward gap.
+     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
+  int remaining_probes = 6;
+
+  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
+     occur if TP is localtime's returned value and CONVERT is localtime.  */
+  int sec = tp->tm_sec;
+  int min = tp->tm_min;
+  int hour = tp->tm_hour;
+  int mday = tp->tm_mday;
+  int mon = tp->tm_mon;
+  int year_requested = tp->tm_year;
+  int isdst = tp->tm_isdst;
+
+  /* 1 if the previous probe was DST.  */
+  int dst2;
+
+  /* Ensure that mon is in range, and set year accordingly.  */
+  int mon_remainder = mon % 12;
+  int negative_mon_remainder = mon_remainder < 0;
+  int mon_years = mon / 12 - negative_mon_remainder;
+  long_int lyear_requested = year_requested;
+  long_int year = lyear_requested + mon_years;
+
+  /* The other values need not be in range:
+     the remaining code handles minor overflows correctly,
+     assuming int and __time64_t arithmetic wraps around.
+     Major overflows are caught at the end.  */
+
+  /* Calculate day of year from year, month, and day of month.
+     The result need not be in range.  */
+  int mon_yday = ((__mon_yday[leapyear (year)]
+		   [mon_remainder + 12 * negative_mon_remainder])
+		  - 1);
+  long_int lmday = mday;
+  long_int yday = mon_yday + lmday;
+
+  __time64_t guessed_offset = *offset;
+
+  int sec_requested = sec;
+
+  if (LEAP_SECONDS_POSSIBLE)
+    {
+      /* Handle out-of-range seconds specially,
+	 since ydhms_tm_diff assumes every minute has 60 seconds.  */
+      if (sec < 0)
+	sec = 0;
+      if (59 < sec)
+	sec = 59;
+    }
+
+  /* Invert CONVERT by probing.  First assume the same offset as last
+     time.  */
+
+  t0 = ydhms64_diff (year, yday, hour, min, sec,
+		   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
+
+  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+    {
+      /* __time64_t isn't large enough to rule out overflows, so check
+	 for major overflows.  A gross check suffices, since if t0
+	 has overflowed, it is off by a multiple of TIME_T_MAX -
+	 TIME_T_MIN + 1.  So ignore any component of the difference
+	 that is bounded by a small value.  */
+
+      /* Approximate log base 2 of the number of time units per
+	 biennium.  A biennium is 2 years; use this unit instead of
+	 years to avoid integer overflow.  For example, 2 average
+	 Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
+	 which is 63113904 seconds, and rint (log2 (63113904)) is
+	 26.  */
+      int ALOG2_SECONDS_PER_BIENNIUM = 26;
+      int ALOG2_MINUTES_PER_BIENNIUM = 20;
+      int ALOG2_HOURS_PER_BIENNIUM = 14;
+      int ALOG2_DAYS_PER_BIENNIUM = 10;
+      int LOG2_YEARS_PER_BIENNIUM = 1;
+
+      int approx_requested_biennia =
+	(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
+	 - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
+	 + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
+	 + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
+	 + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
+	 + (LEAP_SECONDS_POSSIBLE
+	    ? 0
+	    : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
+
+      int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
+      int diff = approx_biennia - approx_requested_biennia;
+      int approx_abs_diff = diff < 0 ? -1 - diff : diff;
+
+      /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
+	 gives a positive value of 715827882.  Setting a variable
+	 first then doing math on it seems to work.
+	 (ghazi@caip.rutgers.edu) */
+      __time64_t time64_t_max = TIME_T_MAX;
+      __time64_t time64_t_min = TIME_T_MIN;
+      __time64_t overflow_threshold =
+	(time64_t_max / 3 - time64_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
+
+      if (overflow_threshold < approx_abs_diff)
+	{
+	  /* Overflow occurred.  Try repairing it; this might work if
+	     the time zone offset is enough to undo the overflow.  */
+	  __time64_t repaired_t0 = -1 - t0;
+	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+	  diff = approx_biennia - approx_requested_biennia;
+	  approx_abs_diff = diff < 0 ? -1 - diff : diff;
+	  if (overflow_threshold < approx_abs_diff)
+	    return -1;
+	  guessed_offset += repaired_t0 - t0;
+	  t0 = repaired_t0;
+	}
+    }
+
+  /* Repeatedly use the error to improve the guess.  */
+
+  for (t = t1 = t2 = t0, dst2 = 0;
+       (gt = guess_time64_tm (year, yday, hour, min, sec, &t,
+			    ranged64_convert (convert, &t, &tm)),
+	t != gt);
+       t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+    if (t == t1 && t != t2
+	&& (tm.tm_isdst < 0
+	    || (isdst < 0
+		? dst2 <= (tm.tm_isdst != 0)
+		: (isdst != 0) != (tm.tm_isdst != 0))))
+      /* We can't possibly find a match, as we are oscillating
+	 between two values.  The requested time probably falls
+	 within a spring-forward gap of size GT - T.  Follow the common
+	 practice in this case, which is to return a time that is GT - T
+	 away from the requested time, preferring a time whose
+	 tm_isdst differs from the requested value.  (If no tm_isdst
+	 was requested and only one of the two values has a nonzero
+	 tm_isdst, prefer that value.)  In practice, this is more
+	 useful than returning -1.  */
+      goto offset_found;
+    else if (--remaining_probes == 0)
+      return -1;
+
+  /* We have a match.  Check whether tm.tm_isdst has the requested
+     value, if any.  */
+  if (isdst_differ (isdst, tm.tm_isdst))
+    {
+      /* tm.tm_isdst has the wrong value.  Look for a neighboring
+	 time with the right value, and use its UTC offset.
+
+	 Heuristic: probe the adjacent timestamps in both directions,
+	 looking for the desired isdst.  This should work for all real
+	 time zone histories in the tz database.  */
+
+      /* Distance between probes when looking for a DST boundary.  In
+	 tzdata2003a, the shortest period of DST is 601200 seconds
+	 (e.g., America/Recife starting 2000-10-08 01:00), and the
+	 shortest period of non-DST surrounded by DST is 694800
+	 seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
+	 minimum of these two values, so we don't miss these short
+	 periods when probing.  */
+      int stride = 601200;
+
+      /* The longest period of DST in tzdata2003a is 536454000 seconds
+	 (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
+	 period of non-DST is much longer, but it makes no real sense
+	 to search for more than a year of non-DST, so use the DST
+	 max.  */
+      int duration_max = 536454000;
+
+      /* Search in both directions, so the maximum distance is half
+	 the duration; add the stride to avoid off-by-1 problems.  */
+      int delta_bound = duration_max / 2 + stride;
+
+      int delta, direction;
+
+      for (delta = stride; delta < delta_bound; delta += stride)
+	for (direction = -1; direction <= 1; direction += 2)
+	  if (time64_t_int_add_ok (t, delta * direction))
+	    {
+	      __time64_t ot = t + delta * direction;
+	      struct tm otm;
+	      ranged64_convert (convert, &ot, &otm);
+	      if (! isdst_differ (isdst, otm.tm_isdst))
+		{
+		  /* We found the desired tm_isdst.
+		     Extrapolate back to the desired time.  */
+		  t = guess_time64_tm (year, yday, hour, min, sec, &ot, &otm);
+		  ranged64_convert (convert, &t, &tm);
+		  goto offset_found;
+		}
+	    }
+    }
+
+ offset_found:
+  *offset = guessed_offset + t - t0;
+
+  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
+    {
+      /* Adjust time to reflect the tm_sec requested, not the normalized value.
+	 Also, repair any damage from a false match due to a leap second.  */
+      int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
+      if (! time64_t_int_add_ok (t, sec_requested))
+	return -1;
+      t1 = t + sec_requested;
+      if (! time64_t_int_add_ok (t1, sec_adjustment))
+	return -1;
+      t2 = t1 + sec_adjustment;
+      if (! convert (&t2, &tm))
+	return -1;
+      t = t2;
+    }
+
+  *tp = tm;
+  return t;
+}
+
+
+/* FIXME: This should use a signed type wide enough to hold any UTC
+   offset in seconds.  'int' should be good enough for GNU code.  We
+   can't fix this unilaterally though, as other modules invoke
+   __mktime_internal.  */
+static __time64_t localtime64_offset;
+
+/* Convert *TP to a __time64_t value.  */
+__time64_t
+__mktime64 (struct tm *tp)
+{
+#ifdef _LIBC
+  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+     time zone names contained in the external variable 'tzname' shall
+     be set as if the tzset() function had been called.  */
+  __tzset ();
+#endif
+
+  return __mktime64_internal (tp, __localtime64_r, &localtime64_offset);
+}
 
 #if defined DEBUG_MKTIME && DEBUG_MKTIME
 
diff --git a/time/time.h b/time/time.h
index cd637bc..7260d28 100644
--- a/time/time.h
+++ b/time/time.h
@@ -88,9 +88,15 @@ extern double difftime (time_t __time1, time_t __time0)
      __THROW __attribute__ ((__const__));
 
 /* Return the `time_t' representation of TP and normalize TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (mktime, (struct tm *__tp), __mktime64) __THROW;
+# else
+# define mktime __mktime64
+# endif
+#endif
 extern time_t mktime (struct tm *__tp) __THROW;
 
-
 /* Format TP into S according to FORMAT.
    Write no more than MAXSIZE characters and return the number
    of characters written, or 0 if it would exceed MAXSIZE.  */
@@ -262,6 +268,13 @@ extern int stime (const time_t *__when) __THROW;
 extern time_t timegm (struct tm *__tp) __THROW;
 
 /* Another name for `mktime'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timelocal, (struct tm *__tp), __timelocal64) __THROW;
+# else
+# define timelocal __timelocal64
+# endif
+#endif
 extern time_t timelocal (struct tm *__tp) __THROW;
 
 /* Return the number of days in YEAR.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=33339d28593cfda506a46a0014592852219d1bce

commit 33339d28593cfda506a46a0014592852219d1bce
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Mar 29 12:01:45 2017 +0200

    Y2038: implement Y2038-proof 'struct tm' related APIs
    
    This consists in the following implementation additions:
    
    ([file] 32-bit implementation -> [file] 64-bit addition)
    
    time/ctime.c ctime() -> __ctime64()
    time/ctime_r.c ctime_r() -> __ctime64_r()
    time/gmtime.c gmtime() -> __gmtime64()
    time/gmtime.c gmtime_r() -> __gmtime64_r()
    time/localtime.c localtime() -> __localtime64()
    time/localtime.c localtime_r() -> __localtime64_r()
    
    which require the following internal function additions
    
    time/offtime.c __offtime() -> __offtime64()
    time/tzset.c __tz_convert() -> __tz64_convert()
    
    and internal function (32-bit-time-compatible) changes
    
    time/tzfile.c __tzfile_compute()
    time/tzset.c tzset_internal()
    time/tzset.c compute_change()

diff --git a/include/time.h b/include/time.h
index 684ceb8..09c92e5 100644
--- a/include/time.h
+++ b/include/time.h
@@ -10,6 +10,8 @@ extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
 extern __typeof (strptime_l) __strptime_l;
 
+extern struct tm *__localtime64 (const __time64_t *__timer);
+
 libc_hidden_proto (time)
 libc_hidden_proto (asctime)
 libc_hidden_proto (mktime)
@@ -45,13 +47,13 @@ extern int __use_tzfile attribute_hidden;
 
 extern void __tzfile_read (const char *file, size_t extra,
 			   char **extrap);
-extern void __tzfile_compute (time_t timer, int use_localtime,
+extern void __tzfile_compute (__time64_t timer, int use_localtime,
 			      long int *leap_correct, int *leap_hit,
 			      struct tm *tp);
 extern void __tzfile_default (const char *std, const char *dst,
 			      long int stdoff, long int dstoff);
 extern void __tzset_parse_tz (const char *tz);
-extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
      __THROW internal_function;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
@@ -64,15 +66,25 @@ extern time_t __mktime_internal (struct tm *__tp,
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
-extern struct tm *__gmtime_r (const time_t *__restrict __timer,
+extern struct tm *__localtime64_r (const __time64_t *__timer,
+				 struct tm *__tp) attribute_hidden;
+
+extern struct tm *__gmtime_r (const __time_t *__restrict __timer,
 			      struct tm *__restrict __tp);
 libc_hidden_proto (__gmtime_r)
 
+extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
+			      struct tm *__restrict __tp);
+
 /* 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.
    Return nonzero if successful.  */
-extern int __offtime (const time_t *__timer,
+extern int __offtime (const __time_t *__timer,
+		      long int __offset,
+		      struct tm *__tp);
+
+extern int __offtime64 (const __time64_t *__timer,
 		      long int __offset,
 		      struct tm *__tp);
 
@@ -80,7 +92,9 @@ extern char *__asctime_r (const struct tm *__tp, char *__buf);
 extern void __tzset (void);
 
 /* Prototype for the internal function to get information based on TZ.  */
-extern struct tm *__tz_convert (const time_t *timer, int use_localtime, struct tm *tp);
+extern struct tm *__tz_convert (const __time_t *timer, int use_localtime, struct tm *tp);
+
+extern struct tm *__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp);
 
 /* Return the maximum length of a timezone name.
    This is what `sysconf (_SC_TZNAME_MAX)' does.  */
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index d365576..dd6a160 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -22,5 +22,8 @@ libc {
 
   GLIBC_Y2038 {
     __difftime64;
+    __ctime64; __ctime64_r;
+    __gmtime64; __gmtime64_r;
+    __localtime64; __localtime64_r;
   }
 }
diff --git a/time/ctime.c b/time/ctime.c
index 7baca1b..a5150c1 100644
--- a/time/ctime.c
+++ b/time/ctime.c
@@ -26,3 +26,13 @@ ctime (const time_t *t)
      In particular, ctime and asctime must yield the same pointer.  */
   return asctime (localtime (t));
 }
+
+/* Return a string as returned by asctime which
+   is the representation of *T in that form.  */
+char *
+__ctime64 (const __time64_t *t)
+{
+  /* Apply the same rule as ctime:
+     make ctime64 (t) is equivalent to asctime (localtime64 (t)).  */
+  return asctime (__localtime64 (t));
+}
diff --git a/time/ctime_r.c b/time/ctime_r.c
index ecd7731..74d856f 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -27,3 +27,12 @@ ctime_r (const time_t *t, char *buf)
   struct tm tm;
   return __asctime_r (__localtime_r (t, &tm), buf);
 }
+
+/* Return a string as returned by asctime which is the representation
+   of *T in that form.  Reentrant Y2038-proof version.  */
+char *
+__ctime64_r (const __time64_t *t, char *buf)
+{
+  struct tm tm;
+  return __asctime_r (__localtime64_r (t, &tm), buf);
+}
diff --git a/time/gmtime.c b/time/gmtime.c
index 049d551..7662c1d 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -35,3 +35,18 @@ gmtime (const time_t *t)
 {
   return __tz_convert (t, 0, &_tmbuf);
 }
+
+/* Return the `struct tm' representation of 64-bit-time *T
+   in UTC, using *TP to store the result.  */
+struct tm *
+__gmtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert64 (t, 0, tp);
+}
+
+/* Return the `struct tm' representation of 64-bit-time *T in UTC.	*/
+struct tm *
+__gmtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 0, &_tmbuf);
+}
diff --git a/time/localtime.c b/time/localtime.c
index 07dd67c..fd2d997 100644
--- a/time/localtime.c
+++ b/time/localtime.c
@@ -39,3 +39,20 @@ localtime (const time_t *t)
   return __tz_convert (t, 1, &_tmbuf);
 }
 libc_hidden_def (localtime)
+
+/* 64-bit-time versions */
+
+/* Return the `struct tm' representation of *T in local time,
+   using *TP to store the result.  */
+struct tm *
+__localtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert64 (t, 1, tp);
+}
+
+/* Return the `struct tm' representation of *T in local time.  */
+struct tm *
+__localtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 1, &_tmbuf);
+}
diff --git a/time/offtime.c b/time/offtime.c
index 75a28fe..84237db 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -84,3 +84,67 @@ __offtime (const time_t *t, long int offset, struct tm *tp)
   tp->tm_mday = days + 1;
   return 1;
 }
+
+/* Compute the `struct tm' representation of 64-bit-time *T,
+   offset OFFSET seconds east of UTC,
+   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+   Return nonzero if successful.  */
+int
+__offtime64 (const __time64_t *t, long int offset, struct tm *tp)
+{
+  __time64_t days, rem, y;
+  const unsigned short int *ip;
+
+  days = *t / SECS_PER_DAY;
+  rem = *t % SECS_PER_DAY;
+  rem += offset;
+  while (rem < 0)
+    {
+      rem += SECS_PER_DAY;
+      --days;
+    }
+  while (rem >= SECS_PER_DAY)
+    {
+      rem -= SECS_PER_DAY;
+      ++days;
+    }
+  tp->tm_hour = rem / SECS_PER_HOUR;
+  rem %= SECS_PER_HOUR;
+  tp->tm_min = rem / 60;
+  tp->tm_sec = rem % 60;
+  /* January 1, 1970 was a Thursday.  */
+  tp->tm_wday = (4 + days) % 7;
+  if (tp->tm_wday < 0)
+    tp->tm_wday += 7;
+  y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+  while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+    {
+      /* Guess a corrected year, assuming 365 days per year.  */
+      __time64_t yg = y + days / 365 - (days % 365 < 0);
+
+      /* Adjust DAYS and Y to match the guessed year.  */
+      days -= ((yg - y) * 365
+	       + LEAPS_THRU_END_OF (yg - 1)
+	       - LEAPS_THRU_END_OF (y - 1));
+      y = yg;
+    }
+  tp->tm_year = y - 1900;
+  if (tp->tm_year != y - 1900)
+    {
+      /* The year cannot be represented due to overflow.  */
+      __set_errno (EOVERFLOW);
+      return 0;
+    }
+  tp->tm_yday = days;
+  ip = __mon_yday[__isleap(y)];
+  for (y = 11; days < (long int) ip[y]; --y)
+    continue;
+  days -= ip[y];
+  tp->tm_mon = y;
+  tp->tm_mday = days + 1;
+  return 1;
+}
diff --git a/time/time.h b/time/time.h
index 0fb1416..cd637bc 100644
--- a/time/time.h
+++ b/time/time.h
@@ -125,34 +125,78 @@ extern char *strptime_l (const char *__restrict __s,
 
 
 __BEGIN_NAMESPACE_STD
+
 /* Return the `struct tm' representation of *TIMER
    in Universal Coordinated Time (aka Greenwich Mean Time).  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime, (const time_t *__timer),
+       __gmtime64) __THROW;
+# else
+# define gmtime __gmtime64
+# endif
+#endif
 extern struct tm *gmtime (const time_t *__timer) __THROW;
 
 /* Return the `struct tm' representation
    of *TIMER in the local timezone.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime, (const time_t *__timer),
+       __localtime64) __THROW;
+# else
+# define localtime __localtime64
+# endif
+#endif
 extern struct tm *localtime (const time_t *__timer) __THROW;
+
 __END_NAMESPACE_STD
 
 #ifdef __USE_POSIX
 /* Return the `struct tm' representation of *TIMER in UTC,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __gmtime64_r) __THROW;
+# else
+# define gmtime_r __gmtime64_r
+# endif
+#endif
 extern struct tm *gmtime_r (const time_t *__restrict __timer,
 			    struct tm *__restrict __tp) __THROW;
 
 /* Return the `struct tm' representation of *TIMER in local time,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __localtime64_r) __THROW;
+# else
+# define localtime_r __localtime64_r
+# endif
+#endif
 extern struct tm *localtime_r (const time_t *__restrict __timer,
 			       struct tm *__restrict __tp) __THROW;
 #endif	/* POSIX */
 
 __BEGIN_NAMESPACE_STD
+
 /* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n"
    that is the representation of TP in this format.  */
 extern char *asctime (const struct tm *__tp) __THROW;
 
 /* Equivalent to `asctime (localtime (timer))'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime, (const time_t *__timer),
+       __ctime64) __THROW;
+# else
+# define ctime __ctime64
+# endif
+#endif
 extern char *ctime (const time_t *__timer) __THROW;
+
 __END_NAMESPACE_STD
 
 #ifdef __USE_POSIX
@@ -164,6 +208,14 @@ extern char *asctime_r (const struct tm *__restrict __tp,
 			char *__restrict __buf) __THROW;
 
 /* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime_r, (const time_t *__restrict __timer,
+       char *__restrict __buf), __ctime64_r) __THROW;
+# else
+# define ctime_r __ctime64_r
+# endif
+#endif
 extern char *ctime_r (const time_t *__restrict __timer,
 		      char *__restrict __buf) __THROW;
 #endif	/* POSIX */
diff --git a/time/tzfile.c b/time/tzfile.c
index 3fd4569..9d1a0f6 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -637,7 +637,7 @@ __tzfile_default (const char *std, const char *dst,
 }
 
 void
-__tzfile_compute (time_t timer, int use_localtime,
+__tzfile_compute (__time64_t timer, int use_localtime,
 		  long int *leap_correct, int *leap_hit,
 		  struct tm *tp)
 {
@@ -692,7 +692,7 @@ __tzfile_compute (time_t timer, int use_localtime,
 
 	  /* Convert to broken down structure.  If this fails do not
 	     use the string.  */
-	  if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
+	  if (__glibc_unlikely (! __offtime64 (&timer, 0, tp)))
 	    goto use_last;
 
 	  /* Use the rules from the TZ string to compute the change.  */
diff --git a/time/tzset.c b/time/tzset.c
index eb42069..cd9df8f 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -61,7 +61,7 @@ typedef struct
 
     /* We cache the computed time of change for a
        given year so we don't have to recompute it.  */
-    time_t change;	/* When to change to this zone.  */
+    __time64_t change;	/* When to change to this zone.  */
     int computed_for;	/* Year above is computed for.  */
   } tz_rule;
 
@@ -451,7 +451,7 @@ tzset_internal (int always, int explicit)
       tz_rules[0].name = tz_rules[1].name = "UTC";
       if (J0 != 0)
 	tz_rules[0].type = tz_rules[1].type = J0;
-      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+      tz_rules[0].change = tz_rules[1].change = (__time64_t) -1;
       update_vars ();
       return;
     }
@@ -550,10 +550,11 @@ compute_change (tz_rule *rule, int year)
 
 
 /* Figure out the correct timezone for TM and set `__tzname',
-   `__timezone', and `__daylight' accordingly.  */
+   `__timezone', and `__daylight' accordingly.
+   NOTE: this takes a __time64_t value, so passing a __time_t value is OK. */
 void
 internal_function
-__tz_compute (time_t timer, struct tm *tm, int use_localtime)
+__tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
 {
   compute_change (&tz_rules[0], 1900 + tm->tm_year);
   compute_change (&tz_rules[1], 1900 + tm->tm_year);
@@ -654,6 +655,61 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
 }
 
 
+/* Return the `struct tm' representation of *TIMER in the local timezone.
+   Use local time if USE_LOCALTIME is nonzero, UTC otherwise.  */
+struct tm *
+__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp)
+{
+  long int leap_correction;
+  int leap_extra_secs;
+
+  if (timer == NULL)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  __libc_lock_lock (tzset_lock);
+
+  /* Update internal database according to current TZ setting.
+     POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
+     This is a good idea since this allows at least a bit more parallelism.  */
+  tzset_internal (tp == &_tmbuf && use_localtime, 1);
+
+  if (__use_tzfile)
+    __tzfile_compute (*timer, use_localtime, &leap_correction,
+		      &leap_extra_secs, tp);
+  else
+    {
+      if (! __offtime64 (timer, 0, tp))
+	tp = NULL;
+      else
+	__tz_compute (*timer, tp, use_localtime);
+      leap_correction = 0L;
+      leap_extra_secs = 0;
+    }
+
+  __libc_lock_unlock (tzset_lock);
+
+  if (tp)
+    {
+      if (! use_localtime)
+	{
+	  tp->tm_isdst = 0;
+	  tp->tm_zone = "GMT";
+	  tp->tm_gmtoff = 0L;
+	}
+
+      if (__offtime64 (timer, tp->tm_gmtoff - leap_correction, tp))
+        tp->tm_sec += leap_extra_secs;
+      else
+	tp = NULL;
+    }
+
+  return tp;
+}
+
+
 libc_freeres_fn (free_mem)
 {
   while (tzstring_list != NULL)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=692e945b3717b494daeebcd2d0eeba1cdd66f6a1

commit 692e945b3717b494daeebcd2d0eeba1cdd66f6a1
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Mar 29 11:57:53 2017 +0200

    Y2038: implement Y2038-proof difftime
    
    With -D_TIME_BITS=64, the 'difftime' API is implemented by
    function '__difftime64'.
    
    The API expects __time64_t arguments but returns a double like its
    32-bit-time counterpart, in order to remain as source-code-compatible
    as possible, even though the precision of a a double is only about 55
    bits.
    
    The implementation is simpler than its 32-bit counterpart, as it
    assumes that all __time64_t implementations are just 64-bit integers.
    
    Also, the implementation does not require a Y2038-proof kernel.

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 7e5ba53..d365576 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -16,4 +16,11 @@ libc {
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __difftime64;
+  }
 }
diff --git a/time/difftime.c b/time/difftime.c
index e5e3311..1b2494c 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -119,3 +119,12 @@ __difftime (time_t time1, time_t time0)
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
 strong_alias (__difftime, difftime)
+
+/* Return the difference between 64-bit TIME1 and TIME0.  */
+double
+__difftime64 (__time64_t time1, __time64_t time0)
+{
+  /* Subtract the smaller integer from the larger, convert the difference to
+     double, and then negate if needed.  */
+  return time1 < time0 ? - (time0 - time1) : (time1 - time0);
+}
diff --git a/time/time.h b/time/time.h
index 7f98338..0fb1416 100644
--- a/time/time.h
+++ b/time/time.h
@@ -76,6 +76,14 @@ extern clock_t clock (void) __THROW;
 extern time_t time (time_t *__timer) __THROW;
 
 /* Return the difference between TIME1 and TIME0.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern double __REDIRECT (difftime, (time_t __time1, time_t __time0),
+     __difftime64) __THROW;
+# else
+# define difftime __difftime64
+# endif
+#endif
 extern double difftime (time_t __time1, time_t __time0)
      __THROW __attribute__ ((__const__));
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=46e006383ba874cd38764a23cff55b9a3a7d4db8

commit 46e006383ba874cd38764a23cff55b9a3a7d4db8
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Feb 15 19:25:27 2017 +0100

    Y2038: make time_t Y2038-proof
    
    API type __time64_t is introduced as a 64-bit signed integer.
    
    Then, if _USE_TIME_BITS64 is defined, time_t is defined as __time64_t;
    otherwise, time_t is defined as __time_t.
    
    This allows the same user source code to use the same 'time_t' type
    and thus work with 32-bit time (default case) or with 64-bit time
    (-D_TIME_BITS=64) without any source-level change.
    
    ** NOTE **
    
    1.
    
    __USE_TIME_BITS64 is defined when _TIME_BITS is defined equal to 64.
    
    2.
    
    Defining _TIME_BITS=64 affects *all* API types derived from time_t,
    e.g. struct timeval, struct timespec etc: all time_t fields are now
    64-bit. This, in turn, means that most APIs are now inconsistent with
    their respective implementations. The rest of this series is about
    providing adequate 64-bit-time implementations.

diff --git a/bits/types.h b/bits/types.h
index 7638bd0..f5b2d42 100644
--- a/bits/types.h
+++ b/bits/types.h
@@ -145,7 +145,8 @@ __STD_TYPE __CLOCK_T_TYPE __clock_t;	/* Type of CPU usage counts.  */
 __STD_TYPE __RLIM_T_TYPE __rlim_t;	/* Type for resource measurement.  */
 __STD_TYPE __RLIM64_T_TYPE __rlim64_t;	/* Type for resource measurement (LFS).  */
 __STD_TYPE __ID_T_TYPE __id_t;		/* General type for IDs.  */
-__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
+__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */
+__STD_TYPE __TIME64_T_TYPE __time64_t;	/* Seconds since the Epoch, Y2038-safe.  */
 __STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds.  */
 __STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds.  */
 
diff --git a/bits/typesizes.h b/bits/typesizes.h
index d407bf4..a916cc1 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -48,6 +48,7 @@
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/include/features.h b/include/features.h
index dc8ae79..cef60ac 100644
--- a/include/features.h
+++ b/include/features.h
@@ -356,6 +356,10 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+#if defined _TIME_BITS && _TIME_BITS == 64
+# define __USE_TIME_BITS64	1
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index 16e5269..47ad649 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -5,7 +5,11 @@
 
 __BEGIN_NAMESPACE_STD
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 __END_NAMESPACE_STD
 #ifdef __USE_POSIX
 __USING_NAMESPACE_STD(time_t)

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]