This is the mail archive of the libc-alpha@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]

[RFC2 RESEND PATCH] [AARCH64] ILP32: support stat syscall family


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 lp64 API does.

Initial version of this patch did introduce full set of stat{,fs} headers
and function implementation under aarch64/ilp32 directory. It was rejected
by Joseph, and he requested to extend and re-use existing files where
possible.

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
   __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 requesta.
 - 32-bit syscalls are redirected to 64-bit version.

After all, aarch63/ilp32 contains only 2 syscall filess - fstatfs() and statfs()
that we cannot redirect to generic ones because aarch64 kernel expects arguments
in different registers.

It was tested with LTP, and no regressions found.

The series that includes this patch:
https://github.com/norov/glibc/tree/ilp32-dev

v2:
 - STATFS_IS_STATFS64 removed. Both stat and statfs structures are controlled by
   XSTAT_IS_XSTAT64. I did it because they will doubtly differ with it.
 - fixed coding style numerous issues.
 - conv_timespec() moved to non-imported header. stat_conv_timespecs() is introduced.
 - I didn't move DECLARE_TIMESPEC() to non-installed file because it's used in stat.h,
   and should be known on used side. If it's wrong please hint me how to do this trick.

Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
---
 string/endian.h                                    | 13 +++++++
 sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h   |  6 ++++
 sysdeps/unix/sysv/linux/aarch64/ilp32/fstatfs64.c  | 36 +++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/ilp32/statfs64.c   | 39 +++++++++++++++++++++
 sysdeps/unix/sysv/linux/fxstat64.c                 | 12 +++++++
 sysdeps/unix/sysv/linux/fxstatat64.c               | 15 +++++++-
 sysdeps/unix/sysv/linux/generic/bits/stat.h        | 35 +++++++++++++++----
 sysdeps/unix/sysv/linux/generic/bits/statfs.h      | 32 ++++++++++-------
 .../unix/sysv/linux/generic/wordsize-32/fstatfs.c  |  4 +++
 .../unix/sysv/linux/generic/wordsize-32/fxstat.c   |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/fxstatat.c |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/lxstat.c   |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/lxstat64.c | 21 ++++++++++--
 .../unix/sysv/linux/generic/wordsize-32/statfs.c   |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/xstat.c    |  3 ++
 .../unix/sysv/linux/generic/wordsize-32/xstat64.c  | 17 ++++++++-
 sysdeps/unix/sysv/linux/kernel-time.h              | 40 ++++++++++++++++++++++
 time/time.h                                        | 30 +++++++++++++++-
 18 files changed, 290 insertions(+), 25 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/ilp32/fstatfs64.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/ilp32/statfs64.c
 create mode 100644 sysdeps/unix/sysv/linux/kernel-time.h

diff --git a/string/endian.h b/string/endian.h
index b13ddaa..f021f04 100644
--- a/string/endian.h
+++ b/string/endian.h
@@ -54,6 +54,19 @@
 # define __LONG_LONG_PAIR(HI, LO) HI, LO
 #endif
 
+/* Declare structure field that has different size
+   in 32- and 64-bit ABIs with paddings where needed,
+   so final layout becomes identical.  */
+#if __WORDSIZE == 32
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define __type3264(type, name) type name; type name##_pad
+# else
+#  define __type3264(type, name) type name##_pad; type name
+# endif
+#else /* __WORDSIZE == 64.  */
+# define __type3264(type, name) type name
+#endif
+
 
 #if defined __USE_MISC && !defined __ASSEMBLER__
 /* Conversion interfaces.  */
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
index 39c0c81..be6497f 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
@@ -62,6 +62,12 @@
 #define __SYSCALL_ULONG_TYPE	__ULONGWORD_TYPE
 #define __CPU_MASK_TYPE         __ULONGWORD_TYPE
 
+
+#ifdef __ILP32__
+# define __ASSUME_SUPPORT_64_BIT_TIME_TYPES
+# define XSTAT_IS_XSTAT64
+#endif
+
 /* Tell the libc code that off_t and off64_t are actually the same type
    for all ABI purposes, even if possibly expressed as different base types
    for C type-checking purposes.  */
diff --git a/sysdeps/unix/sysv/linux/aarch64/ilp32/fstatfs64.c b/sysdeps/unix/sysv/linux/aarch64/ilp32/fstatfs64.c
new file mode 100644
index 0000000..174d3a9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/ilp32/fstatfs64.c
@@ -0,0 +1,36 @@
+/* Return information about the filesystem on which FD resides.
+   Copyright (C) 1996-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/>.  */
+#define __fstatfs __statfs_disable
+#define fstatfs statfs_disable
+
+#include <errno.h>
+#include <sys/statfs.h>
+#include <stddef.h>
+
+int
+__fstatfs64 (int fd, struct statfs64 *buf)
+{
+  return INLINE_SYSCALL (fstatfs64, 2, fd, buf);
+}
+
+#undef __fstatfs
+#undef fstatfs
+strong_alias (__fstatfs64, __fstatfs)
+weak_alias (__fstatfs64, fstatfs64)
+weak_alias (__fstatfs64, fstatfs)
+
diff --git a/sysdeps/unix/sysv/linux/aarch64/ilp32/statfs64.c b/sysdeps/unix/sysv/linux/aarch64/ilp32/statfs64.c
new file mode 100644
index 0000000..6c7d1b9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/ilp32/statfs64.c
@@ -0,0 +1,39 @@
+/* Return information about the filesystem on which FILE resides.
+
+   Copyright (C) 2011-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   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/>.  */
+#define __statfs __statfs_disable
+#define statfs statfs_disable
+
+#include <errno.h>
+#include <sys/statfs.h>
+#include <stddef.h>
+
+int
+__statfs64 (const char *file, struct statfs64 *buf)
+{
+  return INLINE_SYSCALL (statfs64, 2, file, buf);
+}
+
+#undef __statfs
+#undef statfs
+weak_alias (__statfs64, statfs64)
+strong_alias (__statfs64, __statfs)
+libc_hidden_ver (__statfs64, __statfs)
+weak_alias (__statfs64, statfs)
+
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 5468dd6..9690da6 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,9 @@ 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..f1d7488 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 dd8d799..4688ed6 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/stat.h
@@ -42,7 +42,7 @@
 
 #if defined __USE_FILE_OFFSET64
 # define __field64(type, type64, name) type64 name
-#elif __WORDSIZE == 64
+#elif __WORDSIZE == 64 || defined (XSTAT_IS_XSTAT64)
 # define __field64(type, type64, name) type name
 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 # define __field64(type, type64, name) \
@@ -73,19 +73,28 @@ 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.  */
+    DECLARE_TIMESPEC (st_atim);		/* Time of last access.  */
+    DECLARE_TIMESPEC (st_mtim);		/* Time of last modification.  */
+    DECLARE_TIMESPEC (st_ctim);		/* Time of last status change.  */
 # 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];
   };
@@ -114,16 +123,28 @@ 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.  */
+    DECLARE_TIMESPEC (st_atim);		/* Time of last access.  */
+    DECLARE_TIMESPEC (st_mtim);		/* Time of last modification.  */
+    DECLARE_TIMESPEC (st_ctim);		/* Time of last status change.  */
+# 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];
   };
diff --git a/sysdeps/unix/sysv/linux/generic/bits/statfs.h b/sysdeps/unix/sysv/linux/generic/bits/statfs.h
index 7d5aa2d..581cf4f 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/statfs.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/statfs.h
@@ -34,7 +34,7 @@
 
 #if defined __USE_FILE_OFFSET64
 # define __field64(type, type64, name) type64 name
-#elif __WORDSIZE == 64
+#elif __WORDSIZE == 64 || defined (XSTAT_IS_XSTAT64)
 # define __field64(type, type64, name) type name
 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 # define __field64(type, type64, name) \
@@ -44,20 +44,26 @@
   int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); 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
@@ -65,18 +71,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..e95800d 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,5 @@ __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..af1ff48 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,5 @@ __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..4543897 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,5 @@ __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..217a6c8 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,30 @@
 #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..4893398 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,5 @@ __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..effb3a0 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,5 @@ __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..fc3ce13 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,28 @@
 #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..500de02
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/kernel-time.h
@@ -0,0 +1,40 @@
+/* Helpers to convert struct __timespec to user-visible timespec.
+
+   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
+# define conv_timespec(ts, _ts)					\
+  do								\
+    {								\
+      (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, &(__stat)->__st_atim);	\
+      conv_timespec (&(__stat)->st_mtim, &(__stat)->__st_mtim);	\
+      conv_timespec (&(__stat)->st_ctim, &(__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/time/time.h b/time/time.h
index cc93917..c5dfcbb 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					\
@@ -123,6 +133,24 @@ struct timespec
     __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
   };
 
+# if SUPPORT_64BIT_TIME_TYPES
+struct __timespec
+  {
+    long long tv_sec;		/* Seconds.  */
+    long long tv_nsec;		/* Nanoseconds.  */
+  };
+
+#  define DECLARE_TIMESPEC(__name)		\
+    union					\
+      {						\
+	    struct timespec __name;		\
+	    struct __timespec __##__name;	\
+      };
+
+# else
+#  define DECLARE_TIMESPEC(__name) struct timespec __name
+# endif
+
 #endif /* timespec not defined and <time.h> or need timespec.  */
 #undef	__need_timespec
 
-- 
2.7.4


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