+2010-07-14 Paul R. Eggert <eggert@cs.ucla.edu>
+
+ 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 <eggert@cs.ucla.edu>
pthread: Add enough so that coreutils/src/sort.c compiles.
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
# 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)
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
])