From 8a83450e77f84d713a9f5e617baedbb69a8e6f8e Mon Sep 17 00:00:00 2001
From: Waldemar Brodkorb <wbx@openadk.org>
Date: Wed, 23 Oct 2019 13:57:27 +0200
Subject: [PATCH] csky: add statx conditionals
Similar to glibc commit
https://sourceware.org/git/?p=glibc.git;a=commit;h=6bbfc5c09fc5b5e3d4a0cddbbd4e2e457767dae7
we need to handle Linux kernel change, which removed stat64 family from default syscall set.
Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
---
extra/Configs/Config.csky | 1 -
include/fcntl.h | 5 ++
include/sys/stat.h | 5 ++
ldso/include/dl-syscall.h | 62 ++++++++++++++++++++++-
ldso/ldso/csky/elfinterp.c | 10 +---
libc/sysdeps/linux/common/bits/statx.h | 93 ++++++++++++++++++++++++++++++++++
libc/sysdeps/linux/common/fstat.c | 16 +++++-
libc/sysdeps/linux/common/fstat64.c | 17 +++++++
libc/sysdeps/linux/common/lstat.c | 19 ++++++-
libc/sysdeps/linux/common/lstat64.c | 17 +++++++
libc/sysdeps/linux/common/stat.c | 15 +++++-
libc/sysdeps/linux/common/stat64.c | 16 ++++++
libc/sysdeps/linux/common/statx_cp.c | 72 ++++++++++++++++++++++++++
libc/sysdeps/linux/common/statx_cp.h | 22 ++++++++
libc/sysdeps/linux/csky/Makefile.arch | 2 +-
libc/sysdeps/linux/csky/bits/fcntl.h | 6 +--
16 files changed, 361 insertions(+), 17 deletions(-)
create mode 100644 libc/sysdeps/linux/common/bits/statx.h
create mode 100644 libc/sysdeps/linux/common/statx_cp.c
create mode 100644 libc/sysdeps/linux/common/statx_cp.h
@@ -6,7 +6,6 @@ config FORCE_OPTIONS_FOR_ARCH
bool
default y
select ARCH_ANY_ENDIAN
- select ARCH_HAS_DEPRECATED_SYSCALLS
select ARCH_USE_MMU
select ARCH_HAS_MMU
@@ -67,6 +67,11 @@ __BEGIN_DECLS
# define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount
traversal. */
# define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname. */
+# define AT_STATX_SYNC_TYPE 0x6000
+# define AT_STATX_SYNC_AS_STAT 0x0000
+# define AT_STATX_FORCE_SYNC 0x2000
+# define AT_STATX_DONT_SYNC 0x4000
+# define AT_RECURSIVE 0x8000 /* Apply to the entire subtree. */
# endif
# define AT_EACCESS 0x200 /* Test access permitted for
effective IDs, not real IDs. */
@@ -393,6 +393,11 @@ extern int futimens (int __fd, const struct timespec __times[2]) __THROW;
#undef _MKNOD_VER
#define _MKNOD_VER 0
+#ifdef __USE_GNU
+# include <bits/statx.h>
+#endif
+
+
__END_DECLS
@@ -36,9 +36,37 @@ extern int _dl_errno;
/* 1. common-generic ABI doesn't need kernel_stat translation
* 3. S_IS?ID already provided by stat.h
*/
+#include <fcntl.h>
#include <sys/stat.h>
+#include <dl-string.h>
+
+static __always_inline void
+__cp_stat_statx (struct stat *to, struct statx *from)
+{
+ _dl_memset (to, 0, sizeof (struct stat));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
#endif
+#define AT_NO_AUTOMOUNT 0x800
+#define AT_EMPTY_PATH 0x1000
/* Here are the definitions for some syscalls that are used
by the dynamic linker. The idea is that we want to be able
@@ -109,14 +137,46 @@ static __always_inline int _dl_stat(const char *file_name,
# define __NR__dl_stat __NR_stat
static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
struct stat *, buf)
+
+#elif defined __NR_statx
+# define __NR__dl_statx __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+static __always_inline _syscall5(int, _dl_statx, int, fd, const char *, file_name, int, flags,
+ unsigned int, mask, struct statx *, buf);
+
+static __always_inline int _dl_stat(const char *file_name,
+ struct stat *buf)
+{
+ struct statx tmp;
+ int rc = _dl_statx(AT_FDCWD, file_name, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+ return rc;
+}
#endif
#if defined __NR_fstat64 && !defined __NR_fstat
# define __NR__dl_fstat __NR_fstat64
#elif defined __NR_fstat
# define __NR__dl_fstat __NR_fstat
-#endif
static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf)
+#else
+# define __NR__dl_fstatx __NR_statx
+static __always_inline _syscall5(int, _dl_fstatx, int, fd, const char *, file_name, int, flags, unsigned int, mask, struct stat *, buf);
+
+static __always_inline int _dl_fstat(int fd,
+ struct stat *buf)
+{
+ struct statx tmp;
+ int rc = _dl_fstatx(fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+ return rc;
+}
+
+#endif
#define __NR__dl_munmap __NR_munmap
static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length)
@@ -79,17 +79,11 @@ _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem*scope,
strtab + symtab[symtab_index].st_name);
if (unlikely(res < 0)) {
int reloc_type = ELF32_R_TYPE(rpnt->r_info);
-
-#if defined (__SUPPORT_LD_DEBUG__)
- _dl_dprintf(2, "2can't handle reloc type '%s' in lib '%s'\n",
- _dl_reltypes(reloc_type), tpnt->libname);
-#else
- _dl_dprintf(2, "3can't handle reloc type %x in lib '%s'\n",
+ _dl_dprintf(2, "2can't handle reloc type %x in lib '%s'\n",
reloc_type, tpnt->libname);
-#endif
return res;
} else if (unlikely(res > 0)) {
- _dl_dprintf(2, "4can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ _dl_dprintf(2, "3can't resolve symbol in lib '%s'.\n", tpnt->libname);
return res;
}
}
new file mode 100644
@@ -0,0 +1,93 @@
+/* Generic statx-related definitions and declarations.
+ Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+/* This interface is based on <linux/stat.h> in Linux. */
+
+#ifndef _SYS_STAT_H
+# error Never include <bits/statx.h> directly, include <sys/stat.h> instead.
+#endif
+
+struct statx_timestamp
+{
+ __int64_t tv_sec;
+ __uint32_t tv_nsec;
+ __int32_t __statx_timestamp_pad1[1];
+};
+
+/* Warning: The kernel may add additional fields to this struct in the
+ future. Only use this struct for calling the statx function, not
+ for storing data. (Expansion will be controlled by the mask
+ argument of the statx function.) */
+struct statx
+{
+ __uint32_t stx_mask;
+ __uint32_t stx_blksize;
+ __uint64_t stx_attributes;
+ __uint32_t stx_nlink;
+ __uint32_t stx_uid;
+ __uint32_t stx_gid;
+ __uint16_t stx_mode;
+ __uint16_t __statx_pad1[1];
+ __uint64_t stx_ino;
+ __uint64_t stx_size;
+ __uint64_t stx_blocks;
+ __uint64_t stx_attributes_mask;
+ struct statx_timestamp stx_atime;
+ struct statx_timestamp stx_btime;
+ struct statx_timestamp stx_ctime;
+ struct statx_timestamp stx_mtime;
+ __uint32_t stx_rdev_major;
+ __uint32_t stx_rdev_minor;
+ __uint32_t stx_dev_major;
+ __uint32_t stx_dev_minor;
+ __uint64_t __statx_pad2[14];
+};
+
+#ifndef STATX_TYPE
+# define STATX_TYPE 0x0001U
+# define STATX_MODE 0x0002U
+# define STATX_NLINK 0x0004U
+# define STATX_UID 0x0008U
+# define STATX_GID 0x0010U
+# define STATX_ATIME 0x0020U
+# define STATX_MTIME 0x0040U
+# define STATX_CTIME 0x0080U
+# define STATX_INO 0x0100U
+# define STATX_SIZE 0x0200U
+# define STATX_BLOCKS 0x0400U
+# define STATX_BASIC_STATS 0x07ffU
+# define STATX_ALL 0x0fffU
+# define STATX_BTIME 0x0800U
+# define STATX__RESERVED 0x80000000U
+
+# define STATX_ATTR_COMPRESSED 0x0004
+# define STATX_ATTR_IMMUTABLE 0x0010
+# define STATX_ATTR_APPEND 0x0020
+# define STATX_ATTR_NODUMP 0x0040
+# define STATX_ATTR_ENCRYPTED 0x0800
+# define STATX_ATTR_AUTOMOUNT 0x1000
+#endif /* !STATX_TYPE */
+
+__BEGIN_DECLS
+
+/* Fill *BUF with information about PATH in DIRFD. */
+int statx (int __dirfd, const char *__restrict __path, int __flags,
+ unsigned int __mask, struct statx *__restrict __buf)
+ __THROW __nonnull ((2, 5));
+
+__END_DECLS
+
@@ -29,6 +29,20 @@ int fstat(int fd, struct stat *buf)
}
libc_hidden_def(fstat)
+#elif __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int fstat(int fd, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+}
+libc_hidden_def(fstat)
+
#elif defined __NR_fstat
int fstat(int fd, struct stat *buf)
{
@@ -57,7 +71,7 @@ int fstat(int fd, struct stat *buf)
libc_hidden_def(fstat)
#endif
-# if ! defined __NR_fstat64
+# if ! defined __NR_fstat64 && ! defined __NR_statx
strong_alias_untyped(fstat,fstat64)
libc_hidden_def(fstat64)
#endif
@@ -28,9 +28,26 @@ int fstat64(int fd, struct stat64 *buf)
__xstat64_conv(&kbuf, buf);
}
return result;
+
#else
return __syscall_fstat64(fd, buf);
#endif
}
libc_hidden_def(fstat64)
+
+#elif __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int fstat64(int fd, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(fstat64)
#endif
@@ -28,6 +28,23 @@ int lstat(const char *file_name, struct stat *buf)
}
libc_hidden_def(lstat)
+#elif defined __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int lstat(const char *file_name, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name,
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(lstat)
+
/* For systems which have both, prefer the old one */
#else
# include "xstatconv.h"
@@ -57,7 +74,7 @@ int lstat(const char *file_name, struct stat *buf)
}
libc_hidden_def(lstat)
-# if ! defined __NR_fstatat64 && ! defined __NR_lstat64
+# if ! defined __NR_fstatat64 && ! defined __NR_lstat64 && ! defined __NR_statx
strong_alias_untyped(lstat,lstat64)
libc_hidden_def(lstat64)
# endif
@@ -29,6 +29,23 @@ int lstat64(const char *file_name, struct stat64 *buf)
}
libc_hidden_def(lstat64)
+#elif defined __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int lstat64(const char *file_name, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name,
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(lstat64)
+
/* For systems which have both, prefer the old one */
#elif defined __NR_lstat64
# include "xstatconv.h"
@@ -27,7 +27,20 @@ int stat(const char *file_name, struct stat *buf)
{
return fstatat64(AT_FDCWD, file_name, buf, 0);
}
+#elif __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+int stat(const char *file_name, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+
+ return rc;
+}
#else
# include "xstatconv.h"
@@ -58,7 +71,7 @@ int stat(const char *file_name, struct stat *buf)
#endif /* __NR_fstat64 */
libc_hidden_def(stat)
-#if ! defined __NR_stat64 && ! defined __NR_fstatat64
+#if ! defined __NR_stat64 && ! defined __NR_fstatat64 && ! defined __NR_statx
strong_alias_untyped(stat,stat64)
libc_hidden_def(stat64)
#endif
@@ -20,6 +20,22 @@ int stat64(const char *file_name, struct stat64 *buf)
}
libc_hidden_def(stat64)
+#elif __NR_statx
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int stat64(const char *file_name, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(stat64)
+
/* For systems which have both, prefer the old one */
# elif defined __NR_stat64
# define __NR___syscall_stat64 __NR_stat64
new file mode 100644
@@ -0,0 +1,72 @@
+/* Struct statx to stat/stat64 conversion for Linux.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ 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/>. */
+
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <statx_cp.h>
+
+#if !defined(__NR_fstat64) || !defined(__NR_fstatat64)
+void
+__cp_stat64_statx (struct stat64 *to, struct statx *from)
+{
+ memset (to, 0, sizeof (struct stat64));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
+
+void
+__cp_stat_statx (struct stat *to, struct statx *from)
+{
+ memset (to, 0, sizeof (struct stat));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
+#endif
new file mode 100644
@@ -0,0 +1,22 @@
+/* Struct statx to stat/stat64 conversion for Linux.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ 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/>. */
+
+extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
+ attribute_hidden;
+
+extern void __cp_stat_statx (struct stat *to, struct statx *from)
+ attribute_hidden;
@@ -1,6 +1,6 @@
CSRC-y := clone.c __syscall_error.c cacheflush.c
SSRC-y := __longjmp.S setjmp.S
-SSRC-y += libc-read_tp.S vfork.S csky_clone.S
+SSRC-y += libc-read_tp.S csky_clone.S
@@ -33,13 +33,13 @@
#define O_ASYNC 020000
#ifdef __USE_XOPEN2K8
-# define O_DIRECTORY 040000 /* Must be a directory. */
-# define O_NOFOLLOW 0100000 /* Do not follow links. */
+# define O_DIRECTORY 00200000 /* must be a directory */
+# define O_NOFOLLOW 00400000 /* don't follow links */
# define O_CLOEXEC 02000000 /* Set close_on_exec. */
#endif
#ifdef __USE_GNU
-# define O_DIRECT 0200000 /* Direct disk access. */
+# define O_DIRECT 00040000 /* direct disk access hint */
# define O_NOATIME 01000000 /* Do not set atime. */
# define O_PATH 010000000 /* Resolve pathname but do not open file. */
#endif
--
2.11.0