[RFC2,RESEND,AARCH64] ILP32: support stat syscall family
Commit Message
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
Comments
Yury Norov <ynorov@caviumnetworks.com> writes:
> 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
You still didn't take notice of the testsuite failures.
Andreas.
On Wed, 6 Jul 2016, Yury Norov wrote:
> - 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.
First: why is it used in an installed header at all? The public API uses
struct timespec, not struct __timespec. If you need to reinterpret the
bits of struct timespec in some other way, because the kernel ABI is
different from the userspace ABI, that is purely a matter for the relevant
function implementations and should not affect the installed header.
Second: any interface in an installed header that does not start with
_[_A-Z] is a public interface. This means that (a) it must be permitted
to appear in that header by the relevant standards, depending on the
feature test macros in use, (b) we must have made a deliberate decision as
a community that this is an interface that we wish to support for our
users, indefinitely, (c) it must normally be documented and have testsuite
coverage, and (d) it must be system-independent unless there is a definite
reason for a system-specific interface. So any macros, typedefs etc. in
installed headers that do not meet all those requirements must be in the
implementation namespace _[_A-Z]*. This applies to all such macros added
to installed headers by this patch. That includes statfs_word_t; although
POSIX reserves *_t, we should not have any such types in public headers,
outside the _[_A-Z]* namespace, unless they are documented public
interfaces meeting all of (a)-(d), so you should not use statfs_word_t as
a type name.
> +/* 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
I don't think you want name##_pad; if name is a public interface, then
this would make name##_pad a public interface as well, with all the
corresponding requirements. __##name##_pad would be better. And why
isn't this using alignment attributes as in
sysdeps/unix/sysv/linux/generic/bits/stat.h? I wonder if this needs to be
separate from __field64 there or if there could be some common macro?
On Wed, Jul 20, 2016 at 04:11:17PM +0000, Joseph Myers wrote:
> On Wed, 6 Jul 2016, Yury Norov wrote:
>
> > - 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.
>
> First: why is it used in an installed header at all? The public API uses
> struct timespec, not struct __timespec. If you need to reinterpret the
> bits of struct timespec in some other way, because the kernel ABI is
> different from the userspace ABI, that is purely a matter for the relevant
> function implementations and should not affect the installed header.
When I wrote it initially, it was an attempt to start solving Y2038
problem, and it looks like this to me:
- we declare new structure (kernel_timespec or __timespec or timespec64)
that is identical with 64-bit timespec;
- we declare struct timespec in existing structures in union with new
timespec64 (in this patch - __timespec), and use convert_timespec()
macro where needed;
- we deprecate struct timespec for new interfaces, and force users to
use Y2038-safe version.
With all mentioned above, DECLARE_TIMESPEC() and struct __timespec are
both should be available to user in installed header. I was discussing
it with Arnd in comments to previous version to this patch. This is not
needed for arm64/ilp32 port directly, but we'd solve Y2038 somehow.
If there are better idea, I can try it with this port, of course, and then
I will hide 64-bit timespec, and use alignements instead of unions in
public interfaces, as you suggested.
> Second: any interface in an installed header that does not start with
> _[_A-Z] is a public interface. This means that (a) it must be permitted
> to appear in that header by the relevant standards, depending on the
> feature test macros in use, (b) we must have made a deliberate decision as
> a community that this is an interface that we wish to support for our
> users, indefinitely, (c) it must normally be documented and have testsuite
> coverage, and (d) it must be system-independent unless there is a definite
> reason for a system-specific interface. So any macros, typedefs etc. in
> installed headers that do not meet all those requirements must be in the
> implementation namespace _[_A-Z]*. This applies to all such macros added
> to installed headers by this patch. That includes statfs_word_t; although
> POSIX reserves *_t, we should not have any such types in public headers,
> outside the _[_A-Z]* namespace, unless they are documented public
> interfaces meeting all of (a)-(d), so you should not use statfs_word_t as
> a type name.
Thank you. I'll use underscored type / variable names for internal
purposes.
> > +/* 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
>
> I don't think you want name##_pad; if name is a public interface, then
> this would make name##_pad a public interface as well, with all the
> corresponding requirements. __##name##_pad would be better. And why
> isn't this using alignment attributes as in
> sysdeps/unix/sysv/linux/generic/bits/stat.h? I wonder if this needs to be
> separate from __field64 there or if there could be some common macro?
__field64 is more complex and specific macro. I think we can use __type3264
to declare __field64 where needed, I'll do it in next submission.
> --
> Joseph S. Myers
> joseph@codesourcery.com
On Mon, 1 Aug 2016, Yury Norov wrote:
> When I wrote it initially, it was an attempt to start solving Y2038
> problem, and it looks like this to me:
> - we declare new structure (kernel_timespec or __timespec or timespec64)
> that is identical with 64-bit timespec;
As that's for interfacing to the kernel, it should not appear in any
public header at all, only in internal sources.
> - we declare struct timespec in existing structures in union with new
> timespec64 (in this patch - __timespec), and use convert_timespec()
> macro where needed;
No. The structures passed to/from the kernel, containing the
kernel_timespec structure, should be declared in internal headers (e.g.
kernel_stat.h, if you need to convert a struct stat containing a struct
timespec), and conversion should deal with converting a kernel structure
to a public one. No such unions should appear in public headers. Public
headers should only contain the public userspace types, not types for
interfacing with the kernel.
On Mon, Aug 01, 2016 at 03:59:05PM +0000, Joseph Myers wrote:
> On Mon, 1 Aug 2016, Yury Norov wrote:
>
> > When I wrote it initially, it was an attempt to start solving Y2038
> > problem, and it looks like this to me:
> > - we declare new structure (kernel_timespec or __timespec or timespec64)
> > that is identical with 64-bit timespec;
>
> As that's for interfacing to the kernel, it should not appear in any
> public header at all, only in internal sources.
This is for Y2038. For interfacing to the kernel, it's enough to leave
space for 64-bit time types with align directive, and do conversion
internally.
32-bit ports should have 64-bit time types and structures to be ready
to Y2038, and for now we have no such structures.
> > - we declare struct timespec in existing structures in union with new
> > timespec64 (in this patch - __timespec), and use convert_timespec()
> > macro where needed;
>
> No. The structures passed to/from the kernel, containing the
> kernel_timespec structure, should be declared in internal headers (e.g.
> kernel_stat.h, if you need to convert a struct stat containing a struct
> timespec), and conversion should deal with converting a kernel structure
> to a public one. No such unions should appear in public headers. Public
> headers should only contain the public userspace types, not types for
> interfacing with the kernel.
OK, I'll prepare the patch w/o unions. Anyway, I think we'd have
64-bit timespec for 32-bit ports. Are you OK if I will introduce
struct timespec64 in separated installed header, and use it under
SUPPORT_64_BIT_TIME_TYPES option?
Yury.
> --
> Joseph S. Myers
> joseph@codesourcery.com
On Mon, 1 Aug 2016, Yury Norov wrote:
> 32-bit ports should have 64-bit time types and structures to be ready
> to Y2038, and for now we have no such structures.
If you are interested in Y2038 support, you need to engage in the threads
discussing successive revisions of
<https://sourceware.org/glibc/wiki/Y2038ProofnessDesign>. I imagine that
Albert ARIBAUD will be working on patches once the design is established.
> OK, I'll prepare the patch w/o unions. Anyway, I think we'd have
> 64-bit timespec for 32-bit ports. Are you OK if I will introduce
> struct timespec64 in separated installed header, and use it under
> SUPPORT_64_BIT_TIME_TYPES option?
SUPPORT_64_BIT_TIME_TYPES is in the user namespace; it has no business in
installed headers. The proposed design does not involve any APIs for
explicit 64-bit time use (APIs like lseek64 with off64_t in the
large-files case), only use of _TIME_BITS=64 to redirect existing APIs to
new ABIs (those ABIs being in the implementation namespace, of course, and
new ABIs only being present in those cases where the default interface
uses 32-bit time_t). Thus there should be no such type as struct
timespec64 in installed headers, only different definitions of struct
timespec depending on _TIME_BITS.
On Wed, Jul 06, 2016 at 05:32:06PM +0200, Andreas Schwab wrote:
> Yury Norov <ynorov@caviumnetworks.com> writes:
>
> > 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
>
> You still didn't take notice of the testsuite failures.
>
> Andreas.
Andreas,
I cannot run testsuite right now. Could you describe the problem in
detiles?
Yury.
On Do, Aug 04 2016, Yury Norov <ynorov@caviumnetworks.com> wrote:
> I cannot run testsuite right now.
Why not?
Andreas.
On Thu, Aug 04, 2016 at 10:47:01AM +0200, Andreas Schwab wrote:
> On Do, Aug 04 2016, Yury Norov <ynorov@caviumnetworks.com> wrote:
>
> > I cannot run testsuite right now.
>
> Why not?
>
> Andreas.
I cross-compile glibc, and run it under qemu. I just don't know how to
run testsuite in this case. If you know, could you share the manual?
On Do, Aug 04 2016, Yury Norov <ynorov@caviumnetworks.com> wrote:
> I cross-compile glibc, and run it under qemu. I just don't know how to
> run testsuite in this case. If you know, could you share the manual?
Have you tried "make check"?
Andreas.
On Thu, Aug 04, 2016 at 11:11:59AM +0200, Andreas Schwab wrote:
> On Do, Aug 04 2016, Yury Norov <ynorov@caviumnetworks.com> wrote:
>
> > I cross-compile glibc, and run it under qemu. I just don't know how to
> > run testsuite in this case. If you know, could you share the manual?
>
> Have you tried "make check"?
>
> Andreas.
Doesn't work for me as I told.
I have new patches for stat syscalls. So let's I send it to the list
without testsuite run, and while you and other people review it, I'll
fix testsuite failures. This is quite deep rework, so there will be
other comments except of this, for sure.
Yury
yury@yury-N73SV:~/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32$
make check
make -r PARALLELMFLAGS="" -C
/home/yury/work/toolchain/scripts/../glibc objdir=`pwd` check
make[1]: Entering directory '/home/yury/work/toolchain/gits/glibc'
make subdir=csu -C csu ..=../ tests
make[2]: Entering directory '/home/yury/work/toolchain/gits/glibc/csu'
/home/yury/work/toolchain/scripts/../minimal-aarch64-thunderx-linux-gnu/bin/aarch64-thunderx-linux-gnu-gcc
-mabi=ilp32 -O2 -nostdlib -nostartfiles -o
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/tst-atomic
-Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/crt1.o
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/crti.o
`/home/yury/work/toolchain/scripts/../minimal-aarch64-thunderx-linux-gnu/bin/aarch64-thunderx-linux-gnu-gcc
-mabi=ilp32 -O2 --print-file-name=crtbegin.o`
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/tst-atomic.o
-Wl,-dynamic-linker=/lib/ld-linux-aarch64_ilp32.so.1
-Wl,-rpath-link=/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/math:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/elf:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/dlfcn:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/nss:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/nis:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/rt:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/resolv:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/crypt:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/mathvec:/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/nptl
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/libc.so.6
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/libc_nonshared.a
-Wl,--as-needed
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/elf/ld.so
-Wl,--no-as-needed -lgcc -Wl,--as-needed -lgcc_s -Wl,--no-as-needed
`/home/yury/work/toolchain/scripts/../minimal-aarch64-thunderx-linux-gnu/bin/aarch64-thunderx-linux-gnu-gcc
-mabi=ilp32 -O2 --print-file-name=crtend.o`
/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/crtn.o
/home/yury/work/toolchain/minimal-aarch64-thunderx-linux-gnu/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../../aarch64-thunderx-linux-gnu/bin/ld:
cannot find -lgcc_s
collect2: error: ld returned 1 exit status
../Rules:154: recipe for target
'/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/tst-atomic'
failed
make[2]: ***
[/home/yury/work/toolchain/build-glibc-aarch64-thunderx-linux-gnu-mabi-ilp32/csu/tst-atomic]
Error 1
make[2]: Leaving directory '/home/yury/work/toolchain/gits/glibc/csu'
Makefile:214: recipe for target 'csu/tests' failed
make[1]: *** [csu/tests] Error 2
make[1]: Leaving directory '/home/yury/work/toolchain/gits/glibc'
Makefile:9: recipe for target 'check' failed
make: *** [check] Error 2
On Do, Aug 04 2016, Yury Norov <ynorov@caviumnetworks.com> wrote:
> /home/yury/work/toolchain/minimal-aarch64-thunderx-linux-gnu/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../../aarch64-thunderx-linux-gnu/bin/ld:
> cannot find -lgcc_s
You need to fix your cross compiler.
Andreas.
On Thu, 4 Aug 2016, Yury Norov wrote:
> I cross-compile glibc, and run it under qemu. I just don't know how to
> run testsuite in this case. If you know, could you share the manual?
install.texi explains the use of cross-test-ssh.sh for testing over SSH.
You can use the --ssh option if necessary to point to a wrapper that
connects to whatever port your QEMU instance is listening for SSH
connections on.
@@ -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. */
@@ -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. */
new file mode 100644
@@ -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)
+
new file mode 100644
@@ -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)
+
@@ -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
+
@@ -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
+
@@ -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];
};
@@ -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
@@ -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
+
@@ -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
+
@@ -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
+
@@ -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
+
@@ -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
+
@@ -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
+
@@ -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
+
@@ -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
+
new file mode 100644
@@ -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
+
@@ -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