bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 'fflush' test failure on Cygwin


From: Eric Blake
Subject: Re: 'fflush' test failure on Cygwin
Date: Mon, 16 Apr 2007 21:38:13 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.10) Gecko/20070221 Thunderbird/1.5.0.10 Mnenhy/0.7.5.666

-----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  <address@hidden>

        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             address@hidden
-----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:
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]