bug-gnulib
[Top][All Lists]
Advanced

[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>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]