From bcbcf0c59cec0e91db318eccdc564852bafa3c67 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 2 May 2011 15:00:50 -0600 Subject: [PATCH] fflush: also replace fclose when fixing fflush This fixes the fclose failures detected in the previous patch, but only when the GPL fflush module is also in use. That is because the need for behavior of resetting seekable input streams is much less common, and the fix more complex. The LGPLv2+ test for fclose() in isolation is relaxed to pass if fflush is not being replaced to cater to input streams. * modules/fflush (Depends-on): Add fclose. * m4/fflush.m4 (gl_FUNC_FFLUSH): Also replace fclose. * lib/fclose.c (rpl_fclose): Don't cause spurious failures on memstreams with no backing fd. * doc/posix-functions/fclose.texi (fclose): Document the use of fflush module to fix the bug. * tests/test-fclose.c (main): Relax test when fclose is used in isolation. Signed-off-by: Eric Blake --- ChangeLog | 10 ++++++++++ doc/posix-functions/fclose.texi | 16 ++++++++++------ lib/fclose.c | 10 ++++++++-- m4/fflush.m4 | 3 ++- modules/fflush | 2 ++ tests/test-fclose.c | 5 ++++- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9575a1bad..708fc8f161 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2011-05-02 Eric Blake + fflush: also replace fclose when fixing fflush + * modules/fflush (Depends-on): Add fclose. + * m4/fflush.m4 (gl_FUNC_FFLUSH): Also replace fclose. + * lib/fclose.c (rpl_fclose): Don't cause spurious failures on + memstreams with no backing fd. + * doc/posix-functions/fclose.texi (fclose): Document the use of + fflush module to fix the bug. + * tests/test-fclose.c (main): Relax test when fclose is used in + isolation. + fclose: add some tests * modules/fclose-tests: New test module. * tests/test-fclose.c: New file. diff --git a/doc/posix-functions/fclose.texi b/doc/posix-functions/fclose.texi index ad3aca343e..45aac4c7e9 100644 --- a/doc/posix-functions/fclose.texi +++ b/doc/posix-functions/fclose.texi @@ -4,9 +4,17 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fclose.html} -Gnulib module: fclose +Gnulib module: fclose, fflush -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{fflush}: +@itemize +@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. +@end itemize + +Portability problems fixed by Gnulib module @code{fclose}: @itemize @item On Windows platforms (excluding Cygwin), @code{socket} and @code{accept} @@ -17,10 +25,6 @@ followed by @code{fdopen} do not return streams that can be closed by Portability problems not fixed by Gnulib: @itemize @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. -@item On Windows platforms (excluding Cygwin), this function does not set @code{errno} upon failure. @end itemize diff --git a/lib/fclose.c b/lib/fclose.c index c8c2fd8e4c..bed561bdb1 100644 --- a/lib/fclose.c +++ b/lib/fclose.c @@ -24,13 +24,19 @@ #include "freading.h" -/* Override fclose() to call the overridden close(). */ +/* Override fclose() to call the overridden fflush() or close(). */ int rpl_fclose (FILE *fp) #undef fclose { int saved_errno = 0; + int fd; + + /* Don't change behavior on memstreams. */ + fd = fileno (fp); + if (fd < 0) + return fclose (fp); /* We only need to flush the file if it is not reading or if it is seekable. This only guarantees the file position of input files @@ -39,7 +45,7 @@ rpl_fclose (FILE *fp) && fflush (fp)) saved_errno = errno; - if (close (fileno (fp)) < 0 && saved_errno == 0) + if (close (fd) < 0 && saved_errno == 0) saved_errno = errno; fclose (fp); /* will fail with errno = EBADF */ diff --git a/m4/fflush.m4 b/m4/fflush.m4 index f7645deff6..08b9f17d30 100644 --- a/m4/fflush.m4 +++ b/m4/fflush.m4 @@ -1,4 +1,4 @@ -# fflush.m4 serial 8 +# fflush.m4 serial 9 # Copyright (C) 2007-2011 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -61,6 +61,7 @@ AC_DEFUN([gl_FUNC_FFLUSH], ]) if test $gl_cv_func_fflush_stdin = no; then gl_REPLACE_FFLUSH + gl_REPLACE_FCLOSE fi ]) diff --git a/modules/fflush b/modules/fflush index a8a151e93a..2d5839db4c 100644 --- a/modules/fflush +++ b/modules/fflush @@ -7,6 +7,7 @@ lib/stdio-impl.h m4/fflush.m4 Depends-on: +fclose fpurge ftello freading @@ -20,6 +21,7 @@ AC_REQUIRE([AC_FUNC_FSEEKO]) configure.ac: gl_FUNC_FFLUSH +gl_MODULE_INDICATOR([fflush]) gl_STDIO_MODULE_INDICATOR([fflush]) Makefile.am: diff --git a/tests/test-fclose.c b/tests/test-fclose.c index a11eca96e3..d9b940619b 100644 --- a/tests/test-fclose.c +++ b/tests/test-fclose.c @@ -62,7 +62,9 @@ main (int argc, char **argv) ASSERT (errno == EBADF); ASSERT (lseek (fd, 0, SEEK_CUR) == 2); - /* Likewise for an input stream. */ +#if GNULIB_FFLUSH + /* Likewise for an input stream, but only when we know fflush works + on input streams. */ fd2 = dup (fd); ASSERT (0 <= fd2); f = fdopen (fd2, "r"); @@ -73,6 +75,7 @@ main (int argc, char **argv) ASSERT (lseek (fd2, 0, SEEK_CUR) == -1); ASSERT (errno == EBADF); ASSERT (lseek (fd, 0, SEEK_CUR) == 3); +#endif /* Test that fclose() sets errno if someone else closes the stream fd behind the back of stdio. */ -- 2.30.2