changeset 11839:04ea0561a820

fpurge: don't wrap working cygwin implementation * lib/fpurge.c (fpurge): Fix comment typo. * modules/fpurge (Makefile.am): Make replacement conditional, partially reverting 2007-04-29 change. * tests/test-fpurge.c (main): Enhance test. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Sat, 15 Aug 2009 16:43:58 -0600
parents 016ba8fc6061
children d2f20b59cd42
files ChangeLog lib/fpurge.c m4/fpurge.m4 tests/test-fpurge.c
diffstat 4 files changed, 67 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-08-15  Eric Blake  <ebb9@byu.net>
+
+	fpurge: don't wrap working cygwin implementation
+	* lib/fpurge.c (fpurge): Fix comment typo.
+	* modules/fpurge (Makefile.am): Make replacement conditional,
+	partially reverting 2007-04-29 change.
+	* tests/test-fpurge.c (main): Enhance test.
+
 2009-08-15  Eric Blake  <ebb9@byu.net>
 	and Jim Meyering  <meyering@redhat.com>
 
@@ -580,7 +588,7 @@
 	different project/version.
 
 2009-08-02  Paolo Bonzini  <bonzini@gnu.org>
-            Bruno Haible  <bruno@clisp.org>
+	    Bruno Haible  <bruno@clisp.org>
 
 	Tests for module 'pipe-filter-gi'.
 	* modules/pipe-filter-gi-tests: New file.
@@ -595,7 +603,7 @@
 	* modules/pipe-filter-gi: New file.
 
 2009-08-02  Bruno Haible  <bruno@clisp.org>
-            Paolo Bonzini  <bonzini@gnu.org>
+	    Paolo Bonzini  <bonzini@gnu.org>
 
 	Tests for module 'pipe-filter-ii'.
 	* modules/pipe-filter-ii-tests: New file.
@@ -621,7 +629,7 @@
 	* lib/gethostname.c: Include limits.h.
 
 2009-08-02  Simon Josefsson  <simon@josefsson.org>
-            Bruno Haible  <bruno@clisp.org>
+	    Bruno Haible  <bruno@clisp.org>
 
 	Ensure HOST_NAME_MAX as part of the gethostname module.
 	* m4/gethostname.m4 (gl_FUNC_GETHOSTNAME): On native Windows platforms,
--- a/lib/fpurge.c
+++ b/lib/fpurge.c
@@ -35,7 +35,7 @@
   /* The __fpurge function does not have a return value.  */
   return 0;
 
-#elif HAVE_FPURGE                   /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X */
+#elif HAVE_FPURGE                   /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin 1.7 */
 
   /* Call the system's fpurge function.  */
 # undef fpurge
@@ -49,7 +49,7 @@
        <stdio.h> on BSD systems says:
          "The following always hold: if _flags & __SRD, _w is 0."
        If this invariant is not fulfilled and the stream is read-write but
-       currently writing, subsequent putc or fputc calls will write directly
+       currently reading, subsequent putc or fputc calls will write directly
        into the buffer, although they shouldn't be allowed to.  */
     if ((fp_->_flags & __SRD) != 0)
       fp_->_w = 0;
--- a/m4/fpurge.m4
+++ b/m4/fpurge.m4
@@ -1,4 +1,4 @@
-# fpurge.m4 serial 3
+# fpurge.m4 serial 4
 dnl Copyright (C) 2007, 2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,11 +10,36 @@
   AC_CHECK_FUNCS_ONCE([fpurge])
   AC_CHECK_FUNCS_ONCE([__fpurge])
   AC_CHECK_DECLS([fpurge], , , [[#include <stdio.h>]])
-  dnl For now, lib/fpurge.c is always compiled.
   if test "x$ac_cv_func_fpurge" = xyes; then
-    REPLACE_FPURGE=1
+    # Detect BSD bug.  Only cygwin 1.7 is known to be immune.
+    AC_CACHE_CHECK([whether fpurge works], [gl_cv_func_fpurge_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
+]], [FILE *f = fopen ("conftest.txt", "w+");
+	if (!f) return 1;
+	if (fputc ('a', f) != 'a') return 2;
+	rewind (f);
+	if (fgetc (f) != 'a') return 3;
+	if (fgetc (f) != EOF) return 4;
+	if (fpurge (f) != 0) return 5;
+	if (putc ('b', f) != 'b') return 6;
+	if (fclose (f) != 0) return 7;
+	if ((f = fopen ("conftest.txt", "r")) == NULL) return 8;
+	if (fgetc (f) != 'a') return 9;
+	if (fgetc (f) != 'b') return 10;
+	if (fgetc (f) != EOF) return 11;
+	if (fclose (f) != 0) return 12;
+	if (remove ("conftest.txt") != 0) return 13;
+	return 0;])],
+      [gl_cv_func_fpurge_works=yes], [gl_cv_func_fpurge_works=no],
+      [gl_cv_func_fpurge_works='guessing no'])])
+    if test "x$gl_cv_func_fpurge_works" != xyes; then
+      REPLACE_FPURGE=1
+    fi
   fi
   if test "x$ac_cv_have_decl_fpurge" = xno; then
     HAVE_DECL_FPURGE=0
   fi
+  if test "$REPLACE_FPURGE$HAVE_DECL_FPURGE" != 01; then
+    AC_LIBOBJ([fpurge])
+  fi
 ])
--- a/tests/test-fpurge.c
+++ b/tests/test-fpurge.c
@@ -61,8 +61,9 @@
     goto skip;
   if (fflush (fp))
     goto skip;
-  if (fwrite ("az", 1, 2, fp) < 2)
+  if (fwrite ("bz", 1, 2, fp) < 2)
     goto skip;
+  /* Discard pending write.  */
   ASSERT (fpurge (fp) == 0);
   ASSERT (fclose (fp) == 0);
 
@@ -72,16 +73,37 @@
     goto skip;
   {
     char buf[8];
-    if (fread (buf, 1, 8, fp) < 8)
+    if (fread (buf, 1, 7, fp) < 7)
       goto skip;
-    ASSERT (memcmp (buf, "foogarsh", 8) == 0);
+    ASSERT (memcmp (buf, "foogars", 7) == 0);
   }
+  /* Discard the buffered 'h', leaving position at EOF.  */
   ASSERT (fpurge (fp) == 0);
+  ASSERT (getc (fp) == EOF);
   ASSERT (fclose (fp) == 0);
 
+  /* Ensure that purging a read does not corrupt subsequent writes.  */
+  fp = fopen (TESTFILE, "r+");
+  ASSERT (fp);
+  ASSERT (fseek (fp, -1, SEEK_END) == 0);
+  ASSERT (getc (fp) == 'h');
+  ASSERT (getc (fp) == EOF);
+  ASSERT (fpurge (fp) == 0);
+  ASSERT (putc ('!', fp) == '!');
+  ASSERT (fclose (fp) == 0);
+  fp = fopen (TESTFILE, "r");
+  ASSERT (fp);
+  {
+    char buf[9];
+    ASSERT (fread (buf, 1, 9, fp) == 9);
+    ASSERT (memcmp (buf, "foogarsh!", 9) == 0);
+  }
+
+  remove (TESTFILE);
   return 0;
 
  skip:
-  fprintf (stderr, "Skipping test: file operations failed.\n");
+  fprintf (stderr, "Skipping test: prerequisite file operations failed.\n");
+  remove (TESTFILE);
   return 77;
 }