summaryrefslogtreecommitdiff
path: root/ldso/include/dl-syscall.h
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/include/dl-syscall.h')
-rw-r--r--ldso/include/dl-syscall.h84
1 files changed, 77 insertions, 7 deletions
diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
index 9d80c6a26..c143b8d45 100644
--- a/ldso/include/dl-syscall.h
+++ b/ldso/include/dl-syscall.h
@@ -11,8 +11,13 @@
* been dynamicly linked in yet. */
#include "sys/syscall.h"
extern int _dl_errno;
+
+#ifdef UCLIBC_LDSO
#undef __set_errno
#define __set_errno(X) {(_dl_errno) = (X);}
+#endif
+
+#include <linux/version.h>
/* Pull in the arch specific syscall implementation */
#include <dl-syscalls.h>
@@ -20,7 +25,7 @@ extern int _dl_errno;
#define _SYS_MMAN_H 1
#include <bits/mman.h>
-#ifdef __ARCH_HAS_DEPRECATED_SYSCALLS__
+#if defined(__ARCH_HAS_DEPRECATED_SYSCALLS__) && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__))
/* Pull in whatever this particular arch's kernel thinks the kernel version of
* struct stat should look like. It turns out that each arch has a different
* opinion on the subject, and different kernel revs use different names... */
@@ -36,9 +41,40 @@ 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>
+
+#include <bits/uClibc_arch_features.h>
+#if defined __UCLIBC_HAVE_STATX__
+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
#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
@@ -85,7 +121,7 @@ static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
static __always_inline _syscall3(int, _dl_mprotect, const void *, addr,
unsigned long, len, int, prot)
-#if defined __NR_fstatat64 && !defined __NR_stat
+#if defined __NR_fstatat64 && !defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__))
# define __NR__dl_fstatat64 __NR_fstatat64
static __always_inline _syscall4(int, _dl_fstatat64, int, fd, const char *,
fn, struct stat *, stat, int, flags)
@@ -95,7 +131,7 @@ static __always_inline int _dl_stat(const char *file_name,
{
return _dl_fstatat64(AT_FDCWD, file_name, buf, 0);
}
-#elif defined __NR_newfstatat && !defined __NR_stat
+#elif defined __NR_newfstatat && !defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__))
# define __NR__dl_newfstatat __NR_newfstatat
static __always_inline _syscall4(int, _dl_newfstatat, int, fd, const char *,
fn, struct stat *, stat, int, flags)
@@ -105,18 +141,52 @@ static __always_inline int _dl_stat(const char *file_name,
{
return _dl_newfstatat(AT_FDCWD, file_name, buf, 0);
}
-#elif defined __NR_stat
+#elif defined __NR_stat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__) || (LINUX_VERSION_CODE <= KERNEL_VERSION(5,1,0)))
# define __NR__dl_stat __NR_stat
static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
struct stat *, buf)
+
+#elif defined __NR_statx && defined __UCLIBC_HAVE_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
+#if defined __NR_fstat64 && !defined __NR_fstat && (!defined(__UCLIBC_USE_TIME64__) || defined(__sparc__))
# define __NR__dl_fstat __NR_fstat64
-#elif defined __NR_fstat
+static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf)
+#elif defined __NR_fstat && !defined __UCLIBC_USE_TIME64__ || defined(__sparc__)
# define __NR__dl_fstat __NR_fstat
-#endif
static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf)
+#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__
+# 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 statx *, 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;
+}
+#else
+static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf)
+#endif
#define __NR__dl_munmap __NR_munmap
static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length)