+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.
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:
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
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);
-# serial 18
+# serial 19
# Check for several getcwd bugs with long file names.
# If so, arrange to compile the wrapper function.
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])
fail = 11;
break;
}
- if (c || ! (errno == ERANGE || is_ENAMETOOLONG (errno)))
+ if (c)
+ {
+ fail = 31;
+ break;
+ }
+ if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
{
fail = 21;
break;
[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
])
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) ;;
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)
if (! (errno == ERANGE || errno == ENOENT
|| errno == ENAMETOOLONG))
{
- fail = 5;
+ fail = 6;
break;
}
if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
{
- fail = 6;
+ fail = 7;
break;
}
}
if (c && strlen (c) != cwd_len)
{
- fail = 7;
+ fail = 8;
break;
}
++n_chdirs;
int
main (int argc, char **argv)
{
- return test_abort_bug () * 8 + test_long_name ();
+ return test_abort_bug () * 10 + test_long_name ();
}