-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Bruno Haible on 4/12/2007 7:30 PM: > > 1) fpurge exists on MacOS X, but only clears the buffer, without changing > the file descriptor's position in the kernel. So it needs this change > (otherwise the stream's position before the fflush() call is lost): > > *** lib/fflush.c 2007-04-13 00:15:11.000000000 +0200 > --- lib/fflush.c 2007-04-13 02:44:10.000000000 +0200 > *************** > *** 57,63 **** > /* To get here, we must be flushing a seekable input stream, so the > semantics of fpurge are now appropriate. */ > #if HAVE_FPURGE > ! result = fpurge (stream); > #elif HAVE___FPURGE > /* __fpurge has no return value, and on Solaris, we can't even trust > errno. So assume it succeeds. */ > --- 57,72 ---- > /* To get here, we must be flushing a seekable input stream, so the > semantics of fpurge are now appropriate. */ > #if HAVE_FPURGE > ! { > ! off_t pos = ftello (stream); > ! > ! result = fpurge (stream); > ! if (result == 0) > ! { > ! if (lseek (fileno (stream), pos, SEEK_SET) == -1) > ! result = EOF; > ! } > ! }
This is now done as part of my refactoring of fflush to depend on your new fpurge module: 2007-04-16 Eric Blake <[EMAIL PROTECTED]> Make fflush rely on fpurge. * lib/fflush.c (rpl_fflush): Rely on fpurge module, rather than open coding all variants. * modules/fflush (Depends-on): Add fpurge and unistd. * modules/fflush-tests (Depends-on): Unistd is no longer extra. * m4/fflush.m4 (gl_REPLACE_FFLUSH): Simplify. > > A solution might be to make a wrapper around fseek() roughly like this: > > rpl_fseek (...) > { > if (fp is not open for writing > && fp's buffer is empty, like after fpurge) > perform just an lseek > else > fseek (...); > } A module for fseek/fseeko still needs to be written. And in the process, I discovered that mingw lacks ftello, so we also need a module for ftell/ftello (until that is written, fflush fails to compile on mingw). Unfortunately, on mingw, Microsoft has chosen for off_t to be 4 bytes (plain 'long'), which means fseeko is no more accurate than fseek; then changed their mind to provide 64-bit file offsets, but via the non-standard _ftelli64 and _fseeki64 on the type __int64 (basically 'long long'), along with non-standard _stat64 to make stat() use 64-bit timestamps and file lengths rather than 32-bit. I guess we implement fseeko using mingw's choice of off_t, even though it is an artificial limit compared to what the platform is capable of via non-standard functions. - -- Don't work too hard, make some time for fun as well! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGJEEi84KuGfSFAYARAhmiAJ0T7nw1PIMXMvixV+xFOjJNizEzaQCeNPeq QKKMu8C0w4uyTGwEQmE7Jc0= =X9Py -----END PGP SIGNATURE-----
Index: lib/fflush.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/fflush.c,v retrieving revision 1.2 diff -u -p -r1.2 fflush.c --- lib/fflush.c 12 Apr 2007 11:59:14 -0000 1.2 +++ lib/fflush.c 17 Apr 2007 03:25:02 -0000 @@ -21,13 +21,7 @@ #include <errno.h> #include <stdio.h> -#if HAVE_STDIO_EXT_H -# include <stdio_ext.h> -#endif - -#if HAVE_FPURGE && ! HAVE_DECL_FPURGE -int fpurge (FILE *); -#endif +#include "fpurge.h" #undef fflush @@ -36,53 +30,31 @@ int fpurge (FILE *); int rpl_fflush (FILE *stream) { - int e; /* Capture errno of first fflush if nothing else succeeds. */ int result; + off_t pos; /* Try flushing the stream. C89 guarantees behavior of output streams, so we only need to worry if failure might have been on an input stream. When stream is NULL, POSIX only requires flushing of output streams. */ result = fflush (stream); - if (! stream || result == 0 || (e = errno) != EBADF) + if (! stream || result == 0 || errno != EBADF) return result; - /* POSIX does not specify behavior for non-seekable streams. */ - if (fseeko (stream, 0, SEEK_CUR) != 0) + /* POSIX does not specify fflush behavior for non-seekable input + streams. */ + pos = ftello (stream); + if (pos == -1) { - errno = e; + errno = EBADF; return EOF; } /* To get here, we must be flushing a seekable input stream, so the - semantics of fpurge are now appropriate. */ -#if HAVE_FPURGE + semantics of fpurge are now appropriate to clear the buffer. To + avoid losing data, the lseek is also necessary. */ result = fpurge (stream); -#elif HAVE___FPURGE - /* __fpurge has no return value, and on Solaris, we can't even trust - errno. So assume it succeeds. */ - __fpurge (stream); - result = 0; -#else /* ! HAVE___FPURGE */ - - /* No single replacement; do it manually. */ - { - off_t position = ftello (stream); - if (position == -1) - { - result = EOF; /* Should not happen; we know stream is seekable. */ - } - /* Set position of stream; hopefully the stdio routines don't - overoptimize by not setting the underlying file position. */ - else if (fseeko (stream, position, SEEK_SET) != 0) - { - result = EOF; - errno = e; - } - else - result = 0; - } -#endif /* ! HAVE___FPURGE */ - + if (result == 0 && lseek (fileno (stream), pos, SEEK_SET) == -1) + return EOF; return result; } Index: m4/fflush.m4 =================================================================== RCS file: /sources/gnulib/gnulib/m4/fflush.m4,v retrieving revision 1.1 diff -u -p -r1.1 fflush.m4 --- m4/fflush.m4 10 Apr 2007 03:09:07 -0000 1.1 +++ m4/fflush.m4 17 Apr 2007 03:25:02 -0000 @@ -8,8 +8,7 @@ dnl From Eric Blake dnl Find out how to obey POSIX semantics of fflush(stdin) discarding -dnl unread input, rather than C99 undefined semantics. fpurge is not -dnl standardized, but has the desired properties. +dnl unread input on seekable streams, rather than C99 undefined semantics. AC_DEFUN([gl_FUNC_FFLUSH], [ @@ -45,15 +44,6 @@ AC_DEFUN([gl_FUNC_FFLUSH], AC_DEFUN([gl_REPLACE_FFLUSH], [ - AC_CHECK_HEADERS_ONCE([stdio_ext.h]) - AC_CHECK_FUNCS_ONCE([fpurge __fpurge]) -dnl Linux documents int fpurge(), but only declares void __fpurge(). - AC_CHECK_DECLS([fpurge], [], [], [[ -#include <stdio.h> -#if HAVE_STDIO_EXT_H -# include <stdio_ext.h> -#endif -]]) AC_LIBOBJ([fflush]) AC_REQUIRE([gl_STDIO_H_DEFAULTS]) REPLACE_FFLUSH=1 Index: modules/fflush =================================================================== RCS file: /sources/gnulib/gnulib/modules/fflush,v retrieving revision 1.2 diff -u -p -r1.2 fflush --- modules/fflush 13 Apr 2007 01:46:18 -0000 1.2 +++ modules/fflush 17 Apr 2007 03:25:02 -0000 @@ -6,7 +6,9 @@ lib/fflush.c m4/fflush.m4 Depends-on: +fpurge stdio +unistd configure.ac: gl_FUNC_FFLUSH Index: modules/fflush-tests =================================================================== RCS file: /sources/gnulib/gnulib/modules/fflush-tests,v retrieving revision 1.2 diff -u -p -r1.2 fflush-tests --- modules/fflush-tests 13 Apr 2007 23:50:49 -0000 1.2 +++ modules/fflush-tests 17 Apr 2007 03:25:02 -0000 @@ -2,7 +2,6 @@ Files: tests/test-fflush.c Depends-on: -unistd configure.ac: