openat: test for fstatat (..., 0) bug
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Sep 2011 03:17:33 +0000 (20:17 -0700)
committerIan Beckwith <ianb@erislabs.net>
Thu, 8 Sep 2011 02:04:32 +0000 (03:04 +0100)
Further testing with tar suggests that fstatat (..., 0)
does not work in general, on AIX 7.1; see
<http://lists.gnu.org/archive/html/bug-tar/2011-09/msg00023.html>.
So, give up entirely on AIX 7.1's fstatat, and fall back on our
replacement fstatat (which is what older AIX releases were using
anyway).
* lib/fstatat.c (fstatat) [HAVE_FSTATAT]: Do not undef.  The only
use is now changed to orig_fstatat.  This was probably the right
thing to do anyway.
(FSTATAT_AT_FDCWD_0_BROKEN): Remove; no longer used.
(rpl_fstatat) [FSTATAT_ZERO_FLAG_BROKEN]: Remove.
(rpl_fstatat): Simplify, assuming !FSTATAT_ZERO_FLAG_BROKEN.
(AT_FUNC_NAME) [FSTATAT_ZERO_FLAG_BROKEN]: Now rpl_fstatat.
* m4/openat.m4 (gl_FUNC_FSTATAT): Test for the more-general bug
and define FSTATAT_ZERO_FLAG_BROKEN, not FSTATAT_AT_FDCWD_0_BROKEN,
if the bug is found.
(cherry picked from commit 204072b3f5a110d1225d81ca6a929c9f7b76029f)

ChangeLog
lib/fstatat.c
m4/openat.m4

index f6db499..d55acfb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2011-09-03  Paul Eggert  <eggert@cs.ucla.edu>
 
+       openat: test for fstatat (..., 0) bug
+       Further testing with tar suggests that fstatat (..., 0)
+       does not work in general, on AIX 7.1; see
+       <http://lists.gnu.org/archive/html/bug-tar/2011-09/msg00023.html>.
+       So, give up entirely on AIX 7.1's fstatat, and fall back on our
+       replacement fstatat (which is what older AIX releases were using
+       anyway).
+       * lib/fstatat.c (fstatat) [HAVE_FSTATAT]: Do not undef.  The only
+       use is now changed to orig_fstatat.  This was probably the right
+       thing to do anyway.
+       (FSTATAT_AT_FDCWD_0_BROKEN): Remove; no longer used.
+       (rpl_fstatat) [FSTATAT_ZERO_FLAG_BROKEN]: Remove.
+       (rpl_fstatat): Simplify, assuming !FSTATAT_ZERO_FLAG_BROKEN.
+       (AT_FUNC_NAME) [FSTATAT_ZERO_FLAG_BROKEN]: Now rpl_fstatat.
+       * m4/openat.m4 (gl_FUNC_FSTATAT): Test for the more-general bug
+       and define FSTATAT_ZERO_FLAG_BROKEN, not FSTATAT_AT_FDCWD_0_BROKEN,
+       if the bug is found.
+
        openat: test for fstatat (AT_FDCWD, ..., 0) bug
        This tests for another fstatat bug on AIX 7.1:
        fstatat (AT_FDCWD, ..., 0) does not work.  See
index f1bed73..326ce21 100644 (file)
@@ -42,13 +42,7 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
 #include <fcntl.h>
 #include <string.h>
 
-#if HAVE_FSTATAT
-
-# undef fstatat
-
-# ifndef FSTATAT_AT_FDCWD_0_BROKEN
-#  define FSTATAT_AT_FDCWD_0_BROKEN 0
-# endif
+#if HAVE_FSTATAT && !FSTATAT_ZERO_FLAG_BROKEN
 
 # ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK
 #  define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
@@ -66,10 +60,7 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
 int
 rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
 {
-  int result =
-    (FSTATAT_AT_FDCWD_0_BROKEN && fd == AT_FDCWD && flag == 0
-     ? stat (file, st)
-     : orig_fstatat (fd, file, st, flag));
+  int result = orig_fstatat (fd, file, st, flag);
   size_t len;
 
   if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0)
@@ -85,7 +76,7 @@ rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
           errno = ENOTDIR;
           return -1;
         }
-      result = fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
+      result = orig_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
     }
   /* Fix stat behavior.  */
   if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/')
@@ -96,7 +87,7 @@ rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
   return result;
 }
 
-#else /* !HAVE_FSTATAT */
+#else /* !HAVE_FSTATAT || FSTATAT_ZERO_FLAG_BROKEN */
 
 /* On mingw, the gnulib <sys/stat.h> defines `stat' as a function-like
    macro; but using it in AT_FUNC_F2 causes compilation failure
@@ -124,7 +115,11 @@ stat_func (char const *name, struct stat *st)
    then give a diagnostic and exit nonzero.
    Otherwise, this function works just like Solaris' fstatat.  */
 
-# define AT_FUNC_NAME fstatat
+# if FSTATAT_ZERO_FLAG_BROKEN
+#  define AT_FUNC_NAME rpl_fstatat
+# else
+#  define AT_FUNC_NAME fstatat
+# endif
 # define AT_FUNC_F1 lstat
 # define AT_FUNC_F2 stat_func
 # define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
index 149b864..43da4f2 100644 (file)
@@ -1,4 +1,4 @@
-# serial 36
+# serial 37
 # See if we need to use our replacement for Solaris' openat et al functions.
 
 dnl Copyright (C) 2004-2011 Free Software Foundation, Inc.
@@ -167,10 +167,9 @@ AC_DEFUN([gl_FUNC_FSTATAT],
   else
     dnl Test for an AIX 7.1 bug; see
     dnl <http://lists.gnu.org/archive/html/bug-tar/2011-09/msg00015.html>.
-    AC_CACHE_CHECK([whether fstatat (AT_FDCWD, ..., 0) works],
-      [gl_cv_func_fstatat_AT_FDCWD_0],
-      [gl_cv_func_fstatat_AT_FDCWD_0=no
-       echo xxx >conftest.file
+    AC_CACHE_CHECK([whether fstatat (..., 0) works],
+      [gl_cv_func_fstatat_zero_flag],
+      [gl_cv_func_fstatat_zero_flag=no
        AC_RUN_IFELSE(
          [AC_LANG_SOURCE(
             [[
@@ -180,17 +179,17 @@ AC_DEFUN([gl_FUNC_FSTATAT],
               main (void)
               {
                 struct stat a;
-                return fstatat (AT_FDCWD, "conftest.file", &a, 0) != 0;
+                return fstatat (AT_FDCWD, ".", &a, 0) != 0;
               }
             ]])],
-         [gl_cv_func_fstatat_AT_FDCWD_0=yes])])
+         [gl_cv_func_fstatat_zero_flag=yes])])
 
-    case $gl_cv_func_fstatat_AT_FDCWD_0+$gl_cv_func_lstat_dereferences_slashed_symlink in
+    case $gl_cv_func_fstatat_zero_flag+$gl_cv_func_lstat_dereferences_slashed_symlink in
     yes+yes) ;;
     *) REPLACE_FSTATAT=1
-       if test $gl_cv_func_fstatat_AT_FDCWD_0 != yes; then
-         AC_DEFINE([FSTATAT_AT_FDCWD_0_BROKEN], [1],
-           [Define to 1 if fstatat (AT_FDCWD, ..., 0) does not work,
+       if test $gl_cv_func_fstatat_zero_flag != yes; then
+         AC_DEFINE([FSTATAT_ZERO_FLAG_BROKEN], [1],
+           [Define to 1 if fstatat (..., 0) does not work,
             as in AIX 7.1.])
        fi
        ;;