[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: getcwd on AIX
From: |
Bruno Haible |
Subject: |
Re: getcwd on AIX |
Date: |
Mon, 21 Nov 2011 00:56:28 +0100 |
User-agent: |
KMail/1.13.6 (Linux/2.6.37.6-0.5-desktop; KDE/4.6.0; x86_64; ; ) |
Jim Meyering wrote:
> Is there an advantage to using the system getcwd for names
> shorter than PATH_MAX, as there is on Solaris and systems with
> a linux kernel? (i.e., ability to function in spite of restricted
> permissions on a parent directory)
Paul Eggert wrote:
> The first patch is simpler and easier to maintain, so I'd go with it
> unless there's a performance or correctness reason to go with the
> second patch.
>
> In Solaris, the system getcwd has some internal magic that
> makes it better than our replacement when it works; if the
> same is true for AIX that'd argue for the second patch.
On both AIX 5.1 and 7.1, I can see with a "truss" run of my test program
that getcwd() does the usual search through ../, ../../, ../../../, etc.,
like gnulib/lib/getcwd.c also does:
statx("./../../../../../../../../../../../../", 0x2FF20E50, 76, 0) = 0
open("./../../../../../../../../../../../../", O_RDONLY) = 3
getdirent(3, 0x20000998, 4096) = 124
lseek(3, 0, 0) = 0
kfcntl(3, F_GETFD, 0x2FF22FFC) = 0
kfcntl(3, F_SETFD, 0x00000001) = 0
fstatx(3, 0x2FF20FB8, 76, 0) = 0
getdirent(3, 0x20000998, 4096) = 124
close(3) = 0
When run in a directory with an unreadable parent dir, the test program
shows that getcwd() fails, and /bin/pwd as well:
$ /bin/pwd
pwd: The file access permissions do not allow the specified action.
So, I'm going with the first approach.
I'm not writing 'defined _AIX' but instead using an autoconf test. My
new autoconf test is not needed; Jim's old one in m4/getcwd-path-max.m4
also recognizes the bug. Only two modifications are needed: to actually
run the test on this platform (previously it was only run on platforms
where getcwd(NULL,0) works), and a new exit code.
2011-11-20 Bruno Haible <address@hidden>
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.
--- doc/posix-functions/getcwd.texi.orig Mon Nov 21 00:44:38 2011
+++ doc/posix-functions/getcwd.texi Mon Nov 21 00:35:22 2011
@@ -33,7 +33,8 @@
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:
--- lib/getcwd.c.orig Mon Nov 21 00:44:38 2011
+++ lib/getcwd.c Mon Nov 21 00:24:42 2011
@@ -135,7 +135,7 @@
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 @@
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);
--- m4/getcwd-path-max.m4.orig Mon Nov 21 00:44:38 2011
+++ m4/getcwd-path-max.m4 Mon Nov 21 00:29:53 2011
@@ -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 @@
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 @@
[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
])
--- m4/getcwd.m4.orig Mon Nov 21 00:44:38 2011
+++ m4/getcwd.m4 Mon Nov 21 00:30:45 2011
@@ -113,14 +113,31 @@
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) ;;
--- tests/test-getcwd.c.orig Mon Nov 21 00:44:38 2011
+++ tests/test-getcwd.c Mon Nov 21 00:36:56 2011
@@ -164,11 +164,16 @@
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 @@
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 @@
if (c && strlen (c) != cwd_len)
{
- fail = 7;
+ fail = 8;
break;
}
++n_chdirs;
@@ -224,5 +229,5 @@
int
main (int argc, char **argv)
{
- return test_abort_bug () * 8 + test_long_name ();
+ return test_abort_bug () * 10 + test_long_name ();
}
--
In memoriam Kerem Yılmazer <http://en.wikipedia.org/wiki/Kerem_Yılmazer>