diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-01-20 07:08:05 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-01-20 07:08:05 +0000 |
commit | 7c65e9001b93d5d20046bc4d50fd10fff5f4adc2 (patch) | |
tree | 38f65e2a20910e6d074fbcec137eb66853e70eaa /sysdeps/unix/sysv/linux | |
parent | 93c04024a6b900b69bbe9a70de06ac23b8273787 (diff) | |
download | glibc-7c65e9001b93d5d20046bc4d50fd10fff5f4adc2.tar.gz glibc-7c65e9001b93d5d20046bc4d50fd10fff5f4adc2.tar.xz glibc-7c65e9001b93d5d20046bc4d50fd10fff5f4adc2.zip |
* include/fcntl.h: Declare __have_atfcts.
* sysdeps/unix/sysv/linux/faccessat.c: Use syscall if available. * sysdeps/unix/sysv/linux/fchmodat.c: Likewise. * sysdeps/unix/sysv/linux/fchownat.c: Likewise. * sysdeps/unix/sysv/linux/futimesat.c: Likewise. * sysdeps/unix/sysv/linux/linkat.c: Likewise. * sysdeps/unix/sysv/linux/mkdirat.c: Likewise. * sysdeps/unix/sysv/linux/openat.c: Likewise. * sysdeps/unix/sysv/linux/readlinkat.c: Likewise. * sysdeps/unix/sysv/linux/renameat.c: Likewise. * sysdeps/unix/sysv/linux/symlinkat.c: Likewise. * sysdeps/unix/sysv/linux/unlinkat.c: Likewise. * sysdeps/unix/sysv/linux/xmknodat.c: Likewise. * sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c: Likewise. * sysdeps/unix/sysv/linux/kernel-features.h: Define __ASSUME_PSELECT, __ASSUME_PPOLL, and __ASSUME_ATFCTS if possible. * io/ppoll.c: New file. * io/Makefile (routines): Add ppoll. (CFLAGS-ppoll.c): Define. * io/Versions: Export ppoll for GLIBC_2.4. * io/sys/poll.h: Declare ppoll. * sysdeps/unix/sysv/linux/ppoll.c: New file. * misc/pselect.c: Make it possible to include this file to define the generic code as a static function. * sysdeps/unix/sysv/linux/pselect.c: New file.
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r-- | sysdeps/unix/sysv/linux/faccessat.c | 62 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/fchmodat.c | 25 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/fchownat.c | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/futimesat.c | 30 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/kernel-features.h | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/linkat.c | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mkdirat.c | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/openat.c | 68 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ppoll.c | 76 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/pselect.c | 92 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/readlinkat.c | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/renameat.c | 26 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/symlinkat.c | 24 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/unlinkat.c | 23 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c | 31 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/xmknodat.c | 37 |
16 files changed, 542 insertions, 72 deletions
diff --git a/sysdeps/unix/sysv/linux/faccessat.c b/sysdeps/unix/sysv/linux/faccessat.c index 80b3b240f7..7c28280ae6 100644 --- a/sysdeps/unix/sysv/linux/faccessat.c +++ b/sysdeps/unix/sysv/linux/faccessat.c @@ -25,8 +25,10 @@ #include <unistd.h> #include <sys/types.h> #include <alloca.h> +#include <kernel-features.h> #include <sysdep.h> + int faccessat (fd, file, mode, flag) int fd; @@ -40,42 +42,61 @@ faccessat (fd, file, mode, flag) return -1; } - char *buf = NULL; + int result; - if (fd != AT_FDCWD && file[0] != '/') +#ifdef __NR_faccessat + if (flag == 0 +# ifndef __ASSUME_ATFCTS + && __have_atfcts >= 0 +# endif + ) { - size_t filelen = strlen (file); - static const char procfd[] = "/proc/self/fd/%d/%s"; - /* Buffer for the path name we are going to use. It consists of - - the string /proc/self/fd/ - - the file descriptor number - - the file name provided. - The final NUL is included in the sizeof. A bit of overhead - due to the format elements compensates for possible negative - numbers. */ - size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen; - buf = alloca (buflen); - - __snprintf (buf, buflen, procfd, fd, file); - file = buf; + result = INLINE_SYSCALL (faccessat, 3, fd, file, mode); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; } +#endif +#ifndef __ASSUME_ATFCTS if ((!(flag & AT_EACCESS) || ! __libc_enable_secure) -#ifndef __NR_laccess /* Linux so far has no laccess syscall. */ +# ifndef __NR_laccess /* Linux so far has no laccess syscall. */ && !(flag & AT_SYMLINK_NOFOLLOW) -#endif +# endif ) { /* If we are not set-uid or set-gid, access does the same. */ + char *buf = NULL; + + if (fd != AT_FDCWD && file[0] != '/') + { + size_t filelen = strlen (file); + static const char procfd[] = "/proc/self/fd/%d/%s"; + /* Buffer for the path name we are going to use. It consists of + - the string /proc/self/fd/ + - the file descriptor number + - the file name provided. + The final NUL is included in the sizeof. A bit of overhead + due to the format elements compensates for possible negative + numbers. */ + size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen; + buf = alloca (buflen); + + __snprintf (buf, buflen, procfd, fd, file); + file = buf; + } int result; INTERNAL_SYSCALL_DECL (err); -#ifdef __NR_laccess +# ifdef __NR_laccess if (flag & AT_SYMLINK_NOFOLLOW) result = INTERNAL_SYSCALL (laccess, err, 2, file, mode); else -#endif +# endif result = INTERNAL_SYSCALL (access, err, 2, file, mode); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) @@ -86,6 +107,7 @@ faccessat (fd, file, mode, flag) return result; } +#endif struct stat64 stats; if (fstatat64 (fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW)) diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c index de35e4376f..8b420153f1 100644 --- a/sysdeps/unix/sysv/linux/fchmodat.c +++ b/sysdeps/unix/sysv/linux/fchmodat.c @@ -25,6 +25,7 @@ #include <unistd.h> #include <sys/types.h> #include <alloca.h> +#include <kernel-features.h> #include <sysdep.h> int @@ -47,6 +48,24 @@ fchmodat (fd, file, mode, flag) } #endif + int result; + +#ifdef __NR_fchmodat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (fchmodat, 3, fd, file, mode); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (fd != AT_FDCWD && file[0] != '/') @@ -67,14 +86,13 @@ fchmodat (fd, file, mode, flag) file = buf; } - int result; INTERNAL_SYSCALL_DECL (err); -#ifdef __NR_lchmod +# ifdef __NR_lchmod if (flag & AT_SYMLINK_NOFOLLOW) result = INTERNAL_SYSCALL (lchmod, err, 2, file, mode); else -#endif +# endif result = INTERNAL_SYSCALL (chmod, err, 2, file, mode); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) @@ -84,4 +102,5 @@ fchmodat (fd, file, mode, flag) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/fchownat.c b/sysdeps/unix/sysv/linux/fchownat.c index 10d87e87fc..0f731775b3 100644 --- a/sysdeps/unix/sysv/linux/fchownat.c +++ b/sysdeps/unix/sysv/linux/fchownat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -25,6 +25,8 @@ #include <sys/types.h> #include <alloca.h> #include <sysdep.h> +#include <kernel-features.h> + /* Change the owner and group of FILE. */ int @@ -35,6 +37,24 @@ fchownat (fd, file, owner, group, flag) gid_t group; int flag; { + int result; + +#ifdef __NR_fchownat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS if (flag & ~AT_SYMLINK_NOFOLLOW) { __set_errno (EINVAL); @@ -61,7 +81,6 @@ fchownat (fd, file, owner, group, flag) file = buf; } - int result; INTERNAL_SYSCALL_DECL (err); if (flag & AT_SYMLINK_NOFOLLOW) @@ -76,4 +95,5 @@ fchownat (fd, file, owner, group, flag) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/futimesat.c b/sysdeps/unix/sysv/linux/futimesat.c index be148b8d7a..514f456927 100644 --- a/sysdeps/unix/sysv/linux/futimesat.c +++ b/sysdeps/unix/sysv/linux/futimesat.c @@ -35,6 +35,24 @@ futimesat (fd, file, tvp) const char *file; const struct timeval tvp[2]; { + int result; + +#ifdef __NR_futimesat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (futimesat, 3, fd, file, tvp); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (file == NULL) @@ -70,24 +88,23 @@ futimesat (fd, file, tvp) file = buf; } - int result; INTERNAL_SYSCALL_DECL (err); -#ifdef __NR_utimes +# ifdef __NR_utimes result = INTERNAL_SYSCALL (utimes, err, 2, file, tvp); if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return result; -# ifndef __ASSUME_UTIMES +# ifndef __ASSUME_UTIMES if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS) goto fail; +# endif # endif -#endif /* The utimes() syscall does not exist or is not available in the used kernel. Use utime(). For this we have to convert to the data format utime() expects. */ -#ifndef __ASSUME_UTIMES +# ifndef __ASSUME_UTIMES struct utimbuf tmp; struct utimbuf *times; @@ -105,9 +122,10 @@ futimesat (fd, file, tvp) return result; fail: -#endif +# endif __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf); return -1; +#endif } diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 594af419c8..837a1c14fb 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -463,3 +463,27 @@ #if __LINUX_KERNEL_VERSION >= 0x02041a # define __ASSUME_TMPFS_NAME 1 #endif + +/* pselect was introduced just after 2.6.16-rc1. Due to the way the + kernel versions are advertised we can only rely on 2.6.17 to have + the code. */ +#if __LINUX_KERNEL_VERSION >= 0x020611 \ + && (defined __i386__ || defined __powerpc__) +# define __ASSUME_PSELECT 1 +#endif + +/* ppoll was introduced just after 2.6.16-rc1. Due to the way the + kernel versions are advertised we can only rely on 2.6.17 to have + the code. */ +#if __LINUX_KERNEL_VERSION >= 0x020611 \ + && (defined __i386__ || defined __powerpc__) +# define __ASSUME_PPOLL 1 +#endif + +/* The *at syscalls were introduced just after 2.6.16-rc1. Due to the way the + kernel versions are advertised we can only rely on 2.6.17 to have + the code. */ +#if __LINUX_KERNEL_VERSION >= 0x020611 \ + && (defined __i386__ || defined __x86_64__) +# define __ASSUME_ATFCTS 1 +#endif diff --git a/sysdeps/unix/sysv/linux/linkat.c b/sysdeps/unix/sysv/linux/linkat.c index 8ebff74215..5485b3f61c 100644 --- a/sysdeps/unix/sysv/linux/linkat.c +++ b/sysdeps/unix/sysv/linux/linkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -22,6 +22,7 @@ #include <stdio.h> #include <sysdep.h> #include <unistd.h> +#include <kernel-features.h> /* Make a link to FROM named TO but relative paths in TO and FROM are @@ -33,6 +34,24 @@ linkat (fromfd, from, tofd, to) int tofd; const char *to; { + int result; + +#ifdef __NR_linkat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (linkat, 4, fromfd, from, tofd, to); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS static const char procfd[] = "/proc/self/fd/%d/%s"; char *buffrom = NULL; @@ -74,7 +93,7 @@ linkat (fromfd, from, tofd, to) INTERNAL_SYSCALL_DECL (err); - int result = INTERNAL_SYSCALL (link, err, 2, from, to); + result = INTERNAL_SYSCALL (link, err, 2, from, to); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) { @@ -84,4 +103,5 @@ linkat (fromfd, from, tofd, to) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/mkdirat.c b/sysdeps/unix/sysv/linux/mkdirat.c index 367441b05b..3c190085ce 100644 --- a/sysdeps/unix/sysv/linux/mkdirat.c +++ b/sysdeps/unix/sysv/linux/mkdirat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -22,6 +22,7 @@ #include <stdio.h> #include <string.h> #include <sys/stat.h> +#include <kernel-features.h> #include <sysdep-cancel.h> @@ -33,6 +34,24 @@ mkdirat (fd, file, mode) const char *file; mode_t mode; { + int res; + +#ifdef __NR_mkdirat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + res = INLINE_SYSCALL (mkdirat, 3, fd, file, mode); +# ifndef __ASSUME_ATFCTS + if (res == -1 && res == ENOSYS) + __have_atfcts = -1; + else +# endif + return res; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (fd != AT_FDCWD && file[0] != '/') @@ -54,7 +73,7 @@ mkdirat (fd, file, mode) } INTERNAL_SYSCALL_DECL (err); - int res = INTERNAL_SYSCALL (mkdir, err, 2, file, mode); + res = INTERNAL_SYSCALL (mkdir, err, 2, file, mode); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) { @@ -63,4 +82,5 @@ mkdirat (fd, file, mode) } return res; +#endif } diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c index d5d976cbc4..7423800a13 100644 --- a/sysdeps/unix/sysv/linux/openat.c +++ b/sysdeps/unix/sysv/linux/openat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -23,12 +23,12 @@ #include <stdio.h> #include <string.h> #include <sys/stat.h> +#include <kernel-features.h> #include <sysdep-cancel.h> -#ifndef OPENAT +#if !defined OPENAT && !defined __ASSUME_ATFCTS # define OPENAT openat -# define MORE_OFLAGS 0 void @@ -53,6 +53,8 @@ __atfct_seterrno (int errval, int fd, const char *buf) __set_errno (errval); } + +int __have_atfcts; #endif /* Open FILE with access OFLAG. Interpret relative paths relative to @@ -64,6 +66,49 @@ OPENAT (fd, file, oflag) const char *file; int oflag; { + mode_t mode = 0; + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, mode_t); + va_end (arg); + } + + /* We have to add the O_LARGEFILE flag for openat64. */ +#ifdef MORE_OFLAGS + oflag |= MORE_OFLAGS; +#endif + + INTERNAL_SYSCALL_DECL (err); + int res; + +#ifdef __NR_openat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + if (SINGLE_THREAD_P) + res = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode); + else + { + int oldtype = LIBC_CANCEL_ASYNC (); + + res = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode); + + LIBC_CANCEL_RESET (oldtype); + } + +# ifndef __ASSUME_ATFCTS + if (res == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return res; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (fd != AT_FDCWD && file[0] != '/') @@ -84,25 +129,13 @@ OPENAT (fd, file, oflag) file = buf; } - mode_t mode = 0; - if (oflag & O_CREAT) - { - va_list arg; - va_start (arg, oflag); - mode = va_arg (arg, mode_t); - va_end (arg); - } - - INTERNAL_SYSCALL_DECL (err); - int res; - if (SINGLE_THREAD_P) - res = INTERNAL_SYSCALL (open, err, 3, file, oflag | MORE_OFLAGS, mode); + res = INTERNAL_SYSCALL (open, err, 3, file, oflag, mode); else { int oldtype = LIBC_CANCEL_ASYNC (); - res = INTERNAL_SYSCALL (open, err, 3, file, oflag | MORE_OFLAGS, mode); + res = INTERNAL_SYSCALL (open, err, 3, file, oflag, mode); LIBC_CANCEL_RESET (oldtype); } @@ -114,4 +147,5 @@ OPENAT (fd, file, oflag) } return res; +#endif } diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c new file mode 100644 index 0000000000..cfc86ba806 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ppoll.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2006. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <time.h> +#include <sys/poll.h> +#include <kernel-features.h> +#include <sysdep-cancel.h> + + +#ifdef __NR_ppoll +static int __generic_ppoll (struct pollfd *fds, nfds_t nfds, + const struct timespec *timeout, + const sigset_t *sigmask); + + +int +ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, + const sigset_t *sigmask) +{ + /* The Linux kernel can in some situations update the timeout value. + We do not want that so use a local variable. */ + struct timespec tval; + if (timeout != NULL) + { + tval = *timeout; + timeout = &tval; + } + + int result; + + if (SINGLE_THREAD_P) + result = INLINE_SYSCALL (ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8); + else + { + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (ppoll, 5, fds, nfds, timeout, sigmask, + _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + } + +# ifndef __ASSUME_PPOLL + if (result == -1 && errno == ENOSYS) + result = __generic_ppoll (fds, nfds, timeout, sigmask); +# endif + + return result; +} + +# ifndef __ASSUME_PPOLL +# define ppoll static __generic_ppoll +# endif +#endif + +#ifndef __ASSUME_PPOLL +# include <io/ppoll.c> +#endif diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c new file mode 100644 index 0000000000..6fd4d3e071 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pselect.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2006. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <time.h> +#include <sys/poll.h> +#include <kernel-features.h> +#include <sysdep-cancel.h> + + +#ifdef __NR_pselect6 +static int __generic_pselect (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, + const struct timespec *timeout, + const sigset_t *sigmask) + + +int +__pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + /* The Linux kernel can in some situations update the timeout value. + We do not want that so use a local variable. */ + struct timespec tval; + if (timeout != NULL) + { + tval = *timeout; + timeout = &tval; + } + + /* Note: the system call expects 7 values but on most architectures + we can only pass in 6 directly. If there is an architecture with + support for more parameters a new version of this file needs to + be created. */ + struct + { + sigset_t *ss; + size_t ss_len; + } data; + + data.ss = sigmask; + data.ss_len = _NSIG / 8; + + int result; + + if (SINGLE_THREAD_P) + result = INLINE_SYSCALL (pselect6, 6, nfds, readfds, writefds, exceptfds, + timeout, &data); + else + { + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pselect6, 6, nfds, readfds, writefds, exceptfds, + timeout, &data); + + LIBC_CANCEL_RESET (oldtype); + } + +# ifndef __ASSUME_PSELECT + if (result == -1 && errno == ENOSYS) + result = __generic_pselect (nfds, readfds, writefds, exceptfds, timeout, + sigmask); +# endif + + return result; +} + +# ifndef __ASSUME_PSELECT +# define __pselect static __generic_pselect +# endif +#endif + +#ifndef __ASSUME_PSELECT +# include <misc/pselect.c> +#endif diff --git a/sysdeps/unix/sysv/linux/readlinkat.c b/sysdeps/unix/sysv/linux/readlinkat.c index 42c3877bd7..c2f21ee4ca 100644 --- a/sysdeps/unix/sysv/linux/readlinkat.c +++ b/sysdeps/unix/sysv/linux/readlinkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -24,6 +24,7 @@ #include <string.h> #include <sysdep.h> #include <unistd.h> +#include <kernel-features.h> /* Read the contents of the symbolic link PATH relative to FD into no @@ -35,6 +36,24 @@ readlinkat (fd, path, buf, len) char *buf; size_t len; { + int result; + +#ifdef __NR_readlinkat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (readlinkat, 4, fd, path, buf, len); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS char *pathbuf = NULL; if (fd != AT_FDCWD && path[0] != '/') @@ -57,7 +76,7 @@ readlinkat (fd, path, buf, len) INTERNAL_SYSCALL_DECL (err); - int result = INTERNAL_SYSCALL (readlink, err, 3, path, buf, len); + result = INTERNAL_SYSCALL (readlink, err, 3, path, buf, len); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) { @@ -66,4 +85,5 @@ readlinkat (fd, path, buf, len) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/renameat.c b/sysdeps/unix/sysv/linux/renameat.c index 849c67b5d6..bc8ced42df 100644 --- a/sysdeps/unix/sysv/linux/renameat.c +++ b/sysdeps/unix/sysv/linux/renameat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -20,9 +20,11 @@ #include <fcntl.h> #include <stdio.h> #include <string.h> +#include <kernel-features.h> #include <sysdep.h> +#ifndef __ASSUME_ATFCTS void attribute_hidden __atfct_seterrno_2 (int errval, int fd1, const char *buf1, int fd2, @@ -67,6 +69,7 @@ __atfct_seterrno_2 (int errval, int fd1, const char *buf1, int fd2, out: __set_errno (errval); } +#endif /* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */ @@ -77,6 +80,24 @@ renameat (oldfd, old, newfd, new) int newfd; const char *new; { + int result; + +#ifdef __NR_renameat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (renameat, 4, oldfd, old, newfd, new); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS static const char procfd[] = "/proc/self/fd/%d/%s"; char *bufold = NULL; @@ -118,7 +139,7 @@ renameat (oldfd, old, newfd, new) INTERNAL_SYSCALL_DECL (err); - int result = INTERNAL_SYSCALL (rename, err, 2, old, new); + result = INTERNAL_SYSCALL (rename, err, 2, old, new); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) { @@ -128,4 +149,5 @@ renameat (oldfd, old, newfd, new) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/symlinkat.c b/sysdeps/unix/sysv/linux/symlinkat.c index 211b49c299..4cfc924bfc 100644 --- a/sysdeps/unix/sysv/linux/symlinkat.c +++ b/sysdeps/unix/sysv/linux/symlinkat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -24,6 +24,7 @@ #include <string.h> #include <sysdep.h> #include <unistd.h> +#include <kernel-features.h> /* Make a symbolic link to FROM named TO relative to TOFD. */ @@ -33,6 +34,24 @@ symlinkat (from, tofd, to) int tofd; const char *to; { + int result; + +#ifdef __NR_symlinkat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (symlinkat, 3, from, tofd, to); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (tofd != AT_FDCWD && to[0] != '/') @@ -55,7 +74,7 @@ symlinkat (from, tofd, to) INTERNAL_SYSCALL_DECL (err); - int result = INTERNAL_SYSCALL (symlink, err, 2, from, to); + result = INTERNAL_SYSCALL (symlink, err, 2, from, to); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) { @@ -64,4 +83,5 @@ symlinkat (from, tofd, to) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/unlinkat.c b/sysdeps/unix/sysv/linux/unlinkat.c index 821029f5e5..0a07a8a875 100644 --- a/sysdeps/unix/sysv/linux/unlinkat.c +++ b/sysdeps/unix/sysv/linux/unlinkat.c @@ -1,5 +1,5 @@ /* unlinkat -- Remove a link by relative name. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 @@ -25,6 +25,7 @@ #include <string.h> #include <sysdep.h> #include <unistd.h> +#include <kernel-features.h> /* Remove the link named NAME. */ @@ -34,6 +35,24 @@ unlinkat (fd, file, flag) const char *file; int flag; { + int result; + +#ifdef __NR_unlinkat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + result = INLINE_SYSCALL (unlinkat, 3, fd, file, flag); +# ifndef __ASSUME_ATFCTS + if (result == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return result; + } +#endif + +#ifndef __ASSUME_ATFCTS if (flag & ~AT_REMOVEDIR) { __set_errno (EINVAL); @@ -60,7 +79,6 @@ unlinkat (fd, file, flag) file = buf; } - int result; INTERNAL_SYSCALL_DECL (err); if (flag & AT_REMOVEDIR) @@ -75,4 +93,5 @@ unlinkat (fd, file, flag) } return result; +#endif } diff --git a/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c b/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c index 159301c172..0c37495575 100644 --- a/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c +++ b/sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c @@ -28,15 +28,40 @@ #include <sys/stat.h> #include <sysdep.h> +#include <kernel-features.h> #include <sys/syscall.h> #include <bp-checks.h> + /* Get information about the file NAME relative to FD in ST. */ int __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) { - if ((vers != _STAT_VER_KERNEL && vers != _STAT_VER_LINUX) - || (flag & ~AT_SYMLINK_NOFOLLOW) != 0) + if (vers != _STAT_VER_KERNEL && vers != _STAT_VER_LINUX) + { + __set_errno (EINVAL); + return -1; + } + + int res; + +#ifdef __NR_newfstatat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + res = INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag); +# ifndef __ASSUME_ATFCTS + if (res == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return res; + } +#endif + +#ifndef __ASSUME_ATFCTS + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) { __set_errno (EINVAL); return -1; @@ -63,7 +88,6 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) } INTERNAL_SYSCALL_DECL (err); - int res; if (flag & AT_SYMLINK_NOFOLLOW) res = INTERNAL_SYSCALL (lstat, err, 2, file, CHECK_1 (st)); @@ -77,6 +101,7 @@ __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) } return res; +#endif } #undef __fxstatat64 strong_alias (__fxstatat, __fxstatat64); diff --git a/sysdeps/unix/sysv/linux/xmknodat.c b/sysdeps/unix/sysv/linux/xmknodat.c index 9332ae683e..d6cb4ed1be 100644 --- a/sysdeps/unix/sysv/linux/xmknodat.c +++ b/sysdeps/unix/sysv/linux/xmknodat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -25,9 +25,11 @@ #include <sys/sysmacros.h> #include <sysdep.h> +#include <kernel-features.h> #include <sys/syscall.h> #include <bp-checks.h> + /* Create a device file named PATH relative to FD, with permission and special bits MODE and device number DEV (which can be constructed from major and minor device numbers with the `makedev' macro above). */ @@ -40,6 +42,30 @@ __xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t *dev) return -1; } + /* We must convert the value to dev_t type used by the kernel. */ + unsigned long long int k_dev = (*dev) & ((1ULL << 32) - 1); + if (k_dev != *dev) + { + __set_errno (EINVAL); + return -1; + } + +#ifdef __NR_mknodat +# ifndef __ASSUME_ATFCTS + if (__have_atfcts >= 0) +# endif + { + int res = INLINE_SYSCALL (mknodat, 4, fd, file, mode, k_dev); +# ifndef __ASSUME_ATFCTS + if (res == -1 && errno == ENOSYS) + __have_atfcts = -1; + else +# endif + return res; + } +#endif + +#ifndef __ASSUME_ATFCTS char *buf = NULL; if (fd != AT_FDCWD && file[0] != '/') @@ -60,16 +86,9 @@ __xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t *dev) file = buf; } - /* We must convert the value to dev_t type used by the kernel. */ - unsigned long long int k_dev = (*dev) & ((1ULL << 32) - 1); - if (k_dev != *dev) - { - __set_errno (EINVAL); - return -1; - } - return INLINE_SYSCALL (mknod, 3, CHECK_STRING (file), mode, (unsigned int) k_dev); +#endif } libc_hidden_def (__xmknodat) |