bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH] getcwd: on Solaris, work better if ancestors are inaccessible


From: Paul Eggert
Subject: [PATCH] getcwd: on Solaris, work better if ancestors are inaccessible
Date: Wed, 14 Jul 2010 00:12:43 -0700
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100527 Thunderbird/3.0.5

I installed this, for tar's sake:

>From b1ef417aa5830669125c4f4aafd0a163c8902125 Mon Sep 17 00:00:00 2001
From: Paul R. Eggert <address@hidden>
Date: Wed, 14 Jul 2010 00:06:03 -0700
Subject: [PATCH] getcwd: on Solaris, work better if ancestors are inaccessible

* lib/getcwd.c (__getcwd): If getcwd returns EINVAL for zero
buffer and size, try again with a large buffer.  This works better
on Solaris, since its getcwd succeeds even if the path to the root
is inaccessible, and this is helpful in common cases such as .zfs
hidden directories.  Problem reported by J Chapman Flack in
http://lists.gnu.org/archive/html/bug-tar/2010-06/msg00000.html
Use system getcwd if it's declared, not merely if it's partly
working; use the partly-working test only to avoid needless effort
if the system getcwd fails.
* m4/getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Omit
comment that was already obsolete and is now even more obsolete.
* modules/getcwd (Depends-on): Depend on strdup, since __getcwd
now might call strdup.
---
 ChangeLog             |   17 +++++++++++++++++
 lib/getcwd.c          |   33 +++++++++++++++++++++++++--------
 m4/getcwd-path-max.m4 |    4 +---
 modules/getcwd        |    1 +
 4 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b8c73c5..c1adeac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2010-07-14  Paul R. Eggert  <address@hidden>
+
+       getcwd: on Solaris, work better if ancestors are inaccessible
+       * lib/getcwd.c (__getcwd): If getcwd returns EINVAL for zero
+       buffer and size, try again with a large buffer.  This works better
+       on Solaris, since its getcwd succeeds even if the path to the root
+       is inaccessible, and this is helpful in common cases such as .zfs
+       hidden directories.  Problem reported by J Chapman Flack in
+       http://lists.gnu.org/archive/html/bug-tar/2010-06/msg00000.html
+       Use system getcwd if it's declared, not merely if it's partly
+       working; use the partly-working test only to avoid needless effort
+       if the system getcwd fails.
+       * m4/getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Omit
+       comment that was already obsolete and is now even more obsolete.
+       * modules/getcwd (Depends-on): Depend on strdup, since __getcwd
+       now might call strdup.
+
 2010-07-13  Paul R. Eggert  <address@hidden>
 
        pthread: Add enough so that coreutils/src/sort.c compiles.
diff --git a/lib/getcwd.c b/lib/getcwd.c
index 1ba705c..7d47072 100644
--- a/lib/getcwd.c
+++ b/lib/getcwd.c
@@ -136,13 +136,11 @@ __getcwd (char *buf, size_t size)
   size_t allocated = size;
   size_t used;
 
-#if HAVE_PARTLY_WORKING_GETCWD
-  /* The system getcwd works, except it sometimes fails when it
-     shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.  If
-     AT_FDCWD is not defined, the algorithm below is O(N**2) and this
-     is much slower than the system getcwd (at least on GNU/Linux).
-     So trust the system getcwd's results unless they look
-     suspicious.
+#if HAVE_RAW_DECL_GETCWD
+  /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and
+     this is much slower than the system getcwd (at least on
+     GNU/Linux).  So trust the system getcwd's results unless they
+     look suspicious.
 
      Use the system getcwd even if we have openat support, since the
      system getcwd works even when a parent is unreadable, while the
@@ -150,8 +148,27 @@ __getcwd (char *buf, size_t size)
 
 # undef getcwd
   dir = getcwd (buf, size);
-  if (dir || (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT))
+  if (dir)
     return dir;
+
+  /* Solaris getcwd (NULL, 0) fails with errno == EINVAL, but it has
+     internal magic that lets it work even if an ancestor directory is
+     inaccessible, which is better in many cases.  So in this case try
+     again with a buffer that's almost always big enough.  */
+  if (errno == EINVAL && buf == NULL && size == 0)
+    {
+      char big_buffer[BIG_FILE_NAME_LENGTH + 1];
+      dir = getcwd (big_buffer, sizeof big_buffer);
+      if (dir)
+        return strdup (dir);
+    }
+
+# if HAVE_PARTLY_WORKING_GETCWD
+  /* The system getcwd works, except it sometimes fails when it
+     shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.    */
+  if (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT)
+    return NULL;
+# endif
 #endif
 
   if (size == 0)
diff --git a/m4/getcwd-path-max.m4 b/m4/getcwd-path-max.m4
index ecf6192..04ff141 100644
--- a/m4/getcwd-path-max.m4
+++ b/m4/getcwd-path-max.m4
@@ -183,8 +183,6 @@ main ()
   no,*)
     AC_DEFINE([HAVE_PARTLY_WORKING_GETCWD], [1],
       [Define to 1 if getcwd works, except it sometimes fails when it 
shouldn't,
-       setting errno to ERANGE, ENAMETOOLONG, or ENOENT.  If __GETCWD_PREFIX
-       is not defined, it doesn't matter whether HAVE_PARTLY_WORKING_GETCWD
-       is defined.]);;
+       setting errno to ERANGE, ENAMETOOLONG, or ENOENT.]);;
   esac
 ])
diff --git a/modules/getcwd b/modules/getcwd
index cec9e2a..c1544f5 100644
--- a/modules/getcwd
+++ b/modules/getcwd
@@ -17,6 +17,7 @@ openat
 stdbool
 unistd
 malloc-posix
+strdup-posix
 
 configure.ac:
 gl_FUNC_GETCWD
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]