@@ -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
@@ -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
@@ -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
+
@@ -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];
};
@@ -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
@@ -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
@@ -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,4 @@ __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,4 @@ __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,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
@@ -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
@@ -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
@@ -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
new file mode 100644
@@ -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
@@ -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
@@ -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 \
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