[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r13729 - in /fsf/trunk/libc: ./ dirent/ include/ include/sys/ localedata/ sysdeps/mach/hurd/ sysdeps/posix/ sysdeps/unix/ sy...



Author: eglibc
Date: Mon May  9 00:03:12 2011
New Revision: 13729

Log:
Import glibc-mainline for 2011-05-09

Added:
    fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-fxstatat64.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-getcwd.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-openat64.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-opendir.c
Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/NEWS
    fsf/trunk/libc/dirent/rewinddir.c
    fsf/trunk/libc/include/dirent.h
    fsf/trunk/libc/include/sys/stat.h
    fsf/trunk/libc/localedata/ChangeLog
    fsf/trunk/libc/localedata/SUPPORTED
    fsf/trunk/libc/sysdeps/mach/hurd/rewinddir.c
    fsf/trunk/libc/sysdeps/posix/getcwd.c
    fsf/trunk/libc/sysdeps/unix/rewinddir.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile
    fsf/trunk/libc/sysdeps/unix/sysv/linux/getcwd.c

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Mon May  9 00:03:12 2011
@@ -1,4 +1,22 @@
 2011-05-08  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	[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.  Make usable
+	in rtld.  Use *stat64.
+	* sysdeps/unix/sysv/linux/Makefile [subdir=elf] (sysdep-rtld-routines):
+	Add dl-getcwd, dl-openat64, dl-opendir, dl-fxstatat64.
+	* sysdeps/unix/sysv/linux/dl-getcwd.c: New file.
+	* 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.  Don't do locking outside libc.
 
 	* include/dirent.h (__alloc_dir): Add flags parameter.
 	* sysdeps/unix/fdopendir.c (__fdopendir): Pass flags to __alloc_dir.

Modified: fsf/trunk/libc/NEWS
==============================================================================
--- fsf/trunk/libc/NEWS (original)
+++ fsf/trunk/libc/NEWS Mon May  9 00:03:12 2011
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2011-5-7
+GNU C Library NEWS -- history of user-visible changes.  2011-5-8
 Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -23,8 +23,8 @@
 * The following bugs are resolved with this release:
 
   11724, 12393, 12420, 12445, 12454, 12460, 12469, 12489, 12509, 12510,
-  12518, 12583, 12587, 12597, 12631, 12650, 12653, 12655, 12685, 12714,
-  12717, 12723, 12734
+  12518, 12583, 12587, 12597, 12631, 12650, 12653, 12655, 12685, 12713,
+  12714, 12717, 12723, 12734
 
 Version 2.13
 

Modified: fsf/trunk/libc/dirent/rewinddir.c
==============================================================================
--- fsf/trunk/libc/dirent/rewinddir.c (original)
+++ fsf/trunk/libc/dirent/rewinddir.c Mon May  9 00:03:12 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995, 1996, 1997, 2011 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
@@ -29,6 +29,7 @@
   __set_errno (ENOSYS);
   /* No way to indicate failure.	*/
 }
+libc_hidden_def (rewinddir)
 
 
 stub_warning (rewinddir)

Modified: fsf/trunk/libc/include/dirent.h
==============================================================================
--- fsf/trunk/libc/include/dirent.h (original)
+++ fsf/trunk/libc/include/dirent.h Mon May  9 00:03:12 2011
@@ -32,4 +32,6 @@
 			 const struct stat64 *statp)
      internal_function;
 
+libc_hidden_proto (rewinddir)
+
 #endif

Modified: fsf/trunk/libc/include/sys/stat.h
==============================================================================
--- fsf/trunk/libc/include/sys/stat.h (original)
+++ fsf/trunk/libc/include/sys/stat.h Mon May  9 00:03:12 2011
@@ -44,8 +44,14 @@
 #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

Modified: fsf/trunk/libc/localedata/ChangeLog
==============================================================================
--- fsf/trunk/libc/localedata/ChangeLog (original)
+++ fsf/trunk/libc/localedata/ChangeLog Mon May  9 00:03:12 2011
@@ -1,3 +1,8 @@
+2010-12-02  Andreas Schwab  <schwab@xxxxxxxxxx>
+
+	* SUPPORTED: Remove .UTF-8 suffix from az_AZ, as_IN, tt_RU locale
+	names.
+
 2010-05-17  Andreas Schwab  <schwab@xxxxxxxxxx>
 
 	* locales/es_CR (LC_ADDRESS): Fix character names in lang_ab.

Modified: fsf/trunk/libc/localedata/SUPPORTED
==============================================================================
--- fsf/trunk/libc/localedata/SUPPORTED (original)
+++ fsf/trunk/libc/localedata/SUPPORTED Mon May  9 00:03:12 2011
@@ -46,8 +46,8 @@
 ar_TN/ISO-8859-6 \
 ar_YE.UTF-8/UTF-8 \
 ar_YE/ISO-8859-6 \
-az_AZ.UTF-8/UTF-8 \
-as_IN.UTF-8/UTF-8 \
+az_AZ/UTF-8 \
+as_IN/UTF-8 \
 ast_ES.UTF-8/UTF-8 \
 ast_ES/ISO-8859-15 \
 be_BY.UTF-8/UTF-8 \
@@ -385,8 +385,8 @@
 tr_TR.UTF-8/UTF-8 \
 tr_TR/ISO-8859-9 \
 ts_ZA/UTF-8 \
-tt_RU.UTF-8/UTF-8 \
-tt_RU.UTF-8@iqtelif/UTF-8 \
+tt_RU/UTF-8 \
+tt_RU@iqtelif/UTF-8 \
 ug_CN/UTF-8 \
 uk_UA.UTF-8/UTF-8 \
 uk_UA/KOI8-U \

Modified: fsf/trunk/libc/sysdeps/mach/hurd/rewinddir.c
==============================================================================
--- fsf/trunk/libc/sysdeps/mach/hurd/rewinddir.c (original)
+++ fsf/trunk/libc/sysdeps/mach/hurd/rewinddir.c Mon May  9 00:03:12 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1997, 2011 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,10 +22,10 @@
 #include <unistd.h>
 
 /* Rewind DIRP to the beginning of the directory.  */
-/* XXX should be __rewinddir ? */
 void
 rewinddir (dirp)
      DIR *dirp;
 {
   seekdir (dirp, (off_t) 0L);
 }
+libc_hidden_def (rewinddir)

Modified: fsf/trunk/libc/sysdeps/posix/getcwd.c
==============================================================================
--- fsf/trunk/libc/sysdeps/posix/getcwd.c (original)
+++ fsf/trunk/libc/sysdeps/posix/getcwd.c Mon May  9 00:03:12 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99,11 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
@@ -35,6 +35,7 @@
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -171,6 +172,13 @@
 # include <sys/param.h>
 #endif
 
+#if defined _LIBC
+# include <not-cancel.h>
+#else
+# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
+# define close_not_cancel_no_status(fd) close (fd)
+#endif
+
 #ifndef PATH_MAX
 # ifdef	MAXPATHLEN
 #  define PATH_MAX MAXPATHLEN
@@ -189,7 +197,7 @@
 #endif
 
 #ifndef __GNU_LIBRARY__
-# define __lstat	stat
+# define __lstat64	stat64
 #endif
 
 #ifndef _LIBC
@@ -198,6 +206,13 @@
 
 #ifndef GETCWD_RETURN_TYPE
 # define GETCWD_RETURN_TYPE char *
+#endif
+
+#ifdef __ASSUME_ATFCTS
+# 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
@@ -211,6 +226,7 @@
      char *buf;
      size_t size;
 {
+#ifndef __ASSUME_ATFCTS
   static const char dots[]
     = "../../../../../../../../../../../../../../../../../../../../../../../\
 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
@@ -218,14 +234,15 @@
   const char *dotp = &dots[sizeof (dots)];
   const char *dotlist = dots;
   size_t dotsize = sizeof (dots) - 1;
-  dev_t rootdev, thisdev;
-  ino_t rootino, thisino;
+#endif
+  int prev_errno = errno;
+  DIR *dirstream = NULL;
+  bool fd_needs_closing = false;
+  int fd = AT_FDCWD;
+
   char *path;
-  register char *pathp;
-  struct stat st;
-  int prev_errno = errno;
+#ifndef NO_ALLOCATION
   size_t allocated = size;
-
   if (size == 0)
     {
       if (buf != NULL)
@@ -237,189 +254,285 @@
       allocated = PATH_MAX + 1;
     }
 
-  if (buf != NULL)
-    path = buf;
-  else
+  if (buf == NULL)
     {
       path = malloc (allocated);
       if (path == NULL)
 	return NULL;
     }
-
-  pathp = path + allocated;
+  else
+#else
+# define allocated size
+#endif
+    path = buf;
+
+  char *pathp = path + allocated;
   *--pathp = '\0';
 
-  if (__lstat (".", &st) < 0)
-    goto lose2;
-  thisdev = st.st_dev;
-  thisino = st.st_ino;
-
-  if (__lstat ("/", &st) < 0)
-    goto lose2;
-  rootdev = st.st_dev;
-  rootino = st.st_ino;
+  struct stat64 st;
+  if (__lstat64 (".", &st) < 0)
+    goto lose;
+  dev_t thisdev = st.st_dev;
+  ino_t thisino = st.st_ino;
+
+  if (__lstat64 ("/", &st) < 0)
+    goto lose;
+  dev_t rootdev = st.st_dev;
+  ino_t rootino = st.st_ino;
 
   while (!(thisdev == rootdev && thisino == rootino))
     {
-      register DIR *dirstream;
-      struct dirent *d;
-      dev_t dotdev;
-      ino_t dotino;
-      char mount_point;
-
-      /* Look at the parent directory.  */
-      if (dotp == dotlist)
-	{
-	  /* My, what a deep directory tree you have, Grandma.  */
-	  char *new;
-	  if (dotlist == dots)
+      if (__have_atfcts >= 0)
+	{
+	  int mode = O_RDONLY;
+#ifdef O_CLOEXEC
+	  mode |= O_CLOEXEC;
+#endif
+	  fd = openat64_not_cancel_3 (fd, "..", mode);
+	}
+      else
+	fd = -1;
+      if (fd >= 0)
+	{
+	  fd_needs_closing = true;
+	  if (__fstat64 (fd, &st) < 0)
+	    goto lose;
+	}
+#ifndef __ASSUME_ATFCTS
+      else if (errno == ENOSYS)
+	{
+	  __have_atfcts = -1;
+
+	  /* Look at the parent directory.  */
+	  if (dotp == dotlist)
 	    {
-	      new = malloc (dotsize * 2 + 1);
-	      if (new == NULL)
-		goto lose;
-#ifdef HAVE_MEMPCPY
-	      dotp = mempcpy (new, dots, dotsize);
-#else
-	      memcpy (new, dots, dotsize);
-	      dotp = &new[dotsize];
-#endif
+# ifdef NO_ALLOCATION
+	      __set_errno (ENOMEM);
+	      goto lose;
+# else
+	      /* My, what a deep directory tree you have, Grandma.  */
+	      char *new;
+	      if (dotlist == dots)
+		{
+		  new = malloc (dotsize * 2 + 1);
+		  if (new == NULL)
+		    goto lose;
+#  ifdef HAVE_MEMPCPY
+		  dotp = mempcpy (new, dots, dotsize);
+#  else
+		  memcpy (new, dots, dotsize);
+		  dotp = &new[dotsize];
+#  endif
+		}
+	      else
+		{
+		  new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1);
+		  if (new == NULL)
+		    goto lose;
+		  dotp = &new[dotsize];
+		}
+#  ifdef HAVE_MEMPCPY
+	      *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0';
+	      dotsize *= 2;
+#  else
+	      memcpy ((char *) dotp, new, dotsize);
+	      dotsize *= 2;
+	      new[dotsize] = '\0';
+#  endif
+	      dotlist = new;
+# endif
 	    }
-	  else
-	    {
-	      new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1);
-	      if (new == NULL)
-		goto lose;
-	      dotp = &new[dotsize];
-	    }
-#ifdef HAVE_MEMPCPY
-	  *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0';
-	  dotsize *= 2;
-#else
-	  memcpy ((char *) dotp, new, dotsize);
-	  dotsize *= 2;
-	  new[dotsize] = '\0';
-#endif
-	  dotlist = new;
+
+	  dotp -= 3;
+
+	  /* Figure out if this directory is a mount point.  */
+	  if (__lstat64 (dotp, &st) < 0)
+	    goto lose;
 	}
-
-      dotp -= 3;
-
-      /* Figure out if this directory is a mount point.  */
-      if (__lstat (dotp, &st) < 0)
+#endif
+      else
 	goto lose;
-      dotdev = st.st_dev;
-      dotino = st.st_ino;
-      mount_point = dotdev != thisdev;
+
+      if (dirstream && __closedir (dirstream) != 0)
+	{
+	  dirstream = NULL;
+	  goto lose;
+       }
+
+      dev_t dotdev = st.st_dev;
+      ino_t dotino = st.st_ino;
+      bool mount_point = dotdev != thisdev;
 
       /* Search for the last directory.  */
-      dirstream = __opendir (dotp);
+      if (__have_atfcts >= 0)
+	dirstream = __fdopendir (fd);
+#ifndef __ASSUME_ATFCTS
+      else
+	dirstream = __opendir (dotp);
+#endif
       if (dirstream == NULL)
 	goto lose;
-      /* Clear errno to distinguish EOF from error if readdir returns
-	 NULL.  */
-      __set_errno (0);
-      while ((d = __readdir (dirstream)) != NULL)
-	{
-	  if (d->d_name[0] == '.' &&
-	      (d->d_name[1] == '\0' ||
-	       (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+      fd_needs_closing = false;
+
+      struct dirent *d;
+      bool use_d_ino = true;
+      while (1)
+	{
+	  /* Clear errno to distinguish EOF from error if readdir returns
+	     NULL.  */
+	  __set_errno (0);
+	  d = __readdir (dirstream);
+	  if (d == NULL)
+	    {
+	      if (errno == 0)
+		{
+		  /* 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
+		     lstat64.  This is necessary in a chroot on at least one
+		     system.  */
+		  if (use_d_ino)
+		    {
+		      use_d_ino = false;
+		      rewinddir (dirstream);
+		      continue;
+		    }
+
+		  /* EOF on dirstream, which means that the current directory
+		     has been removed.  */
+		  __set_errno (ENOENT);
+		}
+	      goto lose;
+	    }
+
+	  if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN)
 	    continue;
-	  if (mount_point || (ino_t) d->d_ino == thisino)
+	  if (d->d_name[0] == '.'
+	      && (d->d_name[1] == '\0'
+		  || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+	    continue;
+	  if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino)
+	    continue;
+
+	  if (__have_atfcts >= 0)
 	    {
-	      char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN (d)];
-#ifdef HAVE_MEMPCPY
-	      char *tmp = mempcpy (name, dotp, dotlist + dotsize - dotp);
-	      *tmp++ = '/';
-	      strcpy (tmp, d->d_name);
-#else
-	      memcpy (name, dotp, dotlist + dotsize - dotp);
-	      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
-		  && st.st_dev == thisdev && st.st_ino == thisino)
-		break;
+	      if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
+		continue;
+	    }
+#ifndef __ASSUME_ATFCTS
+	  else
+	    {
+	      char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN (d)];
+# ifdef HAVE_MEMPCPY
+	      char *tmp = mempcpy (name, dotp, dotlist + dotsize - dotp);
+	      *tmp++ = '/';
+	      strcpy (tmp, d->d_name);
+# else
+	      memcpy (name, dotp, dotlist + dotsize - dotp);
+	      name[dotlist + dotsize - dotp] = '/';
+	      strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name);
+# endif
+	      /* 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 (__lstat64 (name, &st) < 0)
+		continue;
+	    }
+#endif
+	  if (S_ISDIR (st.st_mode)
+	      && st.st_dev == thisdev && st.st_ino == thisino)
+	    break;
+	}
+
+      size_t namlen = _D_EXACT_NAMLEN (d);
+
+      if ((size_t) (pathp - path) <= namlen)
+	{
+#ifndef NO_ALLOCATION
+	  if (size == 0)
+	    {
+	      size_t oldsize = allocated;
+
+	      allocated = 2 * MAX (allocated, namlen);
+	      char *tmp = realloc (path, allocated);
+	      if (tmp == NULL)
+		goto lose;
+
+	      /* Move current contents up to the end of the buffer.
+		 This is guaranteed to be non-overlapping.  */
+	      pathp = memcpy (tmp + allocated - (path + oldsize - pathp),
+			      tmp + (pathp - path),
+			      path + oldsize - pathp);
+	      path = tmp;
+	    }
+	  else
+#endif
+	    {
+	      __set_errno (ERANGE);
+	      goto lose;
 	    }
 	}
-      if (d == NULL)
-	{
-	  int save = errno;
-	  (void) __closedir (dirstream);
-	  if (save == 0)
-	    /* EOF on dirstream, which means that the current directory
-	       has been removed.  */
-	    save = ENOENT;
-	  __set_errno (save);
-	  goto lose;
-	}
-      else
-	{
-	  size_t namlen = _D_EXACT_NAMLEN (d);
-
-	  if ((size_t) (pathp - path) <= namlen)
-	    {
-	      if (size != 0)
-		{
-		  (void) __closedir (dirstream);
-		  __set_errno (ERANGE);
-		  goto lose;
-		}
-	      else
-		{
-		  char *tmp;
-		  size_t oldsize = allocated;
-
-		  allocated = 2 * MAX (allocated, namlen);
-		  tmp = realloc (path, allocated);
-		  if (tmp == NULL)
-		    {
-		      (void) __closedir (dirstream);
-		      __set_errno (ENOMEM);/* closedir might have changed it.*/
-		      goto lose;
-		    }
-
-		  /* Move current contents up to the end of the buffer.
-		     This is guaranteed to be non-overlapping.  */
-		  pathp = memcpy (tmp + allocated - (path + oldsize - pathp),
-				  tmp + (pathp - path),
-				  path + oldsize - pathp);
-		  path = tmp;
-		}
-	    }
-	  pathp -= namlen;
-	  (void) memcpy (pathp, d->d_name, namlen);
-	  *--pathp = '/';
-	  (void) __closedir (dirstream);
-	}
+      pathp -= namlen;
+      (void) memcpy (pathp, d->d_name, namlen);
+      *--pathp = '/';
 
       thisdev = dotdev;
       thisino = dotino;
     }
 
+  if (dirstream != NULL && __closedir (dirstream) != 0)
+    {
+      dirstream = NULL;
+      goto lose;
+    }
+
   if (pathp == &path[allocated - 1])
     *--pathp = '/';
 
+#ifndef __ASSUME_ATFCTS
   if (dotlist != dots)
     free ((__ptr_t) dotlist);
-
-  memmove (path, pathp, path + allocated - pathp);
+#endif
+
+  size_t used = path + allocated - pathp;
+  memmove (path, pathp, used);
+
+  if (size == 0)
+    /* Ensure that the buffer is only as large as necessary.  */
+    buf = realloc (path, used);
+
+  if (buf == NULL)
+    /* Either buf was NULL all along, or `realloc' failed but
+       we still have the original string.  */
+    buf = path;
 
   /* Restore errno on successful return.  */
   __set_errno (prev_errno);
 
-  return path;
-
- lose:
+  return buf;
+
+ lose:;
+  int save_errno = errno;
+#ifndef __ASSUME_ATFCTS
   if (dotlist != dots)
     free ((__ptr_t) dotlist);
- lose2:
+#endif
+  if (dirstream != NULL)
+    __closedir (dirstream);
+  if (fd_needs_closing)
+    close_not_cancel_no_status (fd);
+#ifndef NO_ALLOCATION
   if (buf == NULL)
     free (path);
+#endif
+  __set_errno (save_errno);
   return NULL;
 }
 

Modified: fsf/trunk/libc/sysdeps/unix/rewinddir.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/rewinddir.c (original)
+++ fsf/trunk/libc/sysdeps/unix/rewinddir.c Mon May  9 00:03:12 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995-1998, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995-1998, 2005, 2011 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -23,15 +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)

Modified: fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile (original)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile Mon May  9 00:03:12 2011
@@ -147,7 +147,8 @@
 endif
 
 ifeq ($(subdir),elf)
-sysdep-rtld-routines += dl-brk dl-sbrk
+sysdep-rtld-routines += dl-brk dl-sbrk dl-getcwd dl-openat64 dl-opendir \
+			dl-fxstatat64
 
 CPPFLAGS-lddlibc4 += -DNOT_IN_libc
 endif

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-fxstatat64.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-fxstatat64.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-fxstatat64.c Mon May  9 00:03:12 2011
@@ -1,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"

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-getcwd.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-getcwd.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-getcwd.c Mon May  9 00:03:12 2011
@@ -1,0 +1,1 @@
+#include "getcwd.c"

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-openat64.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-openat64.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-openat64.c Mon May  9 00:03:12 2011
@@ -1,0 +1,40 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@xxxxxxxxx>, 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
+}

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-opendir.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-opendir.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/dl-opendir.c Mon May  9 00:03:12 2011
@@ -1,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>

Modified: fsf/trunk/libc/sysdeps/unix/sysv/linux/getcwd.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/getcwd.c (original)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/getcwd.c Mon May  9 00:03:12 2011
@@ -1,5 +1,5 @@
 /* Determine current working directory.  Linux version.
-   Copyright (C) 1997,1998,1999,2000,2002,2003,2006
+   Copyright (C) 1997,1998,1999,2000,2002,2003,2006,2011
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1997.
@@ -45,9 +45,21 @@
    compiling under 2.1.92+ the libc still runs under older kernels. */
 # 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
+# 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.
+   An additional problem is that the system call does not return
+   the path of directories longer than one page.  */
+static int no_syscall_getcwd;
+static int have_new_dcache;
+# else
+#  define no_syscall_getcwd 1
+static int have_new_dcache = 1;
+# endif
+#endif
+
 /* 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
@@ -55,18 +67,6 @@
    the proc filesystem mounted.  Use the POSIX implementation in this case.  */
 static char *generic_getcwd (char *buf, size_t size) internal_function;
 
-# 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. */
-static int no_syscall_getcwd;
-static int have_new_dcache;
-# else
-#  define no_syscall_getcwd 1
-static int have_new_dcache = 1;
-# endif
-#endif
-
 char *
 __getcwd (char *buf, size_t size)
 {
@@ -122,6 +122,29 @@
 # endif
 
 	  return buf;
+	}
+
+      /* 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.  */
+      if (errno == ENAMETOOLONG)
+	{
+# ifndef NO_ALLOCATION
+	  if (buf == NULL && size == 0)
+	    {
+	      free (path);
+	      path = NULL;
+	    }
+# endif
+
+	  result = generic_getcwd (path, size);
+
+# ifndef NO_ALLOCATION
+	  if (result == NULL && buf == NULL && size != 0)
+	    free (path);
+# endif
+
+	  return result;
 	}
 
 # if __ASSUME_GETCWD_SYSCALL
@@ -196,7 +219,7 @@
 
 #ifndef NO_ALLOCATION
   /* Don't put restrictions on the length of the path unless the user does.  */
-  if (size == 0)
+  if (buf == NULL && size == 0)
     {
       free (path);
       path = NULL;
@@ -214,9 +237,7 @@
 }
 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>
-#endif
+#define GETCWD_RETURN_TYPE	static char * internal_function
+#define __getcwd		generic_getcwd
+#include <sysdeps/posix/getcwd.c>