From 0ba19fcc5ff43167939e465af4b93f965fffcc8c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 30 Aug 2011 16:38:59 -0700 Subject: [PATCH] openat: work around AIX 7.1 fstatat bug Problem reported by Kevin Brott for GNU tar, in the thread containing . * lib/fstatat.c (rpl_fstatat): Do not invoke underlying fstatat if FSTATAT_ST_SIZE_ETC_BROKEN. (fstatat) [FSTATAT_ST_SIZE_ETC_BROKEN && HAVE_FSTATAT]: #define to rpl_fstatat. * m4/openat.m4 (gl_FUNC_FSTATAT): New macro, with the fstatat-relevant part of gl_FUNC_OPENAT. Also, check for the AIX 7.1 bug, and use AC_CHECK_FUNCS_ONCE for fstatat. (gl_FUNC_OPENAT): Use it. Use AC_CHECK_FUNCS_ONCE for fchmodat, mkdirat, openat and unlinkat. --- ChangeLog | 15 +++++++++++++ lib/fstatat.c | 11 +++++++--- m4/openat.m4 | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7d961e08..ee56aa9a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-08-30 Paul Eggert + + openat: work around AIX 7.1 fstatat bug + Problem reported by Kevin Brott for GNU tar, in the thread containing + . + * lib/fstatat.c (rpl_fstatat): Do not invoke underlying fstatat if + FSTATAT_ST_SIZE_ETC_BROKEN. + (fstatat) [FSTATAT_ST_SIZE_ETC_BROKEN && HAVE_FSTATAT]: #define to + rpl_fstatat. + * m4/openat.m4 (gl_FUNC_FSTATAT): New macro, with the fstatat-relevant + part of gl_FUNC_OPENAT. Also, check for the AIX 7.1 bug, and use + AC_CHECK_FUNCS_ONCE for fstatat. + (gl_FUNC_OPENAT): Use it. Use AC_CHECK_FUNCS_ONCE for + fchmodat, mkdirat, openat and unlinkat. + 2011-08-30 Bruno Haible Avoid endless recursions if config.h includes some header files. diff --git a/lib/fstatat.c b/lib/fstatat.c index 16d60f679..b217126be 100644 --- a/lib/fstatat.c +++ b/lib/fstatat.c @@ -25,7 +25,7 @@ #include #include -#if HAVE_FSTATAT +#if HAVE_FSTATAT && ! FSTATAT_ST_SIZE_ETC_BROKEN # undef fstatat @@ -65,7 +65,12 @@ rpl_fstatat (int fd, char const *file, struct stat *st, int flag) return result; } -#else /* !HAVE_FSTATAT */ +#else /* ! (HAVE_FSTATAT && ! FSTATAT_ST_SIZE_ETC_BROKEN) */ + +# if HAVE_FSTATAT +# undef fstatat +# define fstatat rpl_fstatat +# endif /* On mingw, the gnulib defines `stat' as a function-like macro; but using it in AT_FUNC_F2 causes compilation failure @@ -107,4 +112,4 @@ stat_func (char const *name, struct stat *st) # undef AT_FUNC_POST_FILE_PARAM_DECLS # undef AT_FUNC_POST_FILE_ARGS -#endif /* !HAVE_FSTATAT */ +#endif /* ! (HAVE_FSTATAT && ! FSTATAT_ST_SIZE_ETC_BROKEN) */ diff --git a/m4/openat.m4 b/m4/openat.m4 index affb11455..aa6838dcf 100644 --- a/m4/openat.m4 +++ b/m4/openat.m4 @@ -1,4 +1,4 @@ -# serial 33 +# serial 34 # See if we need to use our replacement for Solaris' openat et al functions. dnl Copyright (C) 2004-2011 Free Software Foundation, Inc. @@ -23,8 +23,7 @@ AC_DEFUN([gl_FUNC_OPENAT], GNULIB_UNLINKAT=1 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - AC_CHECK_FUNCS_ONCE([lchmod]) - AC_CHECK_FUNCS([fchmodat fstatat mkdirat openat unlinkat]) + AC_CHECK_FUNCS_ONCE([fchmodat lchmod mkdirat openat unlinkat]) AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK]) AC_REQUIRE([gl_FUNC_UNLINK]) case $ac_cv_func_openat+$gl_cv_func_lstat_dereferences_slashed_symlink in @@ -37,13 +36,11 @@ AC_DEFUN([gl_FUNC_OPENAT], # Solaris 9 has *at functions, but uniformly mishandles trailing # slash in all of them. REPLACE_OPENAT=1 - REPLACE_FSTATAT=1 REPLACE_UNLINKAT=1 ;; *) HAVE_OPENAT=0 HAVE_UNLINKAT=0 # No known system with unlinkat but not openat - HAVE_FSTATAT=0 # No known system with fstatat but not openat gl_PREREQ_OPENAT;; esac if test $ac_cv_func_fchmodat != yes; then @@ -53,6 +50,7 @@ AC_DEFUN([gl_FUNC_OPENAT], HAVE_MKDIRAT=0 fi gl_FUNC_FCHOWNAT + gl_FUNC_FSTATAT ]) # gl_FUNC_FCHOWNAT_DEREF_BUG([ACTION-IF-BUGGY[, ACTION-IF-NOT_BUGGY]]) @@ -155,6 +153,65 @@ AC_DEFUN([gl_FUNC_FCHOWNAT], [HAVE_FCHOWNAT=0]) ]) +# If we have the fstatat function, and it has the bug (in AIX 7.1) +# that it does not fill in st_size correctly, use the replacement function. +AC_DEFUN([gl_FUNC_FSTATAT], +[ + AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK]) + AC_CHECK_FUNCS_ONCE([fstatat openat]) + + if test $ac_cv_func_fstatat = no; then + HAVE_FSTATAT=0 + else + AC_CACHE_CHECK([whether fstatat fills in st_size etc.], + [gl_cv_func_fstatat_st_size_etc], + [gl_cv_func_fstatat_st_size_etc=no + echo xxx >conftest.file + AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[ + #include + #include + + int + main (void) + { + struct stat a; + struct stat b; + if (fstatat (AT_FDCWD, "conftest.file", &a, + AT_SYMLINK_NOFOLLOW) + != 0) + return 1; + if (lstat ("conftest.file", &b) != 0) + return 2; + if (a.st_size != b.st_size) return 3; + if (a.st_dev != b.st_dev) return 4; + if (a.st_ino != b.st_ino) return 5; + if (a.st_mode != b.st_mode) return 6; + if (a.st_nlink != b.st_nlink) return 7; + if (a.st_uid != b.st_uid) return 8; + if (a.st_gid != b.st_gid) return 9; + /* Don't check time members, to avoid caching issues. */ + return 0; + } + ]])], + [gl_cv_func_fstatat_st_size_etc=yes])]) + + case $gl_cv_func_fstatat_st_size_etc+$gl_cv_func_lstat_dereferences_slashed_symlink in + yes+yes) ;; + *) REPLACE_FSTATAT=1 + if test $gl_cv_func_fstatat_st_size_etc != yes; then + AC_DEFINE([FSTATAT_ST_SIZE_ETC_BROKEN], [1], + [Define to 1 if fstatat does not fill in st_size etc., + as in AIX 7.1.]) + fi + ;; + esac + fi +]) + AC_DEFUN([gl_PREREQ_OPENAT], [ AC_REQUIRE([AC_C_INLINE]) -- 2.11.0