From 69dba6d784566248205fc990673c14d259c4907f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 21 Nov 2011 00:56:11 +0100 Subject: [PATCH] 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. --- ChangeLog | 18 ++++++++++++++++++ doc/posix-functions/getcwd.texi | 3 ++- lib/getcwd.c | 9 +++++++-- m4/getcwd-path-max.m4 | 22 +++++++++++++--------- m4/getcwd.m4 | 19 ++++++++++++++++++- tests/test-getcwd.c | 15 ++++++++++----- 6 files changed, 68 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index c99b7018b..d42125726 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2011-11-20 Bruno Haible + 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 + 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 8648322a7..5dfba599a 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 f8101613f..9b8171cc0 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 6be4b2ce6..d11a668d0 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 982ef4ed9..dbdfcd2f4 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 359aedb3d..5f875acbb 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 (); } -- 2.11.0