about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--include/sys/stat.h4
-rw-r--r--sysdeps/posix/getcwd.c43
-rw-r--r--sysdeps/unix/rewinddir.c5
-rw-r--r--sysdeps/unix/sysv/linux/Makefile3
-rw-r--r--sysdeps/unix/sysv/linux/dl-fxstatat64.c6
-rw-r--r--sysdeps/unix/sysv/linux/dl-openat64.c40
-rw-r--r--sysdeps/unix/sysv/linux/dl-opendir.c6
-rw-r--r--sysdeps/unix/sysv/linux/getcwd.c8
9 files changed, 93 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 488ce8f187..345490185f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,15 +3,20 @@
 	[BZ #12713]
 	* sysdeps/unix/sysv/linux/getcwd.c: If getcwd syscall report
 	ENAMETOOLONG use generic getcwd.
-	* sysdeps/posix/getcwd.c: Add support to use openat.
+	* sysdeps/posix/getcwd.c: Add support to use openat.  Make usable
+	in rtld.  Use *stat64.
 	* sysdeps/unix/sysv/linux/Makefile [subdir=elf] (sysdep-rtld-routines):
-	Add dl-getcwd.
+	Add dl-getcwd, dl-openat64, dl-opendir, dl-fxstatat64.
 	* sysdeps/unix/sysv/linux/dl-getcwd.c: New file.
-	* include/sys/stat.h: Define __fstatat macro.
+	* sysdeps/unix/sysv/linux/dl-openat64.c: New file.
+	* sysdeps/unix/sysv/linux/dl-opendir.c: New file.
+	* sysdeps/unix/sysv/linux/dl-fxstat64.c: New file.
+	* include/sys/stat.h: Define __fstatat, __lstat64, __fstat64, and
+	__fstatat64 macros.
 	* include/dirent.h: Add libc_hidden_proto for rewinddir.
 	* dirent/rewinddir.c: Add libc_hidden_def.
 	* sysdeps/mach/hurd/rewinddir.c: Likewise.
-	* sysdeps/unix/rewinddir.c: Likewise.
+	* sysdeps/unix/rewinddir.c: Likewise.  Don't do locking outside libc.
 
 	* include/dirent.h (__alloc_dir): Add flags parameter.
 	* sysdeps/unix/fdopendir.c (__fdopendir): Pass flags to __alloc_dir.
diff --git a/include/sys/stat.h b/include/sys/stat.h
index e00df5381e..cca0500ec2 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -44,10 +44,14 @@ libc_hidden_proto (__fxstatat64)
 #define lstat(fname, buf)  __lxstat (_STAT_VER, fname, buf)
 #define __lstat(fname, buf)  __lxstat (_STAT_VER, fname, buf)
 #define lstat64(fname, buf)  __lxstat64 (_STAT_VER, fname, buf)
+#define __lstat64(fname, buf)  __lxstat64 (_STAT_VER, fname, buf)
 #define stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
 #define fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf)
+#define __fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf)
 #define fstat(fd, buf) __fxstat (_STAT_VER, fd, buf)
 #define __fstat(fd, buf) __fxstat (_STAT_VER, fd, buf)
 #define __fstatat(dfd, fname, buf, flag) \
   __fxstatat (_STAT_VER, dfd, fname, buf, flag)
+#define __fstatat64(dfd, fname, buf, flag) \
+  __fxstatat64 (_STAT_VER, dfd, fname, buf, flag)
 #endif
diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c
index f683158284..847abc56ca 100644
--- a/sysdeps/posix/getcwd.c
+++ b/sysdeps/posix/getcwd.c
@@ -172,10 +172,10 @@ extern char *alloca ();
 # include <sys/param.h>
 #endif
 
-#if defined _LIBC && !defined NOT_IN_libc
+#if defined _LIBC
 # include <not-cancel.h>
 #else
-# define openat_not_cancel_3(dfd, name, mode) openat (dfd, name, mode)
+# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
 # define close_not_cancel_no_status(fd) close (fd)
 #endif
 
@@ -197,7 +197,7 @@ extern char *alloca ();
 #endif
 
 #ifndef __GNU_LIBRARY__
-# define __lstat	stat
+# define __lstat64	stat64
 #endif
 
 #ifndef _LIBC
@@ -209,9 +209,10 @@ extern char *alloca ();
 #endif
 
 #ifdef __ASSUME_ATFCTS
-# define have_openat 1
-#else
-static int have_openat = 0;
+# define __have_atfcts 1
+#elif defined NOT_IN_libc && defined IS_IN_rtld
+static int __rtld_have_atfcts;
+# define __have_atfcts __rtld_have_atfcts
 #endif
 
 /* Get the pathname of the current working directory, and put it in SIZE
@@ -268,39 +269,39 @@ __getcwd (buf, size)
   char *pathp = path + allocated;
   *--pathp = '\0';
 
-  struct stat st;
-  if (__lstat (".", &st) < 0)
+  struct stat64 st;
+  if (__lstat64 (".", &st) < 0)
     goto lose;
   dev_t thisdev = st.st_dev;
   ino_t thisino = st.st_ino;
 
-  if (__lstat ("/", &st) < 0)
+  if (__lstat64 ("/", &st) < 0)
     goto lose;
   dev_t rootdev = st.st_dev;
   ino_t rootino = st.st_ino;
 
   while (!(thisdev == rootdev && thisino == rootino))
     {
-      if (have_openat >= 0)
+      if (__have_atfcts >= 0)
 	{
 	  int mode = O_RDONLY;
 #ifdef O_CLOEXEC
 	  mode |= O_CLOEXEC;
 #endif
-	  fd = openat_not_cancel_3 (fd, "..", mode);
+	  fd = openat64_not_cancel_3 (fd, "..", mode);
 	}
       else
 	fd = -1;
       if (fd >= 0)
 	{
 	  fd_needs_closing = true;
-	  if (__fstat (fd, &st) < 0)
+	  if (__fstat64 (fd, &st) < 0)
 	    goto lose;
 	}
 #ifndef __ASSUME_ATFCTS
       else if (errno == ENOSYS)
 	{
-	  have_openat = -1;
+	  __have_atfcts = -1;
 
 	  /* Look at the parent directory.  */
 	  if (dotp == dotlist)
@@ -345,7 +346,7 @@ __getcwd (buf, size)
 	  dotp -= 3;
 
 	  /* Figure out if this directory is a mount point.  */
-	  if (__lstat (dotp, &st) < 0)
+	  if (__lstat64 (dotp, &st) < 0)
 	    goto lose;
 	}
 #endif
@@ -363,7 +364,7 @@ __getcwd (buf, size)
       bool mount_point = dotdev != thisdev;
 
       /* Search for the last directory.  */
-      if (have_openat >= 0)
+      if (__have_atfcts >= 0)
 	dirstream = __fdopendir (fd);
 #ifndef __ASSUME_ATFCTS
       else
@@ -388,7 +389,7 @@ __getcwd (buf, size)
 		  /* When we've iterated through all directory entries
 		     without finding one with a matching d_ino, rewind the
 		     stream and consider each name again, but this time, using
-		     lstat.  This is necessary in a chroot on at least one
+		     lstat64.  This is necessary in a chroot on at least one
 		     system.  */
 		  if (use_d_ino)
 		    {
@@ -413,14 +414,14 @@ __getcwd (buf, size)
 	  if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino)
 	    continue;
 
-	  if (have_openat >= 0)
+	  if (__have_atfcts >= 0)
 	    {
-	      /* We don't fail here if we cannot stat() a directory entry.
+	      /* We don't fail here if we cannot stat64() a directory entry.
 		 This can happen when (network) filesystems fail.  If this
 		 entry is in fact the one we are looking for we will find
 		 out soon as we reach the end of the directory without
 		 having found anything.  */
-	      if (__fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
+	      if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
 		continue;
 	    }
 #ifndef __ASSUME_ATFCTS
@@ -436,12 +437,12 @@ __getcwd (buf, size)
 	      name[dotlist + dotsize - dotp] = '/';
 	      strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name);
 # endif
-	      /* We don't fail here if we cannot stat() a directory entry.
+	      /* We don't fail here if we cannot stat64() a directory entry.
 		 This can happen when (network) filesystems fail.  If this
 		 entry is in fact the one we are looking for we will find
 		 out soon as we reach the end of the directory without
 		 having found anything.  */
-	      if (__lstat (name, &st) < 0)
+	      if (__lstat64 (name, &st) < 0)
 		continue;
 	    }
 #endif
diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
index 89b0e6d20d..967289364e 100644
--- a/sysdeps/unix/rewinddir.c
+++ b/sysdeps/unix/rewinddir.c
@@ -23,16 +23,19 @@
 #include <dirstream.h>
 
 /* Rewind DIRP to the beginning of the directory.  */
-/* XXX should be __rewinddir ? */
 void
 rewinddir (dirp)
      DIR *dirp;
 {
+#ifndef NOT_IN_libc
   __libc_lock_lock (dirp->lock);
+#endif
   (void) __lseek (dirp->fd, (off_t) 0, SEEK_SET);
   dirp->filepos = 0;
   dirp->offset = 0;
   dirp->size = 0;
+#ifndef NOT_IN_libc
   __libc_lock_unlock (dirp->lock);
+#endif
 }
 libc_hidden_def (rewinddir)
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 61fbfb4fc8..3b4b63f844 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -147,7 +147,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
 endif
 
 ifeq ($(subdir),elf)
-sysdep-rtld-routines += dl-brk dl-sbrk dl-getcwd
+sysdep-rtld-routines += dl-brk dl-sbrk dl-getcwd dl-openat64 dl-opendir \
+			dl-fxstatat64
 
 CPPFLAGS-lddlibc4 += -DNOT_IN_libc
 endif
diff --git a/sysdeps/unix/sysv/linux/dl-fxstatat64.c b/sysdeps/unix/sysv/linux/dl-fxstatat64.c
new file mode 100644
index 0000000000..9a17a9b739
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-fxstatat64.c
@@ -0,0 +1,6 @@
+/* In this implementation we do not really care whether the call fails
+   because of missing kernel support since we do not even call the
+   function in this case.  */
+#undef __ASSUME_ATFCTS
+#define __ASSUME_ATFCTS 1
+#include "fxstatat64.c"
diff --git a/sysdeps/unix/sysv/linux/dl-openat64.c b/sysdeps/unix/sysv/linux/dl-openat64.c
new file mode 100644
index 0000000000..ca296fd7ca
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-openat64.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gmain.com>, 2003.
+
+   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 <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sysdep.h>
+
+
+int
+openat64 (dfd, file, oflag)
+     int dfd;
+     const char *file;
+     int oflag;
+{
+  assert ((oflag & O_CREAT) == 0);
+
+#ifdef __NR_openat
+  return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE);
+#else
+  __set_errno (ENOSYS);
+  return -1;
+#endif
+}
diff --git a/sysdeps/unix/sysv/linux/dl-opendir.c b/sysdeps/unix/sysv/linux/dl-opendir.c
new file mode 100644
index 0000000000..72d2c06cdc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-opendir.c
@@ -0,0 +1,6 @@
+/* In this implementation we do not really care whether the opened
+   file descriptor has the CLOEXEC bit set.  The only call happens
+   long before there is a call to fork or exec.  */
+#undef __ASSUME_O_CLOEXEC
+#define __ASSUME_O_CLOEXEC 1
+#include <opendir.c>
diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
index db3e292964..fb0dcefd58 100644
--- a/sysdeps/unix/sysv/linux/getcwd.c
+++ b/sysdeps/unix/sysv/linux/getcwd.c
@@ -124,9 +124,6 @@ __getcwd (char *buf, size_t size)
 	  return buf;
 	}
 
-      // XXX This should not be necessary but the full getcwd implementation
-      // drags in too much for the current build proces of ld.so to handle
-#ifndef NOT_IN_libc
       /* The system call cannot handle paths longer than a page.
 	 Neither can the magic symlink in /proc/self.  Just use the
 	 generic implementation right away.  */
@@ -149,7 +146,6 @@ __getcwd (char *buf, size_t size)
 
 	  return result;
 	}
-#endif
 
 # if __ASSUME_GETCWD_SYSCALL
       /* It should never happen that the `getcwd' syscall failed because
@@ -241,11 +237,7 @@ __getcwd (char *buf, size_t size)
 }
 weak_alias (__getcwd, getcwd)
 
-      // XXX This should not be necessary but the full getcwd implementation
-      // drags in too much for the current build proces of ld.so to handle
-#ifndef NOT_IN_libc
 /* Get the code for the generic version.  */
 #define GETCWD_RETURN_TYPE	static char * internal_function
 #define __getcwd		generic_getcwd
 #include <sysdeps/posix/getcwd.c>
-#endif