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/unix/sysv/linux/init-first.c | |
parent | 475e390e80a950a8746dc0b88341742dc99014e4 (diff) | |
download | glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.tar.gz glibc-958f238f3619373d3dbc106d3cda3c467b3419b1.tar.xz 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/unix/sysv/linux/init-first.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/init-first.c | 74 |
1 files changed, 73 insertions, 1 deletions
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 |