On AIX 7.2, I see this test failure: FAIL: test-fclose =================
../../gltests/test-fclose.c:74: assertion 'lseek (fd, 0, SEEK_CUR) == 3' failed FAIL test-fclose (exit status: 134) The cause is that while POSIX specify a certain behaviour regarding the position of the underlying file descriptor for fflush() and fclose(), most systems - either do it right for both — like musl libc — - or wrong for both — like glibc (at least up to version 2.32) —, whereas AIX gets it right for fflush() but wrong for fclose(). This patch fixes it. 2021-01-05 Bruno Haible <br...@clisp.org> fclose: Fix test failure on AIX 7.2. * m4/fclose.m4 (gl_FUNC_FCLOSE_STDIN): New macro. (gl_FUNC_FCLOSE): Invoke it. Set REPLACE_FCLOSE accordingly. * doc/posix-functions/fclose.texi: Update platform information. * doc/posix-functions/fflush.texi: Likewise. diff --git a/doc/posix-functions/fclose.texi b/doc/posix-functions/fclose.texi index d3606b4..fb83f6a 100644 --- a/doc/posix-functions/fclose.texi +++ b/doc/posix-functions/fclose.texi @@ -11,7 +11,7 @@ Portability problems fixed by Gnulib: @item On some platforms, this function fails to set the file position of a seekable input stream to the byte after the last one actually read: -glibc 2.13, FreeBSD. +glibc 2.32, FreeBSD, AIX 7.2. @item This function crashes if the stream's file descriptor has already been closed on some platforms: diff --git a/doc/posix-functions/fflush.texi b/doc/posix-functions/fflush.texi index 1964da4..665951d 100644 --- a/doc/posix-functions/fflush.texi +++ b/doc/posix-functions/fflush.texi @@ -11,7 +11,8 @@ Portability problems fixed by Gnulib: @item @code{fflush} followed by @code{fseek} or @code{fseeko}, applied to an input stream, should have the effect of positioning the underlying file descriptor. -It doesn't do this on some platforms. +It doesn't do this on some platforms: +glibc 2.32 and others. @item @code{fflush} on an input stream changes the position of the stream to the end of the previous buffer, on some platforms: mingw, MSVC 14. diff --git a/m4/fclose.m4 b/m4/fclose.m4 index 13e1799..74a04e1 100644 --- a/m4/fclose.m4 +++ b/m4/fclose.m4 @@ -1,4 +1,4 @@ -# fclose.m4 serial 8 +# fclose.m4 serial 9 dnl Copyright (C) 2008-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -23,4 +23,76 @@ AC_DEFUN([gl_FUNC_FCLOSE], case "$host_os" in openedition) REPLACE_FCLOSE=1 ;; esac + + if test $REPLACE_FCLOSE = 0; then + gl_FUNC_FCLOSE_STDIN + case "$gl_cv_func_fclose_stdin" in + *yes) ;; + *) REPLACE_FCLOSE=1 ;; + esac + fi +]) + +dnl Determine whether fclose works on input streams. +dnl Sets gl_cv_func_fclose_stdin. + +AC_DEFUN([gl_FUNC_FCLOSE_STDIN], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CHECK_HEADERS_ONCE([unistd.h]) + AC_CACHE_CHECK([whether fclose works on input streams], + [gl_cv_func_fclose_stdin], + [echo hello world > conftest.txt + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include <fcntl.h> + #include <stdio.h> + #if HAVE_UNISTD_H + # include <unistd.h> + #else /* on Windows with MSVC */ + # include <io.h> + #endif + ]GL_MDA_DEFINES], + [[int fd; + int fd2; + FILE *fp; + fd = open ("conftest.txt", O_RDONLY); + if (fd < 0) + return 1; + if (lseek (fd, 1, SEEK_SET) != 1) + return 2; + fd2 = dup (fd); + if (fd2 < 0) + return 3; + fp = fdopen (fd2, "r"); + if (fp == NULL) + return 4; + if (fgetc (fp) != 'e') + { fclose (fp); return 5; } + /* This fclose() call should reposition the underlying file + descriptor. */ + if (fclose (fp) != 0) + return 6; + if (lseek (fd2, 0, SEEK_CUR) != -1) /* should fail with EBADF */ + return 7; + /* Verify the file position. */ + if (lseek (fd, 0, SEEK_CUR) != 2) + return 8; + return 0; + ]])], + [gl_cv_func_fclose_stdin=yes], + [gl_cv_func_fclose_stdin=no], + [case "$host_os" in + # Guess no on glibc systems. + *-gnu* | gnu*) gl_cv_func_fclose_stdin="guessing no" ;; + # Guess yes on musl systems. + *-musl*) gl_cv_func_fclose_stdin="guessing yes" ;; + # Guess no on native Windows. + mingw*) gl_cv_func_fclose_stdin="guessing no" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_fclose_stdin="$gl_cross_guess_normal" ;; + esac + ]) + rm conftest.txt + ]) ])