2011-05-02 Eric Blake <eblake@redhat.com>
+ 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.
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}
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
#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
&& 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 */
-# 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
])
if test $gl_cv_func_fflush_stdin = no; then
gl_REPLACE_FFLUSH
+ gl_REPLACE_FCLOSE
fi
])
m4/fflush.m4
Depends-on:
+fclose
fpurge
ftello
freading
configure.ac:
gl_FUNC_FFLUSH
+gl_MODULE_INDICATOR([fflush])
gl_STDIO_MODULE_INDICATOR([fflush])
Makefile.am:
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");
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. */