summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-11-21 00:56:11 +0100
committerBruno Haible <bruno@clisp.org>2011-11-21 00:56:11 +0100
commit69dba6d784566248205fc990673c14d259c4907f (patch)
tree13a28c016f375c5a7178490ce6c19254e71e76c9
parent4b79a20516739258867f4cfc629d6f646f2b260e (diff)
downloadgnulib-69dba6d784566248205fc990673c14d259c4907f.tar.gz
getcwd: Work around getcwd bug on AIX 5..7.
* m4/getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Require AC_CANONICAL_HOST. Assign exit code 31 to the bug seen on AIX 5.1..7.1. Use a different value for gl_cv_func_getcwd_path_max. Move the definition of HAVE_PARTLY_WORKING_GETCWD from here... * m4/getcwd.m4 (gl_FUNC_GETCWD): ... to here. Invoke gl_FUNC_GETCWD_PATH_MAX also when $gl_cv_func_getcwd_null is 'no'. Define HAVE_MINIMALLY_WORKING_GETCWD. * lib/getcwd.c (__getcwd): Don't use the system's getcwd on platforms where it is not even minimally working, that is, on AIX. * tests/test-getcwd.c (test_long_name): Distinguish the same cases as m4/getcwd-path-max.m4. (main): Update exit code computation. * doc/posix-functions/getcwd.texi: Mention list of platforms where getcwd does not handle long file names.
-rw-r--r--ChangeLog18
-rw-r--r--doc/posix-functions/getcwd.texi3
-rw-r--r--lib/getcwd.c9
-rw-r--r--m4/getcwd-path-max.m422
-rw-r--r--m4/getcwd.m419
-rw-r--r--tests/test-getcwd.c15
6 files changed, 68 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index c99b7018bd..d421257268 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2011-11-20 Bruno Haible <bruno@clisp.org>
+ getcwd: Work around getcwd bug on AIX 5..7.
+ * m4/getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Require
+ AC_CANONICAL_HOST. Assign exit code 31 to the bug seen on AIX 5.1..7.1.
+ Use a different value for gl_cv_func_getcwd_path_max. Move the
+ definition of HAVE_PARTLY_WORKING_GETCWD from here...
+ * m4/getcwd.m4 (gl_FUNC_GETCWD): ... to here. Invoke
+ gl_FUNC_GETCWD_PATH_MAX also when $gl_cv_func_getcwd_null is 'no'.
+ Define HAVE_MINIMALLY_WORKING_GETCWD.
+ * lib/getcwd.c (__getcwd): Don't use the system's getcwd on platforms
+ where it is not even minimally working, that is, on AIX.
+ * tests/test-getcwd.c (test_long_name): Distinguish the same cases as
+ m4/getcwd-path-max.m4.
+ (main): Update exit code computation.
+ * doc/posix-functions/getcwd.texi: Mention list of platforms where
+ getcwd does not handle long file names.
+
+2011-11-20 Bruno Haible <bruno@clisp.org>
+
getcwd: Fix bug from 2009-09-10.
* m4/getcwd.m4 (gl_FUNC_GETCWD): Treat "guessing yes" like "yes", not
like "no".
diff --git a/doc/posix-functions/getcwd.texi b/doc/posix-functions/getcwd.texi
index 8648322a77..5dfba599ab 100644
--- a/doc/posix-functions/getcwd.texi
+++ b/doc/posix-functions/getcwd.texi
@@ -33,7 +33,8 @@ Portability problems fixed by Gnulib module @code{getcwd}:
This function is missing on some older platforms.
@item
This function does not handle long file names (greater than @code{PATH_MAX})
-correctly on some platforms.
+correctly on some platforms:
+glibc on Linux 2.4.20, MacOS X 10.5, FreeBSD 6.4, NetBSD 5.1, OpenBSD 4.9, AIX 7.1.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/getcwd.c b/lib/getcwd.c
index f8101613f2..9b8171cc03 100644
--- a/lib/getcwd.c
+++ b/lib/getcwd.c
@@ -135,7 +135,7 @@ __getcwd (char *buf, size_t size)
size_t allocated = size;
size_t used;
-#if HAVE_RAW_DECL_GETCWD
+#if HAVE_RAW_DECL_GETCWD && HAVE_MINIMALLY_WORKING_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
@@ -143,7 +143,12 @@ __getcwd (char *buf, size_t size)
Use the system getcwd even if we have openat support, since the
system getcwd works even when a parent is unreadable, while the
- openat-based approach does not. */
+ openat-based approach does not.
+
+ But on AIX 5.1..7.1, the system getcwd is not even minimally
+ working: If the current directory name is slightly longer than
+ PATH_MAX, it omits the first directory component and returns
+ this wrong result with errno = 0. */
# undef getcwd
dir = getcwd (buf, size);
diff --git a/m4/getcwd-path-max.m4 b/m4/getcwd-path-max.m4
index 6be4b2ce6d..d11a668d06 100644
--- a/m4/getcwd-path-max.m4
+++ b/m4/getcwd-path-max.m4
@@ -1,4 +1,4 @@
-# serial 18
+# serial 19
# Check for several getcwd bugs with long file names.
# If so, arrange to compile the wrapper function.
@@ -16,6 +16,7 @@
AC_DEFUN([gl_FUNC_GETCWD_PATH_MAX],
[
AC_CHECK_DECLS_ONCE([getcwd])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_CHECK_HEADERS_ONCE([unistd.h])
AC_REQUIRE([gl_PATHMAX_SNIPPET_PREREQ])
@@ -124,7 +125,12 @@ main ()
fail = 11;
break;
}
- if (c || ! (errno == ERANGE || is_ENAMETOOLONG (errno)))
+ if (c)
+ {
+ fail = 31;
+ break;
+ }
+ if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
{
fail = 21;
break;
@@ -184,14 +190,12 @@ main ()
[gl_cv_func_getcwd_path_max=yes],
[case $? in
10|11|12) gl_cv_func_getcwd_path_max='no, but it is partly working';;
+ 31) gl_cv_func_getcwd_path_max='no, it has the AIX bug';;
*) gl_cv_func_getcwd_path_max=no;;
esac],
- [gl_cv_func_getcwd_path_max=no])
+ [case "$host_os" in
+ aix*) gl_cv_func_getcwd_path_max='no, it has the AIX bug';;
+ *) gl_cv_func_getcwd_path_max=no;;
+ esac])
])
- case $gl_cv_func_getcwd_path_max in
- 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.]);;
- esac
])
diff --git a/m4/getcwd.m4 b/m4/getcwd.m4
index 982ef4ed9c..dbdfcd2f41 100644
--- a/m4/getcwd.m4
+++ b/m4/getcwd.m4
@@ -113,14 +113,31 @@ AC_DEFUN([gl_FUNC_GETCWD],
gl_cv_func_getcwd_path_max=yes
;;
*)
+ gl_FUNC_GETCWD_PATH_MAX
case "$gl_cv_func_getcwd_null" in
*yes)
- gl_FUNC_GETCWD_PATH_MAX
gl_FUNC_GETCWD_ABORT_BUG([gl_abort_bug=yes])
;;
esac
;;
esac
+ dnl Define HAVE_MINIMALLY_WORKING_GETCWD and HAVE_PARTLY_WORKING_GETCWD
+ dnl if appropriate.
+ case "$gl_cv_func_getcwd_path_max" in
+ "no, it has the AIX bug") ;;
+ *)
+ AC_DEFINE([HAVE_MINIMALLY_WORKING_GETCWD], [1],
+ [Define to 1 if getcwd minimally works, that is, its result can be
+ trusted when it succeeds.])
+ ;;
+ esac
+ case "$gl_cv_func_getcwd_path_max" in
+ "no, but it is partly working")
+ 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.])
+ ;;
+ esac
case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_posix_signature$gl_cv_func_getcwd_path_max,$gl_abort_bug in
*yes,yes,yes,no) ;;
diff --git a/tests/test-getcwd.c b/tests/test-getcwd.c
index 359aedb3d1..5f875acbbf 100644
--- a/tests/test-getcwd.c
+++ b/tests/test-getcwd.c
@@ -164,11 +164,16 @@ test_long_name (void)
fail = 3;
break;
}
- if (c || ! (errno == ERANGE || errno == ENAMETOOLONG))
+ if (c)
{
fail = 4;
break;
}
+ if (! (errno == ERANGE || errno == ENAMETOOLONG))
+ {
+ fail = 5;
+ break;
+ }
}
if (dotdot_max <= cwd_len - initial_cwd_len)
@@ -181,12 +186,12 @@ test_long_name (void)
if (! (errno == ERANGE || errno == ENOENT
|| errno == ENAMETOOLONG))
{
- fail = 5;
+ fail = 6;
break;
}
if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
{
- fail = 6;
+ fail = 7;
break;
}
}
@@ -194,7 +199,7 @@ test_long_name (void)
if (c && strlen (c) != cwd_len)
{
- fail = 7;
+ fail = 8;
break;
}
++n_chdirs;
@@ -224,5 +229,5 @@ test_long_name (void)
int
main (int argc, char **argv)
{
- return test_abort_bug () * 8 + test_long_name ();
+ return test_abort_bug () * 10 + test_long_name ();
}