diff options
author | Ulrich Drepper <drepper@redhat.com> | 1999-05-26 23:37:38 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1999-05-26 23:37:38 +0000 |
commit | 958f238f3619373d3dbc106d3cda3c467b3419b1 (patch) | |
tree | 9d15d47658aeaae08ee7e5e5e9d4a63d034caa49 /sysdeps | |
parent | 475e390e80a950a8746dc0b88341742dc99014e4 (diff) | |
download | glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.tar glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.tar.gz glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.tar.bz2 glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.zip |
Update.
1999-05-26 Ulrich Drepper <drepper@cygnus.com>
* config.h.in: Add __LINUX_KERNEL_VERSION.
* configure.in: Recognize --enable-kernel.
* sysdeps/unix/sysv/linux/configure.in: Check for correct kernel
headers if --enable-kernel is given and set __LINUX_KERNEL_VERSION
appropriately.
* sysdeps/unix/sysv/linux/init-first.c: If minimal kernel version is
given perform runtime test.
* sysdeps/unix/sysv/linux/kernel-features.h: New file.
* sysdeps/unix/sysv/linux/getcwd.c: Elide compatibility code if
minimal supported kernel is known to have the feature.
* sysdeps/unix/sysv/linux/poll.c: Likewise.
* sysdeps/unix/sysv/linux/pread.c: Likewise.
* sysdeps/unix/sysv/linux/pread64.c: Likewise.
* sysdeps/unix/sysv/linux/pwrite.c: Likewise.
* sysdeps/unix/sysv/linux/pwrite64.c: Likewise.
* sysdeps/unix/sysv/linux/seteuid.c: Likewise.
* sysdeps/unix/sysv/linux/sigaction.c: Likewise.
* sysdeps/unix/sysv/linux/sigprocmask.c: Likewise.
* sysdeps/unix/sysv/linux/sigsuspend.c: Likewise.
* sysdeps/unix/sysv/linux/testrtsig.h: Likewise.
* sysdeps/unix/sysv/linux/i386/chown.c: Likewise.
* sysdeps/unix/sysv/linux/i386/pread.c: Likewise.
* sysdeps/unix/sysv/linux/i386/pread64.c: Likewise.
* sysdeps/unix/sysv/linux/i386/pwrite.c: Likewise.
* sysdeps/unix/sysv/linux/i386/pwrite64.c: Likewise.
* sysdeps/unix/sysv/linux/sysctl.c: Add __sysctl alias.
Diffstat (limited to 'sysdeps')
22 files changed, 440 insertions, 71 deletions
diff --git a/sysdeps/unix/sysv/linux/configure b/sysdeps/unix/sysv/linux/configure index bf5e797d31..f5d994b1c7 100644 --- a/sysdeps/unix/sysv/linux/configure +++ b/sysdeps/unix/sysv/linux/configure @@ -13,7 +13,7 @@ if test -n "$sysheaders"; then fi echo $ac_n "checking installed Linux kernel header files""... $ac_c" 1>&6 echo "configure:16: checking installed Linux kernel header files" >&5 -if eval "test \"`echo '$''{'libc_cv_linux2010'+set}'`\" = set"; then +if eval "test \"\${libc_cv_linux2010+set}\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF @@ -49,6 +49,35 @@ make sure that file was built correctly when installing the kernel header files. To use kernel headers not from /usr/include/linux, use the configure option --with-headers." 1>&2; exit 1; } fi + +# If the user gave a minimal version number test whether the available +# kernel headers are young enough. +if test -n "$minimum_kernel"; then + echo $ac_n "checking for kernel header at least $minimum_kernel""... $ac_c" 1>&6 +echo "configure:58: checking for kernel header at least $minimum_kernel" >&5 + decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\(\([0-9]*\)\|\).*/(\1 * 65536 + \2 * 256 + \3)/'`; + cat > conftest.$ac_ext <<EOF +#include <linux/version.h> +int main() { +#if LINUX_VERSION_CODE < $decnum +eat flaming death +#endif +; return 0; } +EOF + if { (eval echo configure:30: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + cat >> confdefs.h <<EOF +#define __LINUX_KERNEL_VERSION $decnum +EOF + + echo "$ac_t""ok" 1>&6 + else + echo "$ac_t""too old!" 1>&6 + { echo "configure: error: *** The available kernel headers are not at least as old as the requested +*** compatible kernel version" 1>&2; exit 1; } + fi + rm -f conftest* +fi + if test -n "$sysheaders"; then CFLAGS=$OLD_CFLAGS fi @@ -135,7 +164,7 @@ if test $host = $build; then ac_prefix=$ac_default_prefix fi echo $ac_n "checking for symlinks in ${ac_prefix}/include""... $ac_c" 1>&6 -echo "configure:131: checking for symlinks in ${ac_prefix}/include" >&5 +echo "configure:168: checking for symlinks in ${ac_prefix}/include" >&5 ac_message= if test -L ${ac_prefix}/include/net; then ac_message="$ac_message diff --git a/sysdeps/unix/sysv/linux/configure.in b/sysdeps/unix/sysv/linux/configure.in index 2c425c5f25..021b4731eb 100644 --- a/sysdeps/unix/sysv/linux/configure.in +++ b/sysdeps/unix/sysv/linux/configure.in @@ -34,6 +34,33 @@ make sure that file was built correctly when installing the kernel header files. To use kernel headers not from /usr/include/linux, use the configure option --with-headers.]) fi + +# If the user gave a minimal version number test whether the available +# kernel headers are young enough. +if test -n "$minimum_kernel"; then + AC_MSG_CHECKING(for kernel header at least $minimum_kernel) +changequote(,)dnl + decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\(\([0-9]*\)\|\).*/(\1 * 65536 + \2 * 256 + \3)/'`; +changequote([,])dnl + cat > conftest.$ac_ext <<EOF +#include <linux/version.h> +int main() { +#if LINUX_VERSION_CODE < $decnum +eat flaming death +#endif +; return 0; } +EOF + if { (eval echo configure:30: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + AC_DEFINE_UNQUOTED(__LINUX_KERNEL_VERSION, $decnum) + AC_MSG_RESULT(ok) + else + AC_MSG_RESULT(too old!) + AC_MSG_ERROR([*** The available kernel headers are not at least as old as the requested +*** compatible kernel version]) + fi + rm -f conftest* +fi + if test -n "$sysheaders"; then CFLAGS=$OLD_CFLAGS fi diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c index fe28e2d894..cc7b987f9b 100644 --- a/sysdeps/unix/sysv/linux/getcwd.c +++ b/sysdeps/unix/sysv/linux/getcwd.c @@ -18,6 +18,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <errno.h> #include <limits.h> #include <stdlib.h> @@ -26,7 +27,19 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "kernel-features.h" + +#if __ASSUME_GETCWD_SYSCALL > 0 +/* Kernel 2.1.92 introduced a third way to get the current working + directory: a syscall. We've got to be careful that even when + compiling under 2.1.92+ the libc still runs under older kernels. */ +extern int __syscall_getcwd (char *buf, unsigned long size); +# define no_syscall_getcwd 0 +# define have_new_dcache 1 +/* This is a trick since we don't define generic_getcwd. */ +# define generic_getcwd getcwd +#else /* The "proc" filesystem provides an easy method to retrieve the value. For each process, the corresponding directory contains a symbolic link named `cwd'. Reading the content of this link immediate gives us the @@ -34,16 +47,17 @@ the proc filesystem mounted. Use the POSIX implementation in this case. */ static char *generic_getcwd (char *buf, size_t size) internal_function; -#ifdef __NR_getcwd +# if __NR_getcwd /* Kernel 2.1.92 introduced a third way to get the current working directory: a syscall. We've got to be careful that even when compiling under 2.1.92+ the libc still runs under older kernels. */ extern int __syscall_getcwd (char *buf, unsigned long size); static int no_syscall_getcwd; static int have_new_dcache; -#else -# define no_syscall_getcwd 1 +# else +# define no_syscall_getcwd 1 static int have_new_dcache = 1; +# endif #endif char * @@ -80,7 +94,7 @@ __getcwd (char *buf, size_t size) save_errno = errno; -#ifdef __NR_getcwd +#if defined __NR_getcwd || __LINUX_GETCWD_SYSCALL > 0 if (!no_syscall_getcwd) { int retval; @@ -98,6 +112,16 @@ __getcwd (char *buf, size_t size) return buf; } +# if __ASSUME_GETCWD_SYSCALL + /* It should never happen that the `getcwd' syscall failed because + the buffer is too small if we allocated the buffer outself. */ + assert (errno != ERANGE || buf != NULL); + + if (buf == NULL) + free (path); + + return NULL; +# else if (errno == ENOSYS) { no_syscall_getcwd = 1; @@ -111,6 +135,7 @@ __getcwd (char *buf, size_t size) } __set_errno (save_errno); +# endif } #endif @@ -136,14 +161,18 @@ __getcwd (char *buf, size_t size) } return buf; } +#ifndef have_new_dcache else have_new_dcache = 0; +#endif } +#if __ASSUME_GETCWD_SYSCALL == 0 /* Set to have_new_dcache only if error indicates that proc doesn't exist. */ if (errno != EACCES && errno != ENAMETOOLONG) have_new_dcache = 0; +#endif /* Something went wrong. Restore the error number and use the generic version. */ @@ -165,7 +194,9 @@ __getcwd (char *buf, size_t size) } weak_alias (__getcwd, getcwd) +#if __ASSUME_GETCWD_SYSCALL == 0 /* Get the code for the generic version. */ -#define GETCWD_RETURN_TYPE static char * internal_function -#define __getcwd generic_getcwd -#include <sysdeps/posix/getcwd.c> +# define GETCWD_RETURN_TYPE static char * internal_function +# define __getcwd generic_getcwd +# include <sysdeps/posix/getcwd.c> +#endif diff --git a/sysdeps/unix/sysv/linux/i386/chown.c b/sysdeps/unix/sysv/linux/i386/chown.c index 3776a4490c..9ab03e3a7c 100644 --- a/sysdeps/unix/sysv/linux/i386/chown.c +++ b/sysdeps/unix/sysv/linux/i386/chown.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999 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,8 @@ #include <sysdep.h> #include <sys/syscall.h> +#include <kernel-features.h> + /* In Linux 2.1.x the chown functions have been changed. A new function lchown was introduced. The new chown now follows symlinks - the old chown and the @@ -34,14 +36,15 @@ extern int __syscall_chown (const char *__file, uid_t __owner, gid_t __group); -#ifdef __NR_lchown +#if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0 /* Running under Linux > 2.1.80. */ -static int __libc_old_chown; int __real_chown (const char *file, uid_t owner, gid_t group) { +# if __ASSUME_LCHOWN_SYSCALL == 0 + static int __libc_old_chown; int result; if (!__libc_old_chown) @@ -57,11 +60,14 @@ __real_chown (const char *file, uid_t owner, gid_t group) } return __lchown (file, owner, group); +# else + return INLINE_SYSCALL (chown, 3, file, owner, group); +# endif } #endif -#ifndef __NR_lchown +#if !defined __NR_lchown && __ASSUME_LCHOWN_SYSCALL == 0 /* Compiling under older kernels. */ int __chown_is_lchown (const char *file, uid_t owner, gid_t group) diff --git a/sysdeps/unix/sysv/linux/i386/pread.c b/sysdeps/unix/sysv/linux/i386/pread.c index 4c2f18d3f2..5745648306 100644 --- a/sysdeps/unix/sysv/linux/i386/pread.c +++ b/sysdeps/unix/sysv/linux/i386/pread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,10 +23,14 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pread +#include <kernel-features.h> +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 static ssize_t __emulate_pread (int fd, void *buf, size_t count, off_t offset) internal_function; +# endif ssize_t @@ -40,16 +44,21 @@ __pread (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pread, 5, fd, buf, count, offset, 0); +# if __ASSUME_PREAD_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pread (fd, buf, count, offset); +# endif return result; } weak_alias (__pread, pread) -#define __pread(fd, buf, count, offset) \ +# define __pread(fd, buf, count, offset) \ static internal_function __emulate_pread (fd, buf, count, offset) #endif -#include <sysdeps/posix/pread.c> + +#if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread.c> +#endif diff --git a/sysdeps/unix/sysv/linux/i386/pread64.c b/sysdeps/unix/sysv/linux/i386/pread64.c index 8cfb3c0a43..aa0c54d385 100644 --- a/sysdeps/unix/sysv/linux/i386/pread64.c +++ b/sysdeps/unix/sysv/linux/i386/pread64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,13 +23,14 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pread +#include <kernel-features.h> -extern ssize_t __syscall_pread64 (int fd, void *buf, size_t count, - off_t offset_hi, off_t offset_lo); +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 +# if __ASSUME_PREAD_SYSCALL == 0 static ssize_t __emulate_pread64 (int fd, void *buf, size_t count, off64_t offset) internal_function; +# endif ssize_t @@ -45,16 +46,21 @@ __pread64 (fd, buf, count, offset) result = INLINE_SYSCALL (pread, 5, fd, buf, count, (off_t) (offset & 0xffffffff), (off_t) (offset >> 32)); +# if __ASSUME_PREAD_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pread64 (fd, buf, count, offset); +# endif return result; } weak_alias (__pread64, pread64) -#define __pread64(fd, buf, count, offset) \ +# define __pread64(fd, buf, count, offset) \ static internal_function __emulate_pread64 (fd, buf, count, offset) #endif -#include <sysdeps/posix/pread64.c> + +#if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/i386/pwrite.c b/sysdeps/unix/sysv/linux/i386/pwrite.c index a1fc99f156..90eee5b4e1 100644 --- a/sysdeps/unix/sysv/linux/i386/pwrite.c +++ b/sysdeps/unix/sysv/linux/i386/pwrite.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,10 +23,14 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pwrite +#include <kernel-features.h> +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count, off_t offset) internal_function; +# endif ssize_t @@ -40,16 +44,21 @@ __pwrite (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pwrite, 5, fd, buf, count, offset, 0); +# if __ASSUME_PWRITE_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pwrite (fd, buf, count, offset); +# endif return result; } weak_alias (__pwrite, pwrite) -#define __pwrite(fd, buf, count, offset) \ +# define __pwrite(fd, buf, count, offset) \ static internal_function __emulate_pwrite (fd, buf, count, offset) #endif -#include <sysdeps/posix/pwrite.c> + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite.c> +#endif diff --git a/sysdeps/unix/sysv/linux/i386/pwrite64.c b/sysdeps/unix/sysv/linux/i386/pwrite64.c index 7a5d665de3..500cd7cef3 100644 --- a/sysdeps/unix/sysv/linux/i386/pwrite64.c +++ b/sysdeps/unix/sysv/linux/i386/pwrite64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,10 +23,14 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pwrite +#include <kernel-features.h> +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count, off64_t offset) internal_function; +# endif ssize_t @@ -42,16 +46,21 @@ __pwrite64 (fd, buf, count, offset) result = INLINE_SYSCALL (pwrite, 5, fd, buf, count, (off_t) (offset & 0xffffffff), (off_t) (offset >> 32)); +# if __ASSUME_PWRITE_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pwrite64 (fd, buf, count, offset); +# endif return result; } weak_alias (__pwrite64, pwrite64) -#define __pwrite64(fd, buf, count, offset) \ +# define __pwrite64(fd, buf, count, offset) \ static internal_function __emulate_pwrite64 (fd, buf, count, offset) #endif -#include <sysdeps/posix/pwrite64.c> + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c index 01395baf75..b8ee2bdf14 100644 --- a/sysdeps/unix/sysv/linux/init-first.c +++ b/sysdeps/unix/sysv/linux/init-first.c @@ -1,5 +1,5 @@ /* Initialization code run first thing by the ELF startup code. Linux version. - Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 1999 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 @@ -17,12 +17,17 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <stdio.h> +#include <fcntl.h> #include <unistd.h> #include <sysdep.h> #include <fpu_control.h> #include <linux/personality.h> #include <init-first.h> +#include <sys/param.h> +#include <sys/sysctl.h> #include <sys/types.h> +#include "kernel-features.h" extern void __libc_init_secure (void); extern void __libc_init (int, char **, char **); @@ -31,6 +36,10 @@ extern void __libc_global_ctors (void); /* The function is called from assembly stubs the compiler can't see. */ static void init (int, char **, char **) __attribute__ ((unused)); +/* The function we use to get the kernel revision. */ +extern int __sysctl (int *name, int nlen, void *oldval, size_t *oldlenp, + void *newval, size_t newlen); + extern int _dl_starting_up; weak_extern (_dl_starting_up) @@ -56,6 +65,69 @@ init (int argc, char **argv, char **envp) /* We must not call `personality' twice. */ if (!__libc_multiple_libcs) { + /* Test whether the kernel is new enough. This test is only + performed if the library is not compiled to run on all + kernels. */ + if (__LINUX_KERNEL_VERSION > 0) + { + static const int sysctl_args[] = { CTL_KERN, KERN_OSRELEASE }; + char buf[64]; + size_t reslen = sizeof (buf); + unsigned int version; + int parts; + char *cp; + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc + filesystem. */ + int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY); + if (fd == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up since we cannot + make sure the library can actually work. */ + __libc_fatal ("FATAL: cannot determine library version\n"); + + __close (fd); + } + buf[MIN (reslen, sizeof (buf) - 1)] = '\0'; + + /* Now convert it into a number. The string consists of at most + three parts. */ + version = 0; + parts = 0; + cp = buf; + while ((*cp >= '0') && (*cp <= '9')) + { + unsigned int here = *cp++ - '0'; + + while ((*cp >= '0') && (*cp <= '9')) + { + here *= 10; + here += *cp++ - '0'; + } + + ++parts; + version <<= 8; + version |= here; + + if (*cp++ != '.') + /* Another part following? */ + break; + } + + if (parts < 3) + version <<= 8 * (3 - parts); + + /* Now we can test with the required version. */ + if (version < __LINUX_KERNEL_VERSION) + /* Not sufficent. */ + __libc_fatal ("FATAL: kernel too old\n"); + } + /* The `personality' system call takes one argument that chooses the "personality", i.e. the set of system calls and such. We must make this call first thing to disable emulation of some diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h new file mode 100644 index 0000000000..6813853ccc --- /dev/null +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -0,0 +1,74 @@ +/* Set flags signalling availability of kernel features based on given + kernel version number. + Copyright (C) 1999 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 + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file must not contain any C code. At least it must be protected + to allow using the file also in assembler files. */ + +/* XXX For testing. */ +#define __LINUX_KERNEL_VERSION 131584 + +#ifndef __LINUX_KERNEL_VERSION +/* We assume the worst; all kernels should be supported. */ +# define __LINUX_KERNEL_VERSION 0 +#endif + +/* We assume for __LINUX_KERNEL_VERSION the same encoding used in + linux/version.h. I.e., the major, minor, and subminor all get a + byte with the major number being in the highest byte. This means + we can do numeric comparisons. + + In the following we will define certain symbols depending on + whether the describes kernel feature is available in the kernel + version given by __LINUX_KERNEL_VERSION. We are not always exactly + recording the correct versions in which the features were + introduced. If somebody cares these values can afterwards be + corrected. Most of the numbers here are set corresponding to + 2.2.0. */ + +/* `getcwd' system call. */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_GETCWD_SYSCALL 1 +#endif + +/* Real-time signal became usable in 2.1.70. */ +#if __LINUX_KERNEL_VERSION >= 131398 +# define __ASSUME_REALTIME_SIGNALS 1 +#endif + +/* When were the `pread'/`pwrite' syscalls introduced? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_PREAD_SYSCALL 1 +# define __ASSUME_PWRITE_SYSCALL 1 +#endif + +/* When was `poll' introduced? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_POLL_SYSCALL 1 +#endif + +/* The `lchown' syscall was introduced in 2.1.80. */ +#if __LINUX_KERNEL_VERSION >= 131408 +# define __ASSUME_LCHOWN_SYSCALL 1 +#endif + +/* When did the `setresuid' sysall became available? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_SETRESUID_SYSCALL 1 +#endif diff --git a/sysdeps/unix/sysv/linux/poll.c b/sysdeps/unix/sysv/linux/poll.c index e7df3b7774..16433e53e7 100644 --- a/sysdeps/unix/sysv/linux/poll.c +++ b/sysdeps/unix/sysv/linux/poll.c @@ -22,13 +22,18 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_poll + +#include "kernel-features.h" + +#if defined __NR_poll || __ASSUME_POLL_SYSCALL > 0 extern int __syscall_poll __P ((struct pollfd *fds, unsigned int nfds, int timeout)); +# if __ASSUME_POLL_SYSCALL == 0 static int __emulate_poll __P ((struct pollfd *fds, unsigned long int nfds, int timeout)) internal_function; +# endif /* The real implementation. */ int @@ -37,6 +42,7 @@ __poll (fds, nfds, timeout) unsigned long int nfds; int timeout; { +# if __ASSUME_POLL_SYSCALL == 0 static int must_emulate; if (!must_emulate) @@ -52,6 +58,9 @@ __poll (fds, nfds, timeout) } return __emulate_poll (fds, nfds, timeout); +# else + return INLINE_SYSCALL (poll, 3, fds, nfds, timeout); +# endif } weak_alias (__poll, poll) @@ -59,4 +68,7 @@ weak_alias (__poll, poll) # define __poll(fds, nfds, timeout) \ static internal_function __emulate_poll (fds, nfds, timeout) #endif -#include <sysdeps/unix/bsd/poll.c> + +#if __ASSUME_POLL_SYSCALL == 0 +# include <sysdeps/unix/bsd/poll.c> +#endif diff --git a/sysdeps/unix/sysv/linux/pread.c b/sysdeps/unix/sysv/linux/pread.c index a9461cab2e..cae3d62a5d 100644 --- a/sysdeps/unix/sysv/linux/pread.c +++ b/sysdeps/unix/sysv/linux/pread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,13 +23,17 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pread +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 extern ssize_t __syscall_pread (int fd, void *buf, size_t count, off_t offset_hi, off_t offset_lo); +# if __ASSUME_PREAD_SYSCALL == 0 static ssize_t __emulate_pread (int fd, void *buf, size_t count, off_t offset) internal_function; +# endif ssize_t @@ -43,16 +47,21 @@ __pread (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pread, 5, fd, buf, count, 0, offset); +# if __ASSUME_PREAD_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pread (fd, buf, count, offset); +# endif return result; } weak_alias (__pread, pread) -#define __pread(fd, buf, count, offset) \ +# define __pread(fd, buf, count, offset) \ static internal_function __emulate_pread (fd, buf, count, offset) #endif -#include <sysdeps/posix/pread.c> + +#if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread.c> +#endif diff --git a/sysdeps/unix/sysv/linux/pread64.c b/sysdeps/unix/sysv/linux/pread64.c index b8e117770f..fc4f7f24a0 100644 --- a/sysdeps/unix/sysv/linux/pread64.c +++ b/sysdeps/unix/sysv/linux/pread64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,13 +23,17 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pread +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 extern ssize_t __syscall_pread (int fd, void *buf, size_t count, off_t offset_hi, off_t offset_lo); +# if __ASSUME_PREAD_SYSCALL == 0 static ssize_t __emulate_pread64 (int fd, void *buf, size_t count, off64_t offset) internal_function; +# endif ssize_t @@ -44,16 +48,21 @@ __pread64 (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pread, 5, fd, buf, count, (off_t) (offset >> 32), (off_t) (offset & 0xffffffff)); +# if __ASSUME_PREAD_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pread64 (fd, buf, count, offset); +# endif return result; } weak_alias (__pread64, pread64) -#define __pread64(fd, buf, count, offset) \ +# define __pread64(fd, buf, count, offset) \ static internal_function __emulate_pread64 (fd, buf, count, offset) #endif -#include <sysdeps/posix/pread64.c> + +# if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/pwrite.c b/sysdeps/unix/sysv/linux/pwrite.c index cd7b8adaa1..fd4ec8896d 100644 --- a/sysdeps/unix/sysv/linux/pwrite.c +++ b/sysdeps/unix/sysv/linux/pwrite.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,13 +23,17 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pwrite +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 extern ssize_t __syscall_pwrite (int fd, const void *buf, size_t count, off_t offset_hi, off_t offset_lo); +# if __ASSUME_PWRITE_SYSCALL == 0 static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count, off_t offset) internal_function; +# endif ssize_t @@ -43,16 +47,21 @@ __pwrite (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pwrite, 5, fd, buf, count, 0, offset); +# if __ASSUME_PWRITE_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pwrite (fd, buf, count, offset); +# endif return result; } weak_alias (__pwrite, pwrite) -#define __pwrite(fd, buf, count, offset) \ +# define __pwrite(fd, buf, count, offset) \ static internal_function __emulate_pwrite (fd, buf, count, offset) #endif -#include <sysdeps/posix/pwrite.c> + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite.c> +#endif diff --git a/sysdeps/unix/sysv/linux/pwrite64.c b/sysdeps/unix/sysv/linux/pwrite64.c index b6ebba154b..cc92de1d76 100644 --- a/sysdeps/unix/sysv/linux/pwrite64.c +++ b/sysdeps/unix/sysv/linux/pwrite64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,13 +23,17 @@ #include <sysdep.h> #include <sys/syscall.h> -#ifdef __NR_pwrite +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 extern ssize_t __syscall_pwrite64 (int fd, const void *buf, size_t count, off_t offset_hi, off_t offset_lo); +# if __ASSUME_PWRITE_SYSCALL == 0 static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count, off64_t offset) internal_function; +# endif ssize_t @@ -44,16 +48,21 @@ __pwrite64 (fd, buf, count, offset) /* First try the syscall. */ result = INLINE_SYSCALL (pwrite, 5, fd, buf, count, (off_t) (offset >> 32), (off_t) (offset & 0xffffffff)); +# if __ASSUME_PWRITE_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use the emulation. */ result = __emulate_pwrite64 (fd, buf, count, offset); +# endif return result; } weak_alias (__pwrite64, pwrite64) -#define __pwrite64(fd, buf, count, offset) \ +# define __pwrite64(fd, buf, count, offset) \ static internal_function __emulate_pwrite64 (fd, buf, count, offset) #endif -#include <sysdeps/posix/pwrite64.c> + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/seteuid.c b/sysdeps/unix/sysv/linux/seteuid.c index 20840dbfc0..15687e36e4 100644 --- a/sysdeps/unix/sysv/linux/seteuid.c +++ b/sysdeps/unix/sysv/linux/seteuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999 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 @@ -21,7 +21,9 @@ #include <sys/types.h> #include <unistd.h> -#ifdef __NR_setresuid +#include "kernel-features.h" + +#if defined __NR_setresuid || __ASSUME_SETRESUID_SYSCALL > 0 extern int __setresuid (uid_t ruid, uid_t euid, uid_t suid); @@ -38,11 +40,13 @@ seteuid (uid_t uid) /* First try the syscall. */ result = __setresuid (-1, uid, -1); +# if __ASSUME_SETRESUID_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use emulation. This may not work since `setreuid' also sets the saved user ID when UID is not equal to the real user ID, making it impossible to switch back. */ result = __setreuid (-1, uid); +# endif return result; } diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c index a5580cc0e6..40f9bbc252 100644 --- a/sysdeps/unix/sysv/linux/sigaction.c +++ b/sysdeps/unix/sysv/linux/sigaction.c @@ -23,20 +23,27 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "kernel-features.h" + /* The difference here is that the sigaction structure used in the kernel is not the same as we use in the libc. Therefore we must translate it here. */ #include <kernel_sigaction.h> +#if __ASSUME_REALTIME_SIGNALS == 0 +/* The variable is shared between all wrappers around signal handling + functions which have RT equivalents. This is the definition. */ +int __libc_missing_rt_sigs; + extern int __syscall_sigaction (int, const struct old_kernel_sigaction *, struct old_kernel_sigaction *); +# define rtsignals_guaranteed 0 +#else +# define rtsignals_guaranteed 1 +#endif extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *, struct kernel_sigaction *, size_t); -/* The variable is shared between all wrappers around signal handling - functions which have RT equivalents. This is the definition. */ -int __libc_missing_rt_sigs; - /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ @@ -49,12 +56,18 @@ __sigaction (sig, act, oact) struct old_kernel_sigaction k_sigact, k_osigact; int result; -#ifdef __NR_rt_sigaction +#if defiend __NR_rt_sigaction || __ASSUME_REALTIME_SIGNALS > 0 /* First try the RT signals. */ +# if __ASSUME_REALTIME_SIGNALS == 0 if (!__libc_missing_rt_sigs) +# endif { struct kernel_sigaction kact, koact; + /* Save the current error value for later. We need not do this + if we are guaranteed to have realtime signals. */ +# if __ASSUME_REALTIME_SIGNALS == 0 int saved_errno = errno; +# endif if (act) { @@ -71,7 +84,9 @@ __sigaction (sig, act, oact) result = INLINE_SYSCALL (rt_sigaction, 4, sig, act ? &kact : NULL, oact ? &koact : NULL, _NSIG / 8); +# if __ASSUME_REALTIME_SIGNALS == 0 if (result >= 0 || errno != ENOSYS) +# endif { if (oact && result >= 0) { @@ -85,19 +100,22 @@ __sigaction (sig, act, oact) return result; } +# if __ASSUME_REALTIME_SIGNALS == 0 __set_errno (saved_errno); __libc_missing_rt_sigs = 1; +# endif } #endif +#if __ASSUME_REALTIME_SIGNALS == 0 if (act) { k_sigact.k_sa_handler = act->sa_handler; k_sigact.sa_mask = act->sa_mask.__val[0]; k_sigact.sa_flags = act->sa_flags; -#ifdef HAVE_SA_RESTORER +# ifdef HAVE_SA_RESTORER k_sigact.sa_restorer = act->sa_restorer; -#endif +# endif } result = INLINE_SYSCALL (sigaction, 3, sig, act ? &k_sigact : NULL, oact ? &k_osigact : NULL); @@ -106,11 +124,12 @@ __sigaction (sig, act, oact) oact->sa_handler = k_osigact.k_sa_handler; oact->sa_mask.__val[0] = k_osigact.sa_mask; oact->sa_flags = k_osigact.sa_flags; -#ifdef HAVE_SA_RESTORER +# ifdef HAVE_SA_RESTORER oact->sa_restorer = k_osigact.sa_restorer; -#endif +# endif } return result; +#endif } weak_alias (__sigaction, sigaction) diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c index c41c4f266a..932314520c 100644 --- a/sysdeps/unix/sysv/linux/sigpending.c +++ b/sysdeps/unix/sysv/linux/sigpending.c @@ -23,6 +23,8 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "kernel-features.h" + extern int __syscall_sigpending (sigset_t *); extern int __syscall_rt_sigpending (sigset_t *, size_t); @@ -38,7 +40,10 @@ int sigpending (set) sigset_t *set; { -#ifdef __NR_rt_pending +#if __ASSUME_REALTIME_SIGNALS > 0 + return INLINE_SYSCALL (rt_sigpending, 2, set, _NSIG / 8); +#else +# ifdef __NR_rt_pending /* First try the RT signals. */ if (!__libc_missing_rt_sigs) { @@ -53,7 +58,8 @@ sigpending (set) __set_errno (saved_errno); __libc_missing_rt_sigs = 1; } -#endif +# endif return INLINE_SYSCALL (sigpending, 1, set); +#endif } diff --git a/sysdeps/unix/sysv/linux/sigprocmask.c b/sysdeps/unix/sysv/linux/sigprocmask.c index 5e72c9892d..3e0719aa7f 100644 --- a/sysdeps/unix/sysv/linux/sigprocmask.c +++ b/sysdeps/unix/sysv/linux/sigprocmask.c @@ -23,6 +23,9 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "kernel-features.h" + + extern int __syscall_sigprocmask (int, const sigset_t *, sigset_t *); extern int __syscall_rt_sigprocmask (int, const sigset_t *, sigset_t *, size_t); @@ -39,7 +42,10 @@ __sigprocmask (how, set, oset) const sigset_t *set; sigset_t *oset; { -#ifdef __NR_rt_sigprocmask +#if __ASSUME_REALTIME_SIGNALS > 0 + return INLINE_SYSCALL (rt_sigprocmask, 4, how, set, oset, _NSIG / 8); +#else +# ifdef __NR_rt_sigprocmask /* First try the RT signals. */ if (!__libc_missing_rt_sigs) { @@ -55,8 +61,9 @@ __sigprocmask (how, set, oset) __set_errno (saved_errno); __libc_missing_rt_sigs = 1; } -#endif +# endif return INLINE_SYSCALL (sigprocmask, 3, how, set, oset); +#endif } weak_alias (__sigprocmask, sigprocmask) diff --git a/sysdeps/unix/sysv/linux/sigsuspend.c b/sysdeps/unix/sysv/linux/sigsuspend.c index 1d0dba0270..da743396b8 100644 --- a/sysdeps/unix/sysv/linux/sigsuspend.c +++ b/sysdeps/unix/sysv/linux/sigsuspend.c @@ -23,6 +23,8 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "kernel-features.h" + extern int __syscall_sigsuspend (int, unsigned long int, unsigned long int); extern int __syscall_rt_sigsuspend (const sigset_t *, size_t); @@ -38,7 +40,10 @@ int __sigsuspend (set) const sigset_t *set; { -#ifdef __NR_rt_sigsuspend +#if __ASSUME_REALTIME_SIGNALS + return INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8); +#else +# ifdef __NR_rt_sigsuspend /* First try the RT signals. */ if (!__libc_missing_rt_sigs) { @@ -53,8 +58,9 @@ __sigsuspend (set) __set_errno (saved_errno); __libc_missing_rt_sigs = 1; } -#endif +# endif return INLINE_SYSCALL (sigsuspend, 3, 0, 0, set->__val[0]); +#endif } weak_alias (__sigsuspend, sigsuspend) diff --git a/sysdeps/unix/sysv/linux/sysctl.c b/sysdeps/unix/sysv/linux/sysctl.c index 1ab3c79bed..b131820a30 100644 --- a/sysdeps/unix/sysv/linux/sysctl.c +++ b/sysdeps/unix/sysv/linux/sysctl.c @@ -1,5 +1,5 @@ /* Read or write system information. Linux version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999 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 @@ -26,8 +26,8 @@ extern int __syscall__sysctl (struct __sysctl_args *args); int -sysctl (int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen) +__sysctl (int *name, int nlen, void *oldval, size_t *oldlenp, + void *newval, size_t newlen) { struct __sysctl_args args = { @@ -41,3 +41,4 @@ sysctl (int *name, int nlen, void *oldval, size_t *oldlenp, return INLINE_SYSCALL (_sysctl, 1, &args); } +weak_alias (__sysctl, sysctl) diff --git a/sysdeps/unix/sysv/linux/testrtsig.h b/sysdeps/unix/sysv/linux/testrtsig.h index 7c41877e66..72d4e5a3d2 100644 --- a/sysdeps/unix/sysv/linux/testrtsig.h +++ b/sysdeps/unix/sysv/linux/testrtsig.h @@ -1,5 +1,5 @@ /* Test whether RT signals are really available. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -21,10 +21,16 @@ #include <string.h> #include <sys/utsname.h> +#include "kernel-features.h" + static int kernel_has_rtsig (void) { +#if __ASSUME_REALTIME_SIGNALS + return 1; +#else struct utsname name; return uname (&name) == 0 && __strverscmp (name.release, "2.1.70") >= 0; +#endif } |