Thread (27 messages) 27 messages, 3 authors, 2018-07-19

Re: [PATCH v2 02/17] y2038: Remove newstat family from default syscall set

From: Arnd Bergmann <arnd@arndb.de>
Date: 2018-07-17 14:51:36
Also in: linux-arch, netdev
Subsystem: the rest · Maintainer: Linus Torvalds

On Tue, Jul 17, 2018 at 2:50 PM, Christoph Hellwig [off-list ref] wrote:
On Mon, Jul 16, 2018 at 06:10:48PM +0200, Arnd Bergmann wrote:
quoted
We have four generations of stat() syscalls:
- the oldstat syscalls that are only used on the older architectures
- the newstat family that is used on all 64-bit architectures but
  lacked support for large files on 32-bit architectures.
- the stat64 family that is used mostly on 32-bit architectures to
  replace newstat
- statx() to replace all of the above, adding 64-bit timestamps among
  other things.

We already compile stat64 only on those architectures that need it,
but newstat is always built, including on those that don't reference
it. This adds a new __ARCH_WANT_NEW_STAT symbol along the lines of
__ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 to control compilation of
newstat. All architectures that need it use an explict define, the
others now get a little bit smaller, and future architecture (including
64-bit targets) won't ever see it.

Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Do I read this right that you only want to provide statx by default?
Yes, that is correct.
It is a little different from the traditional stat calls, so I'd like
to know this is actually ok from libc folks first.
That would definitely help. See below for the stat implementation
I did in my musl libc prototype based on statx(). It passes the
LTP syscall tests, but that doesn't mean all the corner cases
are correct.

       Arnd
diff --git a/src/stat/fstat.c b/src/stat/fstat.c
index ab4afc0..b4f2027 100644
--- a/src/stat/fstat.c
+++ b/src/stat/fstat.c
@@ -1,3 +1,4 @@
+#define _BSD_SOURCE
 #include <sys/stat.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -8,6 +9,9 @@ void __procfdname(char *, unsigned);

 int fstat(int fd, struct stat *st)
 {
+#ifdef __USE_TIME_BITS64
+       return __statx(fd, "", st, AT_EMPTY_PATH | AT_STATX_SYNC_AS_STAT);
+#else
        int ret = __syscall(SYS_fstat, fd, st);
        if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0)
                return __syscall_ret(ret);
@@ -19,6 +23,7 @@ int fstat(int fd, struct stat *st)
 #else
        return syscall(SYS_fstatat, AT_FDCWD, buf, st, 0);
 #endif
+#endif
 }

 LFS64(fstat);
diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
index 863d526..80add64 100644
--- a/src/stat/fstatat.c
+++ b/src/stat/fstatat.c
@@ -1,10 +1,53 @@
+#define _BSD_SOURCE
 #include <sys/stat.h>
+#include <statx.h>
+#include <fcntl.h>
+#include <errno.h>
 #include "syscall.h"
 #include "libc.h"

+#ifdef __USE_TIME_BITS64
+
+#define AT_FLAGS (AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH)
+
+int __statx(int fd, const char *restrict path, struct stat *restrict
buf, int flag)
+{
+       struct statx stx;
+       int ret;
+
+       ret = syscall(SYS_statx, fd, path, flag, STATX_BASIC_STATS, &stx);
+
+       buf->st_dev = (dev_t)stx.stx_dev_major << 32 | stx.stx_dev_minor;
+       buf->st_ino = stx.stx_ino;
+       buf->st_mode = stx.stx_mode;
+       buf->st_nlink = stx.stx_nlink;
+       buf->st_uid = stx.stx_uid;
+       buf->st_gid = stx.stx_gid;
+       buf->st_rdev = (dev_t)stx.stx_rdev_major << 32 | stx.stx_rdev_minor;
+       buf->st_size = stx.stx_size;
+       buf->st_blksize = stx.stx_blksize;
+       buf->st_blocks = stx.stx_blocks;
+       buf->st_atim.tv_sec = stx.stx_atime.tv_sec;
+       buf->st_mtim.tv_sec = stx.stx_atime.tv_sec;
+       buf->st_ctim.tv_sec = stx.stx_atime.tv_sec;
+       buf->st_atim.tv_nsec = stx.stx_atime.tv_nsec;
+       buf->st_mtim.tv_nsec = stx.stx_atime.tv_nsec;
+       buf->st_ctim.tv_nsec = stx.stx_atime.tv_nsec;
+
+       return ret;
+}
+#endif
+
 int fstatat(int fd, const char *restrict path, struct stat *restrict
buf, int flag)
 {
+#ifdef __USE_TIME_BITS64
+       if (flag & ~AT_FLAGS)
+               return __syscall_ret(-EINVAL);
+
+       return __statx(fd, path, buf, flag);
+#else
        return syscall(SYS_fstatat, fd, path, buf, flag);
+#endif
 }

 LFS64(fstatat);
diff --git a/src/stat/lstat.c b/src/stat/lstat.c
index 5e8b84f..ad2bddd 100644
--- a/src/stat/lstat.c
+++ b/src/stat/lstat.c
@@ -1,3 +1,4 @@
+#define _BSD_SOURCE
 #include <sys/stat.h>
 #include <fcntl.h>
 #include "syscall.h"
@@ -5,7 +6,9 @@

 int lstat(const char *restrict path, struct stat *restrict buf)
 {
-#ifdef SYS_lstat
+#ifdef __USE_TIME_BITS64
+       return __statx(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW |
AT_STATX_SYNC_AS_STAT);
+#elif defined(SYS_lstat)
        return syscall(SYS_lstat, path, buf);
 #else
        return syscall(SYS_fstatat, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
diff --git a/src/stat/stat.c b/src/stat/stat.c
index b4433a0..599903a 100644
--- a/src/stat/stat.c
+++ b/src/stat/stat.c
@@ -1,3 +1,4 @@
+#define _BSD_SOURCE
 #include <sys/stat.h>
 #include <fcntl.h>
 #include "syscall.h"
@@ -5,7 +6,9 @@

 int stat(const char *restrict path, struct stat *restrict buf)
 {
-#ifdef SYS_stat
+#ifdef __USE_TIME_BITS64
+       return __statx(AT_FDCWD, path, buf, AT_STATX_SYNC_AS_STAT);
+#elif defined(SYS_stat)
        return syscall(SYS_stat, path, buf);
 #else
        return syscall(SYS_fstatat, AT_FDCWD, path, buf, 0);
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help