[PATCH] support kernels without __ARCH_WANT_SYSCALL_NO_AT

Mark Salter msalter at redhat.com
Thu Apr 26 14:18:54 UTC 2012


---
 ldso/include/dl-syscall.h                          |   22 ++++++++++++++++++++
 libc/sysdeps/linux/common/access.c                 |    8 +++++++
 libc/sysdeps/linux/common/chmod.c                  |    8 +++++++
 libc/sysdeps/linux/common/chown.c                  |   15 ++++++++++++-
 libc/sysdeps/linux/common/fstatat.c                |    2 +-
 libc/sysdeps/linux/common/fstatat64.c              |    2 +-
 libc/sysdeps/linux/common/lchown.c                 |   13 +++++++++++
 libc/sysdeps/linux/common/link.c                   |    9 ++++++++
 libc/sysdeps/linux/common/lstat.c                  |    3 ++
 libc/sysdeps/linux/common/mkdir.c                  |    8 +++++++
 libc/sysdeps/linux/common/mknod.c                  |    5 ++++
 libc/sysdeps/linux/common/not-cancel.h             |    8 +++++++
 libc/sysdeps/linux/common/open.c                   |    8 +++++++
 libc/sysdeps/linux/common/readlink.c               |    8 +++++++
 libc/sysdeps/linux/common/rename.c                 |    9 ++++++++
 libc/sysdeps/linux/common/rmdir.c                  |    9 ++++++++
 libc/sysdeps/linux/common/stubs.c                  |    4 +-
 libc/sysdeps/linux/common/symlink.c                |    8 +++++++
 libc/sysdeps/linux/common/unlink.c                 |    8 +++++++
 libc/sysdeps/linux/common/utimes.c                 |   22 ++++++++++++++++++++
 .../linuxthreads.old/sysdeps/pthread/not-cancel.h  |    8 +++++++
 21 files changed, 182 insertions(+), 5 deletions(-)

diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
index 7549204..0908d3f 100644
--- a/ldso/include/dl-syscall.h
+++ b/ldso/include/dl-syscall.h
@@ -49,9 +49,20 @@ static __always_inline _syscall1(void, _dl_exit, int, status)
 #define __NR__dl_close __NR_close
 static __always_inline _syscall1(int, _dl_close, int, fd)
 
+#if defined(__NR_open)
 #define __NR__dl_open __NR_open
 static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags,
                         __kernel_mode_t, mode)
+#elif defined(__NR_openat)
+#define __NR__dl_openat __NR_openat
+static __always_inline _syscall4(int, _dl_openat, int, dirfd, const char *, fn,
+				 int, flags, __kernel_mode_t, mode)
+static __always_inline ssize_t
+_dl_open(const char *fn, int flags, __kernel_mode_t mode)
+{
+	return _dl_openat(AT_FDCWD, fn, flags, mode);
+}
+#endif
 
 #define __NR__dl_write __NR_write
 static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
@@ -120,9 +131,20 @@ static __always_inline _syscall0(gid_t, _dl_getegid)
 #define __NR__dl_getpid __NR_getpid
 static __always_inline _syscall0(gid_t, _dl_getpid)
 
+#if defined(__NR_readlink)
 #define __NR__dl_readlink __NR_readlink
 static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
                         size_t, bufsiz)
+#elif defined(__NR_readlinkat)
+#define __NR__dl_readlinkat __NR_readlinkat
+static __always_inline _syscall4(int, _dl_readlinkat, int, dirfd,
+				 const char *, fn, char *, buf, size_t, size)
+static __always_inline int
+_dl_readlink(const char *fn, char *buf, size_t size)
+{
+	return _dl_readlinkat(AT_FDCWD, fn, buf, size);
+}
+#endif
 
 #ifdef __NR_pread64
 #define __NR___syscall_pread __NR_pread64
diff --git a/libc/sysdeps/linux/common/access.c b/libc/sysdeps/linux/common/access.c
index a075d42..1cbee2a 100644
--- a/libc/sysdeps/linux/common/access.c
+++ b/libc/sysdeps/linux/common/access.c
@@ -9,4 +9,12 @@
 
 #include <sys/syscall.h>
 #include <unistd.h>
+#ifdef __NR_access
 _syscall2(int, access, const char *, pathname, int, mode)
+#elif defined __NR_faccessat
+#include <fcntl.h>
+int access(const char *pathname, int mode)
+{
+	return faccessat(AT_FDCWD, pathname, mode, 0);
+}
+#endif
diff --git a/libc/sysdeps/linux/common/chmod.c b/libc/sysdeps/linux/common/chmod.c
index 871e023..7c2d6fc 100644
--- a/libc/sysdeps/linux/common/chmod.c
+++ b/libc/sysdeps/linux/common/chmod.c
@@ -11,6 +11,7 @@
 #include <sys/stat.h>
 
 
+#ifdef __NR_chmod
 #define __NR___syscall_chmod __NR_chmod
 static __inline__ _syscall2(int, __syscall_chmod, const char *, path, __kernel_mode_t, mode)
 
@@ -18,4 +19,11 @@ int chmod(const char *path, mode_t mode)
 {
 	return __syscall_chmod(path, mode);
 }
+#elif defined __NR_fchmodat
+#include <fcntl.h>
+int chmod(const char *path, mode_t mode)
+{
+	return fchmodat(AT_FDCWD, path, mode, 0);
+}
+#endif
 libc_hidden_def(chmod)
diff --git a/libc/sysdeps/linux/common/chown.c b/libc/sysdeps/linux/common/chown.c
index f2c60e0..4de5979 100644
--- a/libc/sysdeps/linux/common/chown.c
+++ b/libc/sysdeps/linux/common/chown.c
@@ -22,7 +22,8 @@ _syscall3(int, chown, const char *, path, uid_t, owner, gid_t, group)
 
 #else
 
-# define __NR___syscall_chown __NR_chown
+# ifdef __NR_chown
+#  define __NR___syscall_chown __NR_chown
 static __inline__ _syscall3(int, __syscall_chown, const char *, path,
 		__kernel_uid_t, owner, __kernel_gid_t, group)
 
@@ -35,6 +36,18 @@ int chown(const char *path, uid_t owner, gid_t group)
 	}
 	return (__syscall_chown(path, owner, group));
 }
+# elif defined __NR_fchownat
+#include <fcntl.h>
+int chown(const char *path, uid_t owner, gid_t group)
+{
+	if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U))
+		|| ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) {
+		__set_errno(EINVAL);
+		return -1;
+	}
+	return fchownat(AT_FDCWD, path, owner, group, 0);
+}
+# endif
 #endif
 
 libc_hidden_def(chown)
diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c
index 33daa7c..21f1383 100644
--- a/libc/sysdeps/linux/common/fstatat.c
+++ b/libc/sysdeps/linux/common/fstatat.c
@@ -11,7 +11,7 @@
 #include "xstatconv.h"
 
 /* 64bit ports tend to favor newfstatat() */
-#ifdef __NR_newfstatat
+#if defined(__NR_newfstatat) && !defined(__NR_fstatat64)
 # define __NR_fstatat64 __NR_newfstatat
 #endif
 
diff --git a/libc/sysdeps/linux/common/fstatat64.c b/libc/sysdeps/linux/common/fstatat64.c
index 95627af..78a27b9 100644
--- a/libc/sysdeps/linux/common/fstatat64.c
+++ b/libc/sysdeps/linux/common/fstatat64.c
@@ -13,7 +13,7 @@
 #ifdef __UCLIBC_HAS_LFS__
 
 /* 64bit ports tend to favor newfstatat() */
-#ifdef __NR_newfstatat
+#if defined(__NR_newfstatat) && !defined(__NR_fstatat64)
 # define __NR_fstatat64 __NR_newfstatat
 #endif
 
diff --git a/libc/sysdeps/linux/common/lchown.c b/libc/sysdeps/linux/common/lchown.c
index c0f8ce7..9e3c8e3 100644
--- a/libc/sysdeps/linux/common/lchown.c
+++ b/libc/sysdeps/linux/common/lchown.c
@@ -21,6 +21,7 @@ _syscall3(int, lchown, const char *, path, uid_t, owner, gid_t, group)
 
 #else
 
+# if defined(__NR_lchown)
 # define __NR___syscall_lchown __NR_lchown
 static __inline__ _syscall3(int, __syscall_lchown, const char *, path,
 		__kernel_uid_t, owner, __kernel_gid_t, group)
@@ -35,4 +36,16 @@ int lchown(const char *path, uid_t owner, gid_t group)
 	return __syscall_lchown(path, owner, group);
 }
 
+# elif defined(__NR_fchownat)
+#include <fcntl.h>
+int lchown(const char *path, uid_t owner, gid_t group)
+{
+	if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U))
+		|| ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) {
+		__set_errno(EINVAL);
+		return -1;
+	}
+	return fchownat(AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW);
+}
+# endif
 #endif
diff --git a/libc/sysdeps/linux/common/link.c b/libc/sysdeps/linux/common/link.c
index b5e5536..59007f1 100644
--- a/libc/sysdeps/linux/common/link.c
+++ b/libc/sysdeps/linux/common/link.c
@@ -9,4 +9,13 @@
 
 #include <sys/syscall.h>
 #include <unistd.h>
+#if defined(__NR_link)
 _syscall2(int, link, const char *, oldpath, const char *, newpath)
+#elif defined(__NR_linkat)
+#include <fcntl.h>
+
+int link(const char * oldpath, const char * newpath)
+{
+	return linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
+}
+#endif
diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c
index db72d1f..f8678c0 100644
--- a/libc/sysdeps/linux/common/lstat.c
+++ b/libc/sysdeps/linux/common/lstat.c
@@ -9,6 +9,7 @@
 
 #include <sys/syscall.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include "xstatconv.h"
 
@@ -26,6 +27,8 @@ int lstat(const char *file_name, struct stat *buf)
 	if (result == 0) {
 		__xstat32_conv(&kbuf, buf);
 	}
+#elif defined(__NR_fstatat64)
+	result = fstatat(AT_FDCWD, file_name, buf, AT_SYMLINK_NOFOLLOW);
 #else
 	struct kernel_stat kbuf;
 
diff --git a/libc/sysdeps/linux/common/mkdir.c b/libc/sysdeps/linux/common/mkdir.c
index fbc587d..b4eb890 100644
--- a/libc/sysdeps/linux/common/mkdir.c
+++ b/libc/sysdeps/linux/common/mkdir.c
@@ -11,6 +11,7 @@
 #include <sys/stat.h>
 
 
+#ifdef __NR_mkdir
 #define __NR___syscall_mkdir __NR_mkdir
 static __inline__ _syscall2(int, __syscall_mkdir, const char *, pathname,
 		__kernel_mode_t, mode)
@@ -19,4 +20,11 @@ int mkdir(const char *pathname, mode_t mode)
 {
 	return (__syscall_mkdir(pathname, mode));
 }
+#elif defined(__NR_mkdirat)
+#include <fcntl.h>
+int mkdir(const char *pathname, mode_t mode)
+{
+	return mkdirat(AT_FDCWD, pathname, mode);
+}
+#endif
 libc_hidden_def(mkdir)
diff --git a/libc/sysdeps/linux/common/mknod.c b/libc/sysdeps/linux/common/mknod.c
index b52c8c5..9954626 100644
--- a/libc/sysdeps/linux/common/mknod.c
+++ b/libc/sysdeps/linux/common/mknod.c
@@ -9,6 +9,7 @@
 
 #include <sys/syscall.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 
 int mknod(const char *path, mode_t mode, dev_t dev)
 {
@@ -17,6 +18,10 @@ int mknod(const char *path, mode_t mode, dev_t dev)
 	/* We must convert the value to dev_t type used by the kernel.  */
 	k_dev = (dev) & ((1ULL << 32) - 1);
 
+#ifdef __NR_mknod
 	return INLINE_SYSCALL(mknod, 3, path, mode, (unsigned int)k_dev);
+#elif defined __NR_mknodat
+	return INLINE_SYSCALL(mknodat, 4, AT_FDCWD, path, mode, (unsigned int)k_dev);
+#endif
 }
 libc_hidden_def(mknod)
diff --git a/libc/sysdeps/linux/common/not-cancel.h b/libc/sysdeps/linux/common/not-cancel.h
index 9418417..b726edd 100644
--- a/libc/sysdeps/linux/common/not-cancel.h
+++ b/libc/sysdeps/linux/common/not-cancel.h
@@ -21,10 +21,18 @@
 #include <sysdep.h>
 
 /* Uncancelable open.  */
+#ifdef __NR_open
 #define open_not_cancel(name, flags, mode) \
    INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode))
 #define open_not_cancel_2(name, flags) \
    INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
+#elif defined (__NR_openat)
+#include <fcntl.h>
+#define open_not_cancel(name, flags, mode) \
+   INLINE_SYSCALL (openat, 4, AT_FDCWD, (const char *) (name), (flags), (mode))
+#define open_not_cancel_2(name, flags) \
+   INLINE_SYSCALL (openat, 3, AT_FDCWD, (const char *) (name), (flags))
+#endif
 
 /* Uncancelable close.  */
 #define close_not_cancel(fd) \
diff --git a/libc/sysdeps/linux/common/open.c b/libc/sysdeps/linux/common/open.c
index 9fb694d..e49a000 100644
--- a/libc/sysdeps/linux/common/open.c
+++ b/libc/sysdeps/linux/common/open.c
@@ -14,9 +14,17 @@
 #include <string.h>
 #include <sys/param.h>
 
+#ifdef __NR_open
 #define __NR___syscall_open __NR_open
 static __inline__ _syscall3(int, __syscall_open, const char *, file,
 		int, flags, __kernel_mode_t, mode)
+#endif
+#ifdef __NR_openat
+#define __NR___syscall_openat __NR_openat
+static __inline__ _syscall4(int, __syscall_openat, int, fd, const char *, file,
+		int, flags, __kernel_mode_t, mode)
+#define __syscall_open(a,b,c) __syscall_openat(AT_FDCWD, (a), (b), (c))
+#endif
 
 int open(const char *file, int oflag, ...)
 {
diff --git a/libc/sysdeps/linux/common/readlink.c b/libc/sysdeps/linux/common/readlink.c
index ef9e835..26cf04f 100644
--- a/libc/sysdeps/linux/common/readlink.c
+++ b/libc/sysdeps/linux/common/readlink.c
@@ -10,5 +10,13 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
+#ifdef __NR_readlink
 _syscall3(ssize_t, readlink, const char *, path, char *, buf, size_t, bufsiz)
+#elif defined(__NR_readlinkat)
+#include <fcntl.h>
+ssize_t readlink(const char *path, char *buf, size_t bufsiz)
+{
+	return readlinkat(AT_FDCWD, path, buf, bufsiz);
+}
+#endif
 libc_hidden_def(readlink)
diff --git a/libc/sysdeps/linux/common/rename.c b/libc/sysdeps/linux/common/rename.c
index 9d8397a..1b26530 100644
--- a/libc/sysdeps/linux/common/rename.c
+++ b/libc/sysdeps/linux/common/rename.c
@@ -13,6 +13,7 @@
 #include <sys/param.h>
 #include <stdio.h>
 
+#if defined(__NR_rename)
 #define __NR___syscall_rename __NR_rename
 static __inline__ _syscall2(int, __syscall_rename, const char *, oldpath,
 		const char *, newpath)
@@ -21,4 +22,12 @@ int rename(const char * oldpath, const char * newpath)
 {
 	return __syscall_rename(oldpath, newpath);
 }
+#elif defined(__NR_renameat)
+#include <fcntl.h>
+
+int rename(const char * oldpath, const char * newpath)
+{
+	return renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
+}
+#endif
 
diff --git a/libc/sysdeps/linux/common/rmdir.c b/libc/sysdeps/linux/common/rmdir.c
index bad6654..85671ec 100644
--- a/libc/sysdeps/linux/common/rmdir.c
+++ b/libc/sysdeps/linux/common/rmdir.c
@@ -11,5 +11,14 @@
 #include <unistd.h>
 
 
+#if defined(__NR_rmdir)
 _syscall1(int, rmdir, const char *, pathname)
+#elif defined(__NR_unlinkat)
+#include <fcntl.h>
+
+int rmdir(const char * pathname)
+{
+	return unlinkat(AT_FDCWD, pathname, AT_REMOVEDIR);
+}
+#endif
 libc_hidden_def(rmdir)
diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c
index a821647..5c37ef1 100644
--- a/libc/sysdeps/linux/common/stubs.c
+++ b/libc/sysdeps/linux/common/stubs.c
@@ -403,7 +403,7 @@ make_stub(swapoff)
 make_stub(swapon)
 #endif
 
-#ifndef __NR_symlink
+#if !defined __NR_symlink && !defined __NR_symlinkat
 make_stub(symlink)
 #endif
 
@@ -443,7 +443,7 @@ make_stub(lutimes)
 # endif
 #endif
 
-#if !defined __NR_utime && !defined __NR_utimes
+#if !defined __NR_utime && !defined __NR_utimes && !defined __NR_utimensat
 /*make_stub(utime) obsoleted */
 make_stub(utimes)
 #endif
diff --git a/libc/sysdeps/linux/common/symlink.c b/libc/sysdeps/linux/common/symlink.c
index e53e8d4..c578d04 100644
--- a/libc/sysdeps/linux/common/symlink.c
+++ b/libc/sysdeps/linux/common/symlink.c
@@ -10,5 +10,13 @@
 #include <sys/syscall.h>
 #if defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K
 #include <unistd.h>
+# ifdef __NR_symlink
 _syscall2(int, symlink, const char *, oldpath, const char *, newpath)
+# elif defined __NR_symlinkat
+#include <fcntl.h>
+int symlink(const char *oldpath, const char *newpath)
+{
+	return symlinkat(oldpath, AT_FDCWD, newpath);
+}
+# endif
 #endif
diff --git a/libc/sysdeps/linux/common/unlink.c b/libc/sysdeps/linux/common/unlink.c
index 513cdd5..6ffb4c0 100644
--- a/libc/sysdeps/linux/common/unlink.c
+++ b/libc/sysdeps/linux/common/unlink.c
@@ -11,5 +11,13 @@
 #include <unistd.h>
 
 
+#if defined __NR_unlink
 _syscall1(int, unlink, const char *, pathname)
+#elif defined __NR_unlinkat
+#include <fcntl.h>
+int unlink(const char *pathname)
+{
+	return unlinkat(AT_FDCWD, pathname, 0);
+}
+#endif
 libc_hidden_def(unlink)
diff --git a/libc/sysdeps/linux/common/utimes.c b/libc/sysdeps/linux/common/utimes.c
index 99d9202..c8abcd5 100644
--- a/libc/sysdeps/linux/common/utimes.c
+++ b/libc/sysdeps/linux/common/utimes.c
@@ -14,6 +14,28 @@
 
 #ifdef __NR_utimes
 _syscall2(int, utimes, const char *, file, const struct timeval *, tvp)
+#elif defined __NR_utimensat
+#include <stdlib.h>
+#include <fcntl.h>
+
+int utimes(const char *file, const struct timeval tvp[2])
+{
+	struct timespec ts[2];
+
+	if (tvp) {
+		if (tvp[0].tv_usec >= 1000000 || tvp[0].tv_usec < 0 ||
+		    tvp[1].tv_usec >= 1000000 || tvp[1].tv_usec < 0)
+			return -EINVAL;
+
+		ts[0].tv_sec = tvp[0].tv_sec;
+		ts[0].tv_nsec = 1000 * tvp[0].tv_usec;
+		ts[1].tv_sec = tvp[1].tv_sec;
+		ts[1].tv_nsec = 1000 * tvp[1].tv_usec;
+
+		return utimensat(AT_FDCWD, file, ts, 0);
+	} else
+		return utimensat(AT_FDCWD, file, NULL, 0);
+}
 #else
 #include <stdlib.h>
 
diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h b/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h
index 80d33be..ce0a497 100644
--- a/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h
+++ b/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h
@@ -22,10 +22,18 @@
 #include <sysdep.h>
 
 /* Uncancelable open.  */
+#ifdef __NR_open
 #define open_not_cancel(name, flags, mode) \
    INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode))
 #define open_not_cancel_2(name, flags) \
    INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
+#elif defined __NR_openat
+#include <fcntl.h>
+#define open_not_cancel(name, flags, mode) \
+   INLINE_SYSCALL (openat, 4, AT_FDCWD, (const char *) (name), (flags), (mode))
+#define open_not_cancel_2(name, flags) \
+   INLINE_SYSCALL (openat, 3, AT_FDCWD, (const char *) (name), (flags))
+#endif
 
 /* Uncancelable openat.  */
 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
-- 
1.7.9.1



More information about the uClibc mailing list