[v4,2/3] 32-bit ABIs: support stat syscall family

Message ID 1470304959-9944-3-git-send-email-ynorov@caviumnetworks.com
State New
Headers show
Series
  • Untitled series #1898
Related show

Commit Message

Yury Norov Aug. 4, 2016, 10:02 a.m.
In modern APIs stat and statfs structures has their layouts identical
to 64-bit version after changing off_t, ino_t etc sizes to 64-bit.
It means we can pass it to kernel same way as 64-bit ABI does.

In this patch:
 - __ASSUME_SUPPORT_64_BIT_TIME_TYPES macro introduced to indicate that 32-bit
   ABI has struct __timespec (and maybe __timeval in future) that is compatible
   to 64-bit kernel timespec;
 - conv_timespec() and stat_conv_timespecs() macros are introduced to convert
   kernel 64-bit timespec to 32-bit timespec;
 - XSTAT_IS_XSTAT64 is reused in 32-bit code to hint GLIBC that structures  stat
   and statfs are identical to 64-bit versions, and 64-bit syscalls should be used
   for corresponding requests.
 - 32-bit syscalls are redirected to 64-bit version.

Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>

---
 sysdeps/unix/sysv/linux/fstatfs64.c                |  7 ++++
 sysdeps/unix/sysv/linux/fxstat64.c                 | 11 +++++
 sysdeps/unix/sysv/linux/fxstatat64.c               | 15 ++++++-
 sysdeps/unix/sysv/linux/generic/bits/stat.h        | 49 ++++++++++++++++++----
 sysdeps/unix/sysv/linux/generic/bits/statfs.h      | 32 ++++++++------
 .../unix/sysv/linux/generic/wordsize-32/fstatfs.c  |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/fxstat.c   |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/fxstatat.c |  2 +
 .../unix/sysv/linux/generic/wordsize-32/lxstat.c   |  2 +
 .../unix/sysv/linux/generic/wordsize-32/lxstat64.c | 20 ++++++++-
 .../unix/sysv/linux/generic/wordsize-32/statfs.c   |  2 +
 .../unix/sysv/linux/generic/wordsize-32/xstat.c    |  2 +
 .../unix/sysv/linux/generic/wordsize-32/xstat64.c  | 16 ++++++-
 sysdeps/unix/sysv/linux/kernel-time.h              | 45 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/statfs64.c                 |  8 ++++
 time/time.h                                        | 12 +++++-
 16 files changed, 204 insertions(+), 25 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/kernel-time.h

-- 
2.7.4

Patch

diff --git a/sysdeps/unix/sysv/linux/fstatfs64.c b/sysdeps/unix/sysv/linux/fstatfs64.c
index a624de6..e0297c4 100644
--- a/sysdeps/unix/sysv/linux/fstatfs64.c
+++ b/sysdeps/unix/sysv/linux/fstatfs64.c
@@ -15,6 +15,8 @@ 
    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/>.  */
+#define __fstatfs __statfs_disable
+#define fstatfs statfs_disable
 
 #include <errno.h>
 #include <string.h>
@@ -70,3 +72,8 @@  __fstatfs64 (int fd, struct statfs64 *buf)
 #endif
 }
 weak_alias (__fstatfs64, fstatfs64)
+
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__fstatfs64, __fstatfs)
+weak_alias (__fstatfs64, fstatfs)
+#endif
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 5468dd6..0a65fa2 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -15,6 +15,7 @@ 
    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/>.  */
+#define __fxstat __fxstat_disable
 
 #include <errno.h>
 #include <stddef.h>
@@ -25,6 +26,7 @@ 
 #include <sys/syscall.h>
 
 #include <kernel-features.h>
+#include <kernel-time.h>
 
 /* Get information about the file FD in BUF.  */
 
@@ -36,12 +38,16 @@  ___fxstat64 (int vers, int fd, struct stat64 *buf)
 #if defined _HAVE_STAT64___ST_INO && !defined __ASSUME_ST_INO_64_BIT
   if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino)
     buf->st_ino = buf->__st_ino;
+  return result;
 #endif
+  if (!result)
+    stat_conv_timespecs (buf);
   return result;
 }
 
 #include <shlib-compat.h>
 
+#undef __fxstat
 #if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
 versioned_symbol (libc, ___fxstat64, __fxstat64, GLIBC_2_2);
 strong_alias (___fxstat64, __old__fxstat64)
@@ -51,3 +57,8 @@  hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__fxstat64, __fxstat)
+libc_hidden_ver (__fxstat64, __fxstat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index 7ffa2d4..0346d7c 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -14,6 +14,7 @@ 
    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/>.  */
+#define __fxstatat __fxstatat_disable
 
 #include <errno.h>
 #include <fcntl.h>
@@ -26,6 +27,8 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <kernel-time.h>
+
 /* Get information about the file NAME in BUF.  */
 
 int
@@ -39,9 +42,19 @@  __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 
   result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag);
   if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
-    return 0;
+    {
+      stat_conv_timespecs (st);
+      return 0;
+    }
   else
     return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
 								      err));
 }
 libc_hidden_def (__fxstatat64)
+
+#undef __fxstatat
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__fxstatat64, __fxstatat)
+libc_hidden_ver (__fxstatat64, __fxstatat)
+#endif
+
diff --git a/sysdeps/unix/sysv/linux/generic/bits/stat.h b/sysdeps/unix/sysv/linux/generic/bits/stat.h
index 8e3f745..85e9866 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/stat.h
@@ -41,7 +41,7 @@ 
 /* Versions of the `xmknod' interface.  */
 #define _MKNOD_VER_LINUX	0
 
-#if defined __USE_FILE_OFFSET64
+#if defined (__USE_FILE_OFFSET64) || defined (XSTAT_IS_XSTAT64)
 # define __field64(type, type64, name) type64 name
 #else
 # define __field64(type, type64, name) __type3264 (type, name)
@@ -68,19 +68,37 @@  struct stat
        identifier 'timespec' to appear in the <sys/stat.h> header.
        Therefore we have to handle the use of this header in strictly
        standard-compliant sources special.  */
-    struct timespec st_atim;		/* Time of last access.  */
-    struct timespec st_mtim;		/* Time of last modification.  */
-    struct timespec st_ctim;		/* Time of last status change.  */
+
+# if SUPPORT_64BIT_TIME_TYPES
+    __type3264 (struct timespec, st_atim);		/* Time of last access.  */
+    __type3264 (struct timespec, st_mtim);		/* Time of last modification.  */
+    __type3264 (struct timespec, st_ctim);		/* Time of last status change.  */
+# else
+    struct timespec st_atim;				/* Time of last access.  */
+    struct timespec st_mtim;				/* Time of last modification.  */
+    struct timespec st_ctim;				/* Time of last status change.  */
+# endif
+
 # define st_atime st_atim.tv_sec	/* Backward compatibility.  */
 # define st_mtime st_mtim.tv_sec
 # define st_ctime st_ctim.tv_sec
+
 #else
+# if SUPPORT_64BIT_TIME_TYPES
+    __type3264 (__time_t, st_atime);			/* Time of last access.  */
+    __type3264 (unsigned long int, st_atimensec);	/* Nscecs of last access.  */
+    __type3264 (__time_t, st_mtime);			/* Time of last modification.  */
+    __type3264 (unsigned long int, st_mtimensec);	/* Nsecs of last modification.  */
+    __type3264 (__time_t, st_ctime);			/* Time of last status change.  */
+    __type3264 (unsigned long int, st_ctimensec);	/* Nsecs of last status change.  */
+# else
     __time_t st_atime;			/* Time of last access.  */
     unsigned long int st_atimensec;	/* Nscecs of last access.  */
     __time_t st_mtime;			/* Time of last modification.  */
     unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
     __time_t st_ctime;			/* Time of last status change.  */
     unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
+# endif
 #endif
     int __glibc_reserved[2];
   };
@@ -109,16 +127,33 @@  struct stat64
        identifier 'timespec' to appear in the <sys/stat.h> header.
        Therefore we have to handle the use of this header in strictly
        standard-compliant sources special.  */
-    struct timespec st_atim;		/* Time of last access.  */
-    struct timespec st_mtim;		/* Time of last modification.  */
-    struct timespec st_ctim;		/* Time of last status change.  */
+
+# if SUPPORT_64BIT_TIME_TYPES
+    __type3264 (struct timespec, st_atim);		/* Time of last access.  */
+    __type3264 (struct timespec, st_mtim);		/* Time of last modification.  */
+    __type3264 (struct timespec, st_ctim);		/* Time of last status change.  */
+# else
+    struct timespec st_atim;				/* Time of last access.  */
+    struct timespec st_mtim;				/* Time of last modification.  */
+    struct timespec st_ctim;				/* Time of last status change.  */
+# endif
+
 #else
+# if SUPPORT_64BIT_TIME_TYPES
+    __type3264 (__time_t, st_atime);			/* Time of last access.  */
+    __type3264 (unsigned long int, st_atimensec);	/* Nscecs of last access.  */
+    __type3264 (__time_t, st_mtime);			/* Time of last modification.  */
+    __type3264 (unsigned long int, st_mtimensec);	/* Nsecs of last modification.  */
+    __type3264 (__time_t, st_ctime);			/* Time of last status change.  */
+    __type3264 (unsigned long int, st_ctimensec);	/* Nsecs of last status change.  */
+# else
     __time_t st_atime;			/* Time of last access.  */
     unsigned long int st_atimensec;	/* Nscecs of last access.  */
     __time_t st_mtime;			/* Time of last modification.  */
     unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
     __time_t st_ctime;			/* Time of last status change.  */
     unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
+# endif
 #endif
     int __glibc_reserved[2];
   };
diff --git a/sysdeps/unix/sysv/linux/generic/bits/statfs.h b/sysdeps/unix/sysv/linux/generic/bits/statfs.h
index 96629ac..0245c73 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/statfs.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/statfs.h
@@ -32,26 +32,32 @@ 
    using __USE_FILE_OFFSET64 only see the low 32 bits of some
    of the fields (the __fsblkcnt_t and __fsfilcnt_t fields).  */
 
-#if defined __USE_FILE_OFFSET64
+#if defined (__USE_FILE_OFFSET64) || defined (XSTAT_IS_XSTAT64)
 # define __field64(type, type64, name) type64 name
 #else
 # define __field64(type, type64, name) __type3264 (type, name)
 #endif
 
+#ifdef XSTAT_IS_XSTAT64
+# define __statfs_word_t long long
+#else
+# define __statfs_word_t __SWORD_TYPE
+#endif
+
 struct statfs
   {
-    __SWORD_TYPE f_type;
-    __SWORD_TYPE f_bsize;
+    __statfs_word_t f_type;
+    __statfs_word_t f_bsize;
     __field64(__fsblkcnt_t, __fsblkcnt64_t, f_blocks);
     __field64(__fsblkcnt_t, __fsblkcnt64_t, f_bfree);
     __field64(__fsblkcnt_t, __fsblkcnt64_t, f_bavail);
     __field64(__fsfilcnt_t, __fsfilcnt64_t, f_files);
     __field64(__fsfilcnt_t, __fsfilcnt64_t, f_ffree);
     __fsid_t f_fsid;
-    __SWORD_TYPE f_namelen;
-    __SWORD_TYPE f_frsize;
-    __SWORD_TYPE f_flags;
-    __SWORD_TYPE f_spare[4];
+    __statfs_word_t f_namelen;
+    __statfs_word_t f_frsize;
+    __statfs_word_t f_flags;
+    __statfs_word_t f_spare[4];
   };
 
 #undef __field64
@@ -59,18 +65,18 @@  struct statfs
 #ifdef __USE_LARGEFILE64
 struct statfs64
   {
-    __SWORD_TYPE f_type;
-    __SWORD_TYPE f_bsize;
+    __statfs_word_t f_type;
+    __statfs_word_t f_bsize;
     __fsblkcnt64_t f_blocks;
     __fsblkcnt64_t f_bfree;
     __fsblkcnt64_t f_bavail;
     __fsfilcnt64_t f_files;
     __fsfilcnt64_t f_ffree;
     __fsid_t f_fsid;
-    __SWORD_TYPE f_namelen;
-    __SWORD_TYPE f_frsize;
-    __SWORD_TYPE f_flags;
-    __SWORD_TYPE f_spare[4];
+    __statfs_word_t f_namelen;
+    __statfs_word_t f_frsize;
+    __statfs_word_t f_flags;
+    __statfs_word_t f_spare[4];
   };
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fstatfs.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fstatfs.c
index be9599a..9f20377 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fstatfs.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fstatfs.c
@@ -20,6 +20,8 @@ 
 #include <sys/statfs.h>
 #include <stddef.h>
 
+#ifndef XSTAT_IS_XSTAT64
+
 #include "overflow.h"
 
 /* Return information about the filesystem on which FD resides.  */
@@ -30,3 +32,4 @@  __fstatfs (int fd, struct statfs *buf)
   return rc ?: statfs_overflow (buf);
 }
 weak_alias (__fstatfs, fstatfs)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
index dd52011..b246f5d 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c
@@ -25,6 +25,7 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#ifndef XSTAT_IS_XSTAT64
 #include "overflow.h"
 
 /* Get information about the file FD in BUF.  */
@@ -43,3 +44,5 @@  __fxstat (int vers, int fd, struct stat *buf)
 
 hidden_def (__fxstat)
 weak_alias (__fxstat, _fxstat);
+#endif
+
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
index dc7f934..b00f65d 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c
@@ -26,6 +26,7 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#ifndef XSTAT_IS_XSTAT64
 #include "overflow.h"
 
 /* Get information about the file NAME in BUF.  */
@@ -42,3 +43,4 @@  __fxstatat (int vers, int fd, const char *file, struct stat *buf, int flag)
   return -1;
 }
 libc_hidden_def (__fxstatat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
index 395f98b..4fec6c9 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c
@@ -25,6 +25,7 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#ifndef XSTAT_IS_XSTAT64
 #include "overflow.h"
 
 /* Get information about the file NAME in BUF.  */
@@ -41,3 +42,4 @@  __lxstat (int vers, const char *name, struct stat *buf)
   return -1;
 }
 hidden_def (__lxstat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c
index e1c15a8..9dc06c9 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c
@@ -15,6 +15,7 @@ 
    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/>.  */
+#define __lxstat __lxstat_disable
 
 #include <errno.h>
 #include <stddef.h>
@@ -25,14 +26,29 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <kernel-time.h>
+
 /* Get information about the file NAME in BUF.  */
 int
 __lxstat64 (int vers, const char *name, struct stat64 *buf)
 {
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf,
-                           AT_SYMLINK_NOFOLLOW);
+    {
+      int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf,
+			       AT_SYMLINK_NOFOLLOW);
+      if (!rc)
+	stat_conv_timespecs (buf);
+
+      return rc;
+    }
+
   errno = EINVAL;
   return -1;
 }
 hidden_def (__lxstat64)
+
+#undef __lxstat
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__lxstat64, __lxstat)
+hidden_ver (__lxstat64, __lxstat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/statfs.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/statfs.c
index 1937f05..1a09f60 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/statfs.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/statfs.c
@@ -20,6 +20,7 @@ 
 #include <sys/statfs.h>
 #include <stddef.h>
 
+#ifndef XSTAT_IS_XSTAT64
 #include "overflow.h"
 
 /* Return information about the filesystem on which FILE resides.  */
@@ -31,3 +32,4 @@  __statfs (const char *file, struct statfs *buf)
 }
 libc_hidden_def (__statfs)
 weak_alias (__statfs, statfs)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
index fdd2cb0..8fc13bd 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c
@@ -25,6 +25,7 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#ifndef XSTAT_IS_XSTAT64
 #include "overflow.h"
 
 /* Get information about the file NAME in BUF.  */
@@ -41,3 +42,4 @@  __xstat (int vers, const char *name, struct stat *buf)
   return -1;
 }
 hidden_def (__xstat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c
index 2252337..f8d15e5 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c
@@ -15,6 +15,7 @@ 
    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/>.  */
+#define __xstat __xstat_disable
 
 #include <errno.h>
 #include <stddef.h>
@@ -25,14 +26,27 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <kernel-time.h>
+
 /* Get information about the file NAME in BUF.  */
 int
 __xstat64 (int vers, const char *name, struct stat64 *buf)
 {
   if (vers == _STAT_VER_KERNEL)
-    return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0);
+    {
+      int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0);
+      if (!rc)
+	stat_conv_timespecs (buf);
+      return rc;
+    }
 
   errno = EINVAL;
   return -1;
 }
 hidden_def (__xstat64)
+
+#undef __xstat
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__xstat64, __xstat)
+hidden_ver (__xstat64, __xstat)
+#endif
diff --git a/sysdeps/unix/sysv/linux/kernel-time.h b/sysdeps/unix/sysv/linux/kernel-time.h
new file mode 100644
index 0000000..ba14cf5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/kernel-time.h
@@ -0,0 +1,45 @@ 
+/* Helpers to convert kernel time structures to user-visible ones.
+
+   Copyright (C) 1991-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/>.  */
+
+#if SUPPORT_64BIT_TIME_TYPES
+struct __timespec {
+  long long tv_sec;
+  long long tv_nsec;
+};
+
+# define conv_timespec(ts)					\
+  do								\
+    {								\
+      struct __timespec  *__ts = (void *) (ts);			\
+      (ts)->tv_sec = __ts->tv_sec;				\
+      (ts)->tv_nsec = __ts->tv_nsec;				\
+    }								\
+  while (0)
+# define stat_conv_timespecs(__stat)				\
+  do								\
+    {								\
+      conv_timespec (&(__stat)->st_atim);			\
+      conv_timespec (&(__stat)->st_mtim);			\
+      conv_timespec (&(__stat)->st_ctim);			\
+    }								\
+  while (0)
+#else
+# define conv_timespec(ts, _ts)		do {} while (0)
+# define stat_conv_timespecs(__stat)	do {} while (0)
+#endif
diff --git a/sysdeps/unix/sysv/linux/statfs64.c b/sysdeps/unix/sysv/linux/statfs64.c
index de42261..2ab2fb1 100644
--- a/sysdeps/unix/sysv/linux/statfs64.c
+++ b/sysdeps/unix/sysv/linux/statfs64.c
@@ -15,6 +15,8 @@ 
    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/>.  */
+#define __statfs __statfs_disable
+#define statfs statfs_disable
 
 #include <errno.h>
 #include <string.h>
@@ -72,3 +74,9 @@  __statfs64 (const char *file, struct statfs64 *buf)
 #endif
 }
 weak_alias (__statfs64, statfs64)
+
+#ifdef XSTAT_IS_XSTAT64
+strong_alias (__statfs64, __statfs)
+libc_hidden_ver (__statfs64, __statfs)
+weak_alias (__statfs64, statfs)
+#endif
diff --git a/time/time.h b/time/time.h
index cc93917..8b4cced 100644
--- a/time/time.h
+++ b/time/time.h
@@ -65,6 +65,17 @@  __USING_NAMESPACE_STD(clock_t)
 #endif /* clock_t not defined and <time.h> or need clock_t.  */
 #undef	__need_clock_t
 
+#ifndef SUPPORT_64BIT_TIME_TYPES
+# ifdef __ASSUME_SUPPORT_64_BIT_TIME_TYPES
+#  if __WORDSIZE != 32
+#   error "__ASSUME_SUPPORT_64_BIT_TIME_TYPES is 32-bit only option"
+#  endif
+#  define SUPPORT_64BIT_TIME_TYPES	1
+# else
+#  define SUPPORT_64BIT_TIME_TYPES	0
+# endif
+#endif
+
 #if !defined __time_t_defined && (defined _TIME_H || defined __need_time_t)
 # define __time_t_defined	1
 
@@ -105,7 +116,6 @@  typedef __timer_t timer_t;
 #endif /* timer_t not defined and <time.h> or need timer_t.  */
 #undef	__need_timer_t
 
-
 #if (!defined __timespec_defined					\
      && ((defined _TIME_H						\
 	  && (defined __USE_POSIX199309					\