about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog59
-rw-r--r--elf/dl-reloc.c4
-rw-r--r--rt/aio.h4
-rwxr-xr-xscripts/rellns-sh18
-rw-r--r--sysdeps/arm/dl-machine.h8
-rw-r--r--sysdeps/ieee754/bits/nan.h6
-rw-r--r--sysdeps/unix/sysv/linux/alpha/bits/resource.h204
-rw-r--r--sysdeps/unix/sysv/linux/bits/resource.h44
-rw-r--r--sysdeps/unix/sysv/linux/ftruncate64.c4
-rw-r--r--sysdeps/unix/sysv/linux/fxstat64.c32
-rw-r--r--sysdeps/unix/sysv/linux/i386/bits/resource.h46
-rw-r--r--sysdeps/unix/sysv/linux/i386/setrlimit.c2
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h7
-rw-r--r--sysdeps/unix/sysv/linux/lxstat64.c30
-rw-r--r--sysdeps/unix/sysv/linux/mips/bits/resource.h205
-rw-r--r--sysdeps/unix/sysv/linux/sparc/bits/resource.h47
-rw-r--r--sysdeps/unix/sysv/linux/truncate64.c4
-rw-r--r--sysdeps/unix/sysv/linux/xstat64.c33
18 files changed, 634 insertions, 123 deletions
diff --git a/ChangeLog b/ChangeLog
index f3b284705f..4cc94489c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,62 @@
+1999-12-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/i386/setrlimit.c: Declare local variable
+	result if necessary.
+
+	* sysdeps/unix/sysv/linux/i386/bits/resource.h: Don't depend on the
+	unreliable kernel headers.
+	* sysdeps/unix/sysv/linux/bits/resource.h: Likewise.
+	* sysdeps/unix/sysv/linux/sparc/bits/resource.h: Likewise.
+	* sysdeps/unix/sysv/linux/alpha/bits/resource.h: New file.
+	* sysdeps/unix/sysv/linux/mips/bits/resource.h: New file.
+
+1999-12-18  Andreas Jaeger  <aj@suse.de>
+
+	* config.make.in (datadir): Added.
+	Closes PR libc/1491. Patch by dervishd@jazzfree.com.
+
+1999-12-18  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/ftruncate64.c (ftruncate64): Save and
+	set errno.
+	* sysdeps/unix/sysv/linux/truncate64.c (truncate64): Likewise.
+
+1999-12-18  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/unix/sysv/linux/fxstat64.c: Rewrite to use fstat64
+	syscall if available.
+	* sysdeps/unix/sysv/linux/lxstat64.c: Likewise for lstat64.
+	* sysdeps/unix/sysv/linux/xstat64.c: Likewise for stat64.
+
+	* sysdeps/unix/sysv/linux/kernel-features.h
+	(__ASSUME_STAT64_SYSCALL): New.
+
+1999-12-17  Scott Bambrough  <scottb@netwinder.org>
+
+	* sysdeps/arm/dl-machine.h (CLEAR_CACHE): New macro to force a
+	cache flush.
+	* elf/dl-reloc.c (_dl_relocate_object): Add call to flush cache
+	after .text segment fixups.
+
+1999-12-16  Andreas Jaeger  <aj@suse.de>
+
+	* rt/aio.h: Remove erroneous __restrict declarations.
+
+1999-12-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* scripts/rellns-sh: Find pwd program also in /usr/bin and let shell
+	do the job if it is there neither.
+	Patch by David R. Conrad <drc@adni.net> (PR libc/1485).
+
+1999-12-16  Andreas Jaeger  <aj@suse.de>
+
+	* sysdeps/ieee754/bits/nan.h (NAN): Rename union to avoid
+	duplicate definition with function __nan.
+	Closes PR libc/1487 reported by <diana@kai.com>.
+
 1999-12-17  Ulrich Drepper  <drepper@cygnus.com>
 
-	* string/bits/string2.h (__strtok_r_1c): Help gcc optimizing string
-	access.
+	* string/bits/string2.h (__strsep): Help gcc optimizing string access.
 
 	* locale/programs/ld-collate.c: Implement handling of absolute
 	ellipsis.  Parsing of file and constructing the internal data
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index a1c235a398..7b7e7f1090 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -131,6 +131,10 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	    if (__mprotect (mapstart, mapend - mapstart, prot) < 0)
 	      _dl_signal_error (errno, l->l_name,
 				"can't restore segment prot after reloc");
+
+#ifdef CLEAR_CACHE
+	    CLEAR_CACHE (mapstart, mapend);
+#endif 
 	  }
     }
 }
diff --git a/rt/aio.h b/rt/aio.h
index 205d63afe7..b26d023620 100644
--- a/rt/aio.h
+++ b/rt/aio.h
@@ -172,7 +172,7 @@ extern int __REDIRECT (aio_write, (struct aiocb *__aiocbp) __THROW,
 		       aio_write64);
 
 extern int __REDIRECT (lio_listio,
-		       (int __mode, struct aiocb *__const __restrict __list[],
+		       (int __mode, struct aiocb *__const __list[],
 			int __nent, struct sigevent *__restrict __sig) __THROW,
 		       lio_listio64);
 
@@ -186,7 +186,7 @@ extern int __REDIRECT (aio_cancel,
 		       aio_cancel64);
 
 extern int __REDIRECT (aio_suspend,
-		       (__const struct aiocb *__const __restrict __list[],
+		       (__const struct aiocb *__const __list[],
 			int __nent,
 			__const struct timespec *__restrict __timeout) __THROW,
 		       aio_suspend64);
diff --git a/scripts/rellns-sh b/scripts/rellns-sh
index 890f4eea3a..e4626cebd6 100755
--- a/scripts/rellns-sh
+++ b/scripts/rellns-sh
@@ -22,15 +22,23 @@ if test $# -ne 2; then
   exit 1
 fi
 
+if test -x /bin/pwd; then
+  pwd=/bin/pwd
+elif test -x /usr/bin/pwd; then
+  pwd=/usr/bin/pwd
+else
+  pwd='pwd'
+fi
+
 # Make both paths absolute.
 if test -d $1; then
-  to=`cd $1 && /bin/pwd`
+  to=`cd $1 && $pwd`
 else
   temp=`echo $1 | sed 's%/*[^/]*$%%'`
   if test -z "$temp"; then
-    to=`/bin/pwd`
+    to=`$pwd`
   else
-    to=`cd $temp && /bin/pwd`
+    to=`cd $temp && $pwd`
   fi
   to="$to/`echo $1 | sed 's%.*/\([^/][^/]*\)$%\1%'`"
 fi
@@ -43,9 +51,9 @@ else
 fi
 
 if test -z "$from"; then
-  from=`/bin/pwd | sed 's%^/%%'`
+  from=`$pwd | sed 's%^/%%'`
 else
-  from=`cd $from && /bin/pwd | sed 's%^/%%'`
+  from=`cd $from && $pwd | sed 's%^/%%'`
 fi
 
 while test -n "$to" && test -n "$from"; do
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index 2e6faf5d51..de2d0babf5 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -32,6 +32,14 @@
   && VALID_ELF_OSABI (hdr[EI_OSABI]) \
   && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
 
+#define CLEAR_CACHE(BEG,END)						\
+{									\
+  register unsigned long _beg __asm ("a1") = (unsigned long)(BEG);	\
+  register unsigned long _end __asm ("a2") = (unsigned long)((END) - (BEG));\
+  register unsigned long _flg __asm ("a3") = 0;				\
+  __asm __volatile ("swi 0x9f0002");					\
+}
+
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
 static inline int __attribute__ ((unused))
 elf_machine_matches_host (Elf32_Half e_machine)
diff --git a/sysdeps/ieee754/bits/nan.h b/sysdeps/ieee754/bits/nan.h
index 1f385ffc00..fbabd7e29a 100644
--- a/sysdeps/ieee754/bits/nan.h
+++ b/sysdeps/ieee754/bits/nan.h
@@ -1,5 +1,5 @@
 /* `NAN' constant for IEEE 754 machines.
-   Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1996, 1997, 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
@@ -42,7 +42,7 @@
 #  define __nan_bytes		{ 0, 0, 0xc0, 0x7f }
 # endif
 
-static union { unsigned char __c[4]; float __d; } __nan = { __nan_bytes };
-# define NAN	(__nan.__d)
+static union { unsigned char __c[4]; float __d; } __nan_union = { __nan_bytes };
+# define NAN	(__nan_union.__d)
 
 #endif	/* GCC.  */
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/resource.h b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
new file mode 100644
index 0000000000..c89f5a0639
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
@@ -0,0 +1,204 @@
+/* Bit values & structures for resource limits.  Alpha/Linux version.
+   Copyright (C) 1994, 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
+   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.  */
+
+#ifndef _SYS_RESOURCE_H
+# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Transmute defines to enumerations.  The macro re-definitions are
+   necessary because some programs want to test for operating system
+   features with #ifdef RUSAGE_SELF.  In ISO C the reflexive
+   definition is a no-op.  */
+
+/* Kinds of resource limit.  */
+enum __rlimit_resource
+{
+  /* Per-process CPU limit, in seconds.  */
+  RLIMIT_CPU = 0,
+#define RLIMIT_CPU RLIMIT_CPU
+
+  /* Largest file that can be created, in bytes.  */
+  RLIMIT_FSIZE = 1,
+#define	RLIMIT_FSIZE RLIMIT_FSIZE
+
+  /* Maximum size of data segment, in bytes.  */
+  RLIMIT_DATA = 2,
+#define	RLIMIT_DATA RLIMIT_DATA
+
+  /* Maximum size of stack segment, in bytes.  */
+  RLIMIT_STACK = 3,
+#define	RLIMIT_STACK RLIMIT_STACK
+
+  /* Largest core file that can be created, in bytes.  */
+  RLIMIT_CORE = 4,
+#define	RLIMIT_CORE RLIMIT_CORE
+
+  /* Largest resident set size, in bytes.
+     This affects swapping; processes that are exceeding their
+     resident set size will be more likely to have physical memory
+     taken from them.  */
+  RLIMIT_RSS = 5,
+#define	RLIMIT_RSS RLIMIT_RSS
+
+  /* Number of open files.  */
+  RLIMIT_NOFILE = 6,
+  RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
+#define RLIMIT_NOFILE RLIMIT_NOFILE
+#define RLIMIT_OFILE RLIMIT_OFILE
+
+  /* Address space limit (?) */
+  RLIMIT_AS = 7,
+#define RLIMIT_AS RLIMIT_AS
+
+  /* Number of processes.  */
+  RLIMIT_NPROC = 8,
+#define RLIMIT_NPROC RLIMIT_NPROC
+
+  /* Locked-in-memory address space.  */
+  RLIMIT_MEMLOCK = 9,
+#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
+
+  RLIM_NLIMITS = 10
+#define RLIMIT_NLIMITS RLIMIT_NLIMITS
+#define RLIM_NLIMITS RLIM_NLIMITS
+};
+
+/* Value to indicate that there is no limit.  */
+#ifndef __USE_FILE_OFFSET64
+# define RLIM_INFINITY ((long int)(~0UL >> 1))
+#else
+# define RLIM_INFINITY 0x7fffffffffffffffLL
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define RLIM64_INFINITY 0x7fffffffffffffffLL
+#endif
+
+/* We can represent all limits.  */
+#define RLIM_SAVED_MAX	RLIM_INFINITY
+#define RLIM_SAVED_CUR	RLIM_INFINITY
+
+
+/* Type for resource quantity measurement.  */
+#ifndef __USE_FILE_OFFSET64
+typedef __rlim_t rlim_t;
+#else
+typedef __rlim64_t rlim_t;
+#endif
+#ifdef __USE_LARGEFILE64
+typedef __rlim64_t rlim64_t;
+#endif
+
+struct rlimit
+  {
+    /* The current (soft) limit.  */
+    rlim_t rlim_cur;
+    /* The hard limit.  */
+    rlim_t rlim_max;
+  };
+
+#ifdef __USE_LARGEFILE64
+struct rlimit64
+  {
+    /* The current (soft) limit.  */
+    rlim64_t rlim_cur;
+    /* The hard limit.  */
+    rlim64_t rlim_max;
+ };
+#endif
+
+/* Whose usage statistics do you want?  */
+enum __rusage_who
+{
+  /* The calling process.  */
+  RUSAGE_SELF = 0,
+#define RUSAGE_SELF RUSAGE_SELF
+
+  /* All of its terminated child processes.  */
+  RUSAGE_CHILDREN = -1,
+#define RUSAGE_CHILDREN RUSAGE_CHILDREN
+
+  /* Both.  */
+  RUSAGE_BOTH = -2
+#define RUSAGE_BOTH RUSAGE_BOTH
+};
+
+#define __need_timeval
+#include <bits/time.h>		/* For `struct timeval'.  */
+
+/* Structure which says how much of each resource has been used.  */
+struct rusage
+  {
+    /* Total amount of user time used.  */
+    struct timeval ru_utime;
+    /* Total amount of system time used.  */
+    struct timeval ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    long int ru_maxrss;
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    long int ru_ixrss;
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    long int ru_idrss;
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    long int ru_isrss;
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    long int ru_minflt;
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    long int ru_majflt;
+    /* Number of times a process was swapped out of physical memory.  */
+    long int ru_nswap;
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    long int ru_inblock;
+    /* Number of output operations via the file system.  */
+    long int ru_oublock;
+    /* Number of IPC messages sent.  */
+    long int ru_msgsnd;
+    /* Number of IPC messages received.  */
+    long int ru_msgrcv;
+    /* Number of signals delivered.  */
+    long int ru_nsignals;
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    long int ru_nvcsw;
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    long int ru_nivcsw;
+  };
+
+/* Priority limits.  */
+#define PRIO_MIN	-20	/* Minimum priority a process can have.  */
+#define PRIO_MAX	20	/* Maximum priority a process can have.  */
+
+/* The type of the WHICH argument to `getpriority' and `setpriority',
+   indicating what flavor of entity the WHO argument specifies.  */
+enum __priority_which
+{
+  PRIO_PROCESS = 0,		/* WHO is a process ID.  */
+#define PRIO_PROCESS PRIO_PROCESS
+  PRIO_PGRP = 1,		/* WHO is a process group ID.  */
+#define PRIO_PGRP PRIO_PGRP
+  PRIO_USER = 2			/* WHO is a user ID.  */
+#define PRIO_USER PRIO_USER
+};
diff --git a/sysdeps/unix/sysv/linux/bits/resource.h b/sysdeps/unix/sysv/linux/bits/resource.h
index 6a3d86ce18..fef37f8da9 100644
--- a/sysdeps/unix/sysv/linux/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/bits/resource.h
@@ -33,73 +33,51 @@
 enum __rlimit_resource
 {
   /* Per-process CPU limit, in seconds.  */
-  _RLIMIT_CPU = RLIMIT_CPU,
-#undef RLIMIT_CPU
-  RLIMIT_CPU = _RLIMIT_CPU,
+  RLIMIT_CPU = 0,
 #define RLIMIT_CPU RLIMIT_CPU
 
   /* Largest file that can be created, in bytes.  */
-  _RLIMIT_FSIZE = RLIMIT_FSIZE,
-#undef RLIMIT_FSIZE
-  RLIMIT_FSIZE = _RLIMIT_FSIZE,
+  RLIMIT_FSIZE = 1,
 #define	RLIMIT_FSIZE RLIMIT_FSIZE
 
   /* Maximum size of data segment, in bytes.  */
-  _RLIMIT_DATA = RLIMIT_DATA,
-#undef RLIMIT_DATA
-  RLIMIT_DATA = _RLIMIT_DATA,
+  RLIMIT_DATA = 2,
 #define	RLIMIT_DATA RLIMIT_DATA
 
   /* Maximum size of stack segment, in bytes.  */
-  _RLIMIT_STACK = RLIMIT_STACK,
-#undef RLIMIT_STACK
-  RLIMIT_STACK = _RLIMIT_STACK,
+  RLIMIT_STACK = 3,
 #define	RLIMIT_STACK RLIMIT_STACK
 
   /* Largest core file that can be created, in bytes.  */
-  _RLIMIT_CORE = RLIMIT_CORE,
-#undef RLIMIT_CORE
-  RLIMIT_CORE = _RLIMIT_CORE,
+  RLIMIT_CORE = 4,
 #define	RLIMIT_CORE RLIMIT_CORE
 
   /* Largest resident set size, in bytes.
      This affects swapping; processes that are exceeding their
      resident set size will be more likely to have physical memory
      taken from them.  */
-  _RLIMIT_RSS = RLIMIT_RSS,
-#undef RLIMIT_RSS
-  RLIMIT_RSS = _RLIMIT_RSS,
+  RLIMIT_RSS = 5,
 #define	RLIMIT_RSS RLIMIT_RSS
 
   /* Number of open files.  */
-  _RLIMIT_NOFILE = RLIMIT_NOFILE,
-#undef RLIMIT_NOFILE
-  RLIMIT_NOFILE = _RLIMIT_NOFILE,
+  RLIMIT_NOFILE = 7,
   RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
 #define RLIMIT_NOFILE RLIMIT_NOFILE
 #define RLIMIT_OFILE RLIMIT_OFILE
 
   /* Address space limit (?) */
-  _RLIMIT_AS = RLIMIT_AS,
-#undef RLIMIT_AS
-  RLIMIT_AS = _RLIMIT_AS,
+  RLIMIT_AS = 9,
 #define RLIMIT_AS RLIMIT_AS
 
   /* Number of processes.  */
-  _RLIMIT_NPROC = RLIMIT_NPROC,
-#undef RLIMIT_NPROC
-  RLIMIT_NPROC = _RLIMIT_NPROC,
+  RLIMIT_NPROC = 6,
 #define RLIMIT_NPROC RLIMIT_NPROC
 
   /* Locked-in-memory address space.  */
-  _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK,
-#undef RLIMIT_MEMLOCK
-  RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK,
+  RLIMIT_MEMLOCK = 8,
 #define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
 
-  RLIMIT_NLIMITS = RLIM_NLIMITS,
-#undef RLIM_NLIMITS
-  RLIM_NLIMITS = RLIMIT_NLIMITS
+  RLIM_NLIMITS = 10
 #define RLIMIT_NLIMITS RLIMIT_NLIMITS
 #define RLIM_NLIMITS RLIM_NLIMITS
 };
diff --git a/sysdeps/unix/sysv/linux/ftruncate64.c b/sysdeps/unix/sysv/linux/ftruncate64.c
index 6644b0523c..47df34ec7e 100644
--- a/sysdeps/unix/sysv/linux/ftruncate64.c
+++ b/sysdeps/unix/sysv/linux/ftruncate64.c
@@ -43,6 +43,9 @@ ftruncate64 (fd, length)
     {
       unsigned int low = length & 0xffffffff;
       unsigned int high = length >> 32;
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      int saved_errno = errno;
+#endif
       int result = INLINE_SYSCALL (ftruncate64, 3, fd, low, high);
 
 #ifndef __ASSUME_TRUNCATE64_SYSCALL
@@ -51,6 +54,7 @@ ftruncate64 (fd, length)
 	return result;
 
 #ifndef __ASSUME_TRUNCATE64_SYSCALL
+      __set_errno (saved_errno);
       have_no_ftruncate64 = 1;
 #endif
     }
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 5f13fbe35c..b88a78c7a5 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -1,5 +1,5 @@
 /* fxstat64 using old-style Unix fstat system call.
-   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.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,20 +25,46 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
-#include <xstatconv.c>
+#if __ASSUME_STAT64_SYSCALL == 0
+# include <xstatconv.c>
+#endif
 
 extern int __syscall_fstat (int, struct kernel_stat *);
 
+#ifdef __NR_fstat64
+extern int __syscall_fstat64 (int, struct stat64 *);
+# if  __ASSUME_STAT64_SYSCALL == 0
+/* The variable is shared between all wrappers around *stat64 calls.  */
+extern int have_no_stat64;
+# endif
+#endif
+
 /* Get information about the file FD in BUF.  */
 int
 __fxstat64 (int vers, int fd, struct stat64 *buf)
 {
-  struct kernel_stat kbuf;
+#if __ASSUME_STAT64_SYSCALL > 0
+  return INLINE_SYSCALL (fstat64, 2, fd, &buf);
+#else
   int result;
+  struct kernel_stat kbuf;
+# if defined __NR_fstat64
+  if (! have_no_stat64)
+    {
+      int saved_errno = errno;
+      result = INLINE_SYSCALL (fstat64, 2, fd, &buf);
+
+      if (result != -1 || errno != ENOSYS)
+	return result;
 
+      __set_errno (saved_errno);
+      have_no_stat64 = 1;
+    }
+# endif
   result = INLINE_SYSCALL (fstat, 2, fd, &kbuf);
   if (result == 0)
     result = xstat64_conv (vers, &kbuf, buf);
 
   return result;
+#endif
 }
diff --git a/sysdeps/unix/sysv/linux/i386/bits/resource.h b/sysdeps/unix/sysv/linux/i386/bits/resource.h
index fcff605892..710f1119c0 100644
--- a/sysdeps/unix/sysv/linux/i386/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/i386/bits/resource.h
@@ -21,7 +21,6 @@
 # error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
 #endif
 
-#include <asm/resource.h>
 #include <bits/types.h>
 
 /* Transmute defines to enumerations.  The macro re-definitions are
@@ -33,72 +32,51 @@
 enum __rlimit_resource
 {
   /* Per-process CPU limit, in seconds.  */
-  _RLIMIT_CPU = RLIMIT_CPU,
-#undef RLIMIT_CPU
-  RLIMIT_CPU = _RLIMIT_CPU,
+  RLIMIT_CPU = 0,
 #define RLIMIT_CPU RLIMIT_CPU
 
   /* Largest file that can be created, in bytes.  */
-  _RLIMIT_FSIZE = RLIMIT_FSIZE,
-#undef RLIMIT_FSIZE
-  RLIMIT_FSIZE = _RLIMIT_FSIZE,
+  RLIMIT_FSIZE = 1,
 #define	RLIMIT_FSIZE RLIMIT_FSIZE
 
   /* Maximum size of data segment, in bytes.  */
-  _RLIMIT_DATA = RLIMIT_DATA,
-#undef RLIMIT_DATA
-  RLIMIT_DATA = _RLIMIT_DATA,
+  RLIMIT_DATA = 2,
 #define	RLIMIT_DATA RLIMIT_DATA
 
   /* Maximum size of stack segment, in bytes.  */
-  _RLIMIT_STACK = RLIMIT_STACK,
-#undef RLIMIT_STACK
-  RLIMIT_STACK = _RLIMIT_STACK,
+  RLIMIT_STACK = 3,
 #define	RLIMIT_STACK RLIMIT_STACK
 
   /* Largest core file that can be created, in bytes.  */
-  _RLIMIT_CORE = RLIMIT_CORE,
-#undef RLIMIT_CORE
-  RLIMIT_CORE = _RLIMIT_CORE,
+  RLIMIT_CORE = 4,
 #define	RLIMIT_CORE RLIMIT_CORE
 
   /* Largest resident set size, in bytes.
      This affects swapping; processes that are exceeding their
      resident set size will be more likely to have physical memory
      taken from them.  */
-  _RLIMIT_RSS = RLIMIT_RSS,
-#undef RLIMIT_RSS
-  RLIMIT_RSS = _RLIMIT_RSS,
+  RLIMIT_RSS = 5,
 #define	RLIMIT_RSS RLIMIT_RSS
 
   /* Number of open files.  */
-  _RLIMIT_NOFILE = RLIMIT_NOFILE,
-#undef RLIMIT_NOFILE
-  RLIMIT_NOFILE = _RLIMIT_NOFILE,
+  RLIMIT_NOFILE = 7,
   RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
 #define RLIMIT_NOFILE RLIMIT_NOFILE
 #define RLIMIT_OFILE RLIMIT_OFILE
 
-  /* Address space limit (?) */
-  _RLIMIT_AS = RLIMIT_AS,
-#undef RLIMIT_AS
-  RLIMIT_AS = _RLIMIT_AS,
+  /* Address space limit.  */
+  RLIMIT_AS = 9,
 #define RLIMIT_AS RLIMIT_AS
 
   /* Number of processes.  */
-  _RLIMIT_NPROC = RLIMIT_NPROC,
-#undef RLIMIT_NPROC
-  RLIMIT_NPROC = _RLIMIT_NPROC,
+  RLIMIT_NPROC = 6,
 #define RLIMIT_NPROC RLIMIT_NPROC
 
   /* Locked-in-memory address space.  */
-  _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK,
-#undef RLIMIT_MEMLOCK
-  RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK,
+  RLIMIT_MEMLOCK = 8,
 #define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
 
-  RLIMIT_NLIMITS = RLIM_NLIMITS,
-#undef RLIM_NLIMITS
+  RLIMIT_NLIMITS = 10,
   RLIM_NLIMITS = RLIMIT_NLIMITS
 #define RLIMIT_NLIMITS RLIMIT_NLIMITS
 #define RLIM_NLIMITS RLIM_NLIMITS
diff --git a/sysdeps/unix/sysv/linux/i386/setrlimit.c b/sysdeps/unix/sysv/linux/i386/setrlimit.c
index 2123360fc9..e8adeed5e9 100644
--- a/sysdeps/unix/sysv/linux/i386/setrlimit.c
+++ b/sysdeps/unix/sysv/linux/i386/setrlimit.c
@@ -50,7 +50,7 @@ __new_setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits)
       /* Check if the new ugetrlimit syscall exists.  We must do this
 	 first because older kernels don't reject negative rlimit
 	 values in setrlimit.  */
-      result = INLINE_SYSCALL (ugetrlimit, 2, resource, &rlimits_small);
+      int result = INLINE_SYSCALL (ugetrlimit, 2, resource, &rlimits_small);
       if (result != -1 || errno != ENOSYS)
 	/* The syscall exists.  */
 	__have_no_new_getrlimit = -1;
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index b11dc4cce0..36cd46aa94 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -85,7 +85,12 @@
 # define __ASSUME_TRUNCATE64_SYSCALL	1
 #endif
 
-/* On x86 the truncate64/ftruncate64 syscalls were introduced in 2.3.31.  */
+/* On x86 the mmap2 syscall was introduced in 2.3.31.  */
 #if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__
 # define __ASSUME_MMAP2_SYSCALL	1
 #endif
+
+/* On x86 the stat64/lstat64/fstat64 syscalls were introduced in 2.3.34.  */
+#if __LINUX_KERNEL_VERSION >= 131874 && defined __i386__
+# define __ASSUME_STAT64_SYSCALL	1
+#endif
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 60280804db..9db8fcf455 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -1,5 +1,5 @@
 /* lxstat64 using old-style Unix lstat system call.
-   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.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,20 +25,46 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
-#include <xstatconv.c>
+#if __ASSUME_STAT64_SYSCALL == 0
+# include <xstatconv.c>
+#endif
 
 extern int __syscall_lstat (const char *, struct kernel_stat *);
 
+#ifdef __NR_lstat64
+extern int __syscall_lstat64 (const char *, struct stat64 *);
+# if  __ASSUME_STAT64_SYSCALL == 0
+/* The variable is shared between all wrappers around *stat64 calls.  */
+extern int have_no_stat64;
+# endif
+#endif
+
 /* Get information about the file NAME in BUF.  */
 int
 __lxstat64 (int vers, const char *name, struct stat64 *buf)
 {
+#ifdef __ASSUME_STAT64_SYSCALL
+  return INLINE_SYSCALL (lstat64, 2, name, &buf);
+#else
   struct kernel_stat kbuf;
   int result;
+# ifdef __NR_lstat64
+  if (! have_no_stat64)
+    {
+      int saved_errno = errno;
+      result = INLINE_SYSCALL (lstat64, 2, name, &kbuf);
+
+      if (result != -1 || errno != ENOSYS)
+	return result;
 
+      __set_errno (saved_errno);
+      have_no_stat64 = 1;
+    }
+# endif
   result = INLINE_SYSCALL (lstat, 2, name, &kbuf);
   if (result == 0)
     result = xstat64_conv (vers, &kbuf, buf);
 
   return result;
+#endif
 }
diff --git a/sysdeps/unix/sysv/linux/mips/bits/resource.h b/sysdeps/unix/sysv/linux/mips/bits/resource.h
new file mode 100644
index 0000000000..feb9cc72d0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/bits/resource.h
@@ -0,0 +1,205 @@
+/* Bit values & structures for resource limits.  MIPS/Linux version.
+   Copyright (C) 1994, 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
+   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.  */
+
+#ifndef _SYS_RESOURCE_H
+# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
+#endif
+
+#include <asm/resource.h>
+#include <bits/types.h>
+
+/* Transmute defines to enumerations.  The macro re-definitions are
+   necessary because some programs want to test for operating system
+   features with #ifdef RUSAGE_SELF.  In ISO C the reflexive
+   definition is a no-op.  */
+
+/* Kinds of resource limit.  */
+enum __rlimit_resource
+{
+  /* Per-process CPU limit, in seconds.  */
+  RLIMIT_CPU = 0,
+#define RLIMIT_CPU RLIMIT_CPU
+
+  /* Largest file that can be created, in bytes.  */
+  RLIMIT_FSIZE = 1,
+#define	RLIMIT_FSIZE RLIMIT_FSIZE
+
+  /* Maximum size of data segment, in bytes.  */
+  RLIMIT_DATA = 2,
+#define	RLIMIT_DATA RLIMIT_DATA
+
+  /* Maximum size of stack segment, in bytes.  */
+  RLIMIT_STACK = 3,
+#define	RLIMIT_STACK RLIMIT_STACK
+
+  /* Largest core file that can be created, in bytes.  */
+  RLIMIT_CORE = 4,
+#define	RLIMIT_CORE RLIMIT_CORE
+
+  /* Largest resident set size, in bytes.
+     This affects swapping; processes that are exceeding their
+     resident set size will be more likely to have physical memory
+     taken from them.  */
+  RLIMIT_RSS = 7,
+#define	RLIMIT_RSS RLIMIT_RSS
+
+  /* Number of open files.  */
+  RLIMIT_NOFILE = 5,
+  RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
+#define RLIMIT_NOFILE RLIMIT_NOFILE
+#define RLIMIT_OFILE RLIMIT_OFILE
+
+  /* Address space limit (?) */
+  RLIMIT_AS = 6,
+#define RLIMIT_AS RLIMIT_AS
+
+  /* Number of processes.  */
+  RLIMIT_NPROC = 8,
+#define RLIMIT_NPROC RLIMIT_NPROC
+
+  /* Locked-in-memory address space.  */
+  RLIMIT_MEMLOCK = 9,
+#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
+
+  RLIM_NLIMITS = 10
+#define RLIMIT_NLIMITS RLIMIT_NLIMITS
+#define RLIM_NLIMITS RLIM_NLIMITS
+};
+
+/* Value to indicate that there is no limit.  */
+#ifndef __USE_FILE_OFFSET64
+# define RLIM_INFINITY ((long int)(~0UL >> 1))
+#else
+# define RLIM_INFINITY 0x7fffffffffffffffLL
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define RLIM64_INFINITY 0x7fffffffffffffffLL
+#endif
+
+/* We can represent all limits.  */
+#define RLIM_SAVED_MAX	RLIM_INFINITY
+#define RLIM_SAVED_CUR	RLIM_INFINITY
+
+
+/* Type for resource quantity measurement.  */
+#ifndef __USE_FILE_OFFSET64
+typedef __rlim_t rlim_t;
+#else
+typedef __rlim64_t rlim_t;
+#endif
+#ifdef __USE_LARGEFILE64
+typedef __rlim64_t rlim64_t;
+#endif
+
+struct rlimit
+  {
+    /* The current (soft) limit.  */
+    rlim_t rlim_cur;
+    /* The hard limit.  */
+    rlim_t rlim_max;
+  };
+
+#ifdef __USE_LARGEFILE64
+struct rlimit64
+  {
+    /* The current (soft) limit.  */
+    rlim64_t rlim_cur;
+    /* The hard limit.  */
+    rlim64_t rlim_max;
+ };
+#endif
+
+/* Whose usage statistics do you want?  */
+enum __rusage_who
+{
+  /* The calling process.  */
+  RUSAGE_SELF = 0,
+#define RUSAGE_SELF RUSAGE_SELF
+
+  /* All of its terminated child processes.  */
+  RUSAGE_CHILDREN = -1,
+#define RUSAGE_CHILDREN RUSAGE_CHILDREN
+
+  /* Both.  */
+  RUSAGE_BOTH = -2
+#define RUSAGE_BOTH RUSAGE_BOTH
+};
+
+#define __need_timeval
+#include <bits/time.h>		/* For `struct timeval'.  */
+
+/* Structure which says how much of each resource has been used.  */
+struct rusage
+  {
+    /* Total amount of user time used.  */
+    struct timeval ru_utime;
+    /* Total amount of system time used.  */
+    struct timeval ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    long int ru_maxrss;
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    long int ru_ixrss;
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    long int ru_idrss;
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    long int ru_isrss;
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    long int ru_minflt;
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    long int ru_majflt;
+    /* Number of times a process was swapped out of physical memory.  */
+    long int ru_nswap;
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    long int ru_inblock;
+    /* Number of output operations via the file system.  */
+    long int ru_oublock;
+    /* Number of IPC messages sent.  */
+    long int ru_msgsnd;
+    /* Number of IPC messages received.  */
+    long int ru_msgrcv;
+    /* Number of signals delivered.  */
+    long int ru_nsignals;
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    long int ru_nvcsw;
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    long int ru_nivcsw;
+  };
+
+/* Priority limits.  */
+#define PRIO_MIN	-20	/* Minimum priority a process can have.  */
+#define PRIO_MAX	20	/* Maximum priority a process can have.  */
+
+/* The type of the WHICH argument to `getpriority' and `setpriority',
+   indicating what flavor of entity the WHO argument specifies.  */
+enum __priority_which
+{
+  PRIO_PROCESS = 0,		/* WHO is a process ID.  */
+#define PRIO_PROCESS PRIO_PROCESS
+  PRIO_PGRP = 1,		/* WHO is a process group ID.  */
+#define PRIO_PGRP PRIO_PGRP
+  PRIO_USER = 2			/* WHO is a user ID.  */
+#define PRIO_USER PRIO_USER
+};
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/resource.h b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
index abfe433c59..4d4eddb7aa 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
@@ -1,4 +1,4 @@
-/* Bit values & structures for resource limits.  Linux version.
+/* Bit values & structures for resource limits.  SPARC/Linux version.
    Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -21,7 +21,6 @@
 # error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
 #endif
 
-#include <asm/resource.h>
 #include <bits/types.h>
 
 /* Transmute defines to enumerations.  The macro re-definitions are
@@ -33,73 +32,51 @@
 enum __rlimit_resource
 {
   /* Per-process CPU limit, in seconds.  */
-  _RLIMIT_CPU = RLIMIT_CPU,
-#undef RLIMIT_CPU
-  RLIMIT_CPU = _RLIMIT_CPU,
+  RLIMIT_CPU = 0,
 #define RLIMIT_CPU RLIMIT_CPU
 
   /* Largest file that can be created, in bytes.  */
-  _RLIMIT_FSIZE = RLIMIT_FSIZE,
-#undef RLIMIT_FSIZE
-  RLIMIT_FSIZE = _RLIMIT_FSIZE,
+  RLIMIT_FSIZE = 1,
 #define	RLIMIT_FSIZE RLIMIT_FSIZE
 
   /* Maximum size of data segment, in bytes.  */
-  _RLIMIT_DATA = RLIMIT_DATA,
-#undef RLIMIT_DATA
-  RLIMIT_DATA = _RLIMIT_DATA,
+  RLIMIT_DATA = 2,
 #define	RLIMIT_DATA RLIMIT_DATA
 
   /* Maximum size of stack segment, in bytes.  */
-  _RLIMIT_STACK = RLIMIT_STACK,
-#undef RLIMIT_STACK
-  RLIMIT_STACK = _RLIMIT_STACK,
+  RLIMIT_STACK = 3,
 #define	RLIMIT_STACK RLIMIT_STACK
 
   /* Largest core file that can be created, in bytes.  */
-  _RLIMIT_CORE = RLIMIT_CORE,
-#undef RLIMIT_CORE
-  RLIMIT_CORE = _RLIMIT_CORE,
+  RLIMIT_CORE = 4,
 #define	RLIMIT_CORE RLIMIT_CORE
 
   /* Largest resident set size, in bytes.
      This affects swapping; processes that are exceeding their
      resident set size will be more likely to have physical memory
      taken from them.  */
-  _RLIMIT_RSS = RLIMIT_RSS,
-#undef RLIMIT_RSS
-  RLIMIT_RSS = _RLIMIT_RSS,
+  RLIMIT_RSS = 5,
 #define	RLIMIT_RSS RLIMIT_RSS
 
   /* Number of open files.  */
-  _RLIMIT_NOFILE = RLIMIT_NOFILE,
-#undef RLIMIT_NOFILE
-  RLIMIT_NOFILE = _RLIMIT_NOFILE,
+  RLIMIT_NOFILE = 6,
   RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
 #define RLIMIT_NOFILE RLIMIT_NOFILE
 #define RLIMIT_OFILE RLIMIT_OFILE
 
   /* Address space limit (?) */
-  _RLIMIT_AS = RLIMIT_AS,
-#undef RLIMIT_AS
-  RLIMIT_AS = _RLIMIT_AS,
+  RLIMIT_AS = 9,
 #define RLIMIT_AS RLIMIT_AS
 
   /* Number of processes.  */
-  _RLIMIT_NPROC = RLIMIT_NPROC,
-#undef RLIMIT_NPROC
-  RLIMIT_NPROC = _RLIMIT_NPROC,
+  RLIMIT_NPROC = 7,
 #define RLIMIT_NPROC RLIMIT_NPROC
 
   /* Locked-in-memory address space.  */
-  _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK,
-#undef RLIMIT_MEMLOCK
-  RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK,
+  RLIMIT_MEMLOCK = 8,
 #define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
 
-  RLIMIT_NLIMITS = RLIM_NLIMITS,
-#undef RLIM_NLIMITS
-  RLIM_NLIMITS = RLIMIT_NLIMITS
+  RLIM_NLIMITS = 10
 #define RLIMIT_NLIMITS RLIMIT_NLIMITS
 #define RLIM_NLIMITS RLIM_NLIMITS
 };
diff --git a/sysdeps/unix/sysv/linux/truncate64.c b/sysdeps/unix/sysv/linux/truncate64.c
index 42b72731a9..4fe446475a 100644
--- a/sysdeps/unix/sysv/linux/truncate64.c
+++ b/sysdeps/unix/sysv/linux/truncate64.c
@@ -43,6 +43,9 @@ truncate64 (path, length)
     {
       unsigned int low = length & 0xffffffff;
       unsigned int high = length >> 32;
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      int saved_errno = errno;
+#endif
       int result = INLINE_SYSCALL (truncate64, 3, path, low, high);
 
 #ifndef __ASSUME_TRUNCATE64_SYSCALL
@@ -51,6 +54,7 @@ truncate64 (path, length)
 	return result;
 
 #ifndef __ASSUME_TRUNCATE64_SYSCALL
+      __set_errno (saved_errno);
       have_no_truncate64 = 1;
 #endif
     }
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index 33f130bb68..07b7f208e4 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -1,5 +1,5 @@
 /* xstat64 using old-style Unix stat system call.
-   Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1991, 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
@@ -25,20 +25,49 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
-#include <xstatconv.c>
+#if __ASSUME_STAT64_SYSCALL == 0
+# include <xstatconv.c>
+#endif
 
 extern int __syscall_stat (const char *, struct kernel_stat *);
 
+#ifdef __NR_stat64
+extern int __syscall_fstat64 (int, struct stat64 *);
+# if  __ASSUME_STAT64_SYSCALL == 0
+/* The variable is shared between all wrappers around *stat64 calls.
+   This is the definition.  */
+int have_no_stat64;
+# endif
+#endif
+
 /* Get information about the file NAME in BUF.  */
+
 int
 __xstat64 (int vers, const char *name, struct stat64 *buf)
 {
+#if __ASSUME_STAT64_SYSCALL > 0
+  return INLINE_SYSCALL (stat64, 2, name, &buf);
+#else
   struct kernel_stat kbuf;
   int result;
+# if defined __NR_stat64
+  if (! have_no_stat64)
+    {
+      int saved_errno = errno;
+      result = INLINE_SYSCALL (stat64, 2, name, &buf);
+
+      if (result != -1 || errno != ENOSYS)
+	return result;
 
+      __set_errno (saved_errno);
+      have_no_stat64 = 1;
+    }
+# endif
+ 
   result = INLINE_SYSCALL (stat, 2, name, &kbuf);
   if (result == 0)
     result = xstat64_conv (vers, &kbuf, buf);
 
   return result;
+#endif
 }