changeset 11841:de4ad188001d

Clarify fpurge's effect on the file position.
author Bruno Haible <bruno@clisp.org>
date Sun, 16 Aug 2009 15:51:23 +0200
parents d2f20b59cd42
children f4bcc8a0cd47
files ChangeLog lib/stdio.in.h tests/test-fpurge.c
diffstat 3 files changed, 92 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-08-16  Bruno Haible  <bruno@clisp.org>
+
+	Clarify fpurge's effect on the file position.
+	* lib/stdio.in.h (fpurge): Specify the file position after fpurge.
+	* tests/test-fpurge.c (main): Make a second pass for checking the file
+	position.
+
 2009-08-16  Bruno Haible  <bruno@clisp.org>
 
 	* m4/fpurge.m4 (gl_FUNC_FPURGE): Don't compile fpurge.c if only the
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -414,6 +414,9 @@
 # if @REPLACE_FPURGE@ || !@HAVE_DECL_FPURGE@
   /* Discard all pending buffered I/O data on STREAM.
      STREAM must not be wide-character oriented.
+     When discarding pending output, the file position is set back to where it
+     was before the write calls.  When discarding pending input, the file
+     position is advanced to match the end of the previously read input.
      Return 0 if successful.  Upon error, return -1 and set errno.  */
   extern int fpurge (FILE *gl_stream);
 # endif
--- a/tests/test-fpurge.c
+++ b/tests/test-fpurge.c
@@ -40,74 +40,95 @@
 int
 main ()
 {
-  FILE *fp;
+  int check_filepos;
+
+  for (check_filepos = 0; check_filepos <= 1; check_filepos++)
+    {
+      FILE *fp;
 
-  /* Create a file with some contents.  */
-  fp = fopen (TESTFILE, "w");
-  if (fp == NULL)
-    goto skip;
-  if (fwrite ("foobarsh", 1, 8, fp) < 8)
-    goto skip;
-  if (fclose (fp))
-    goto skip;
+      /* Create a file with some contents.  */
+      fp = fopen (TESTFILE, "w");
+      if (fp == NULL)
+	goto skip;
+      if (fwrite ("foobarsh", 1, 8, fp) < 8)
+	goto skip;
+      if (fclose (fp))
+	goto skip;
 
-  /* The file's contents is now "foobarsh".  */
+      /* The file's contents is now "foobarsh".  */
 
-  /* Open it in read-write mode.  */
-  fp = fopen (TESTFILE, "r+");
-  if (fp == NULL)
-    goto skip;
-  if (fseek (fp, 3, SEEK_CUR))
-    goto skip;
-  if (fwrite ("g", 1, 1, fp) < 1)
-    goto skip;
-  if (fflush (fp))
-    goto skip;
-  if (fwrite ("bz", 1, 2, fp) < 2)
-    goto skip;
-  /* Discard pending write.  */
-  ASSERT (fpurge (fp) == 0);
-  ASSERT (fclose (fp) == 0);
+      /* Open it in read-write mode.  */
+      fp = fopen (TESTFILE, "r+");
+      if (fp == NULL)
+	goto skip;
+      if (fseek (fp, 3, SEEK_CUR))
+	goto skip;
+      if (fwrite ("g", 1, 1, fp) < 1)
+	goto skip;
+      if (fflush (fp))
+	goto skip;
+      if (fwrite ("bz", 1, 2, fp) < 2)
+	goto skip;
+      /* Discard pending write.  */
+      ASSERT (fpurge (fp) == 0);
+      /* Verify that when discarding pending output, the file position is set
+	 back to where it was before the write calls.  */
+      if (check_filepos)
+	ASSERT (ftell (fp) == 4);
+      ASSERT (fclose (fp) == 0);
 
-  /* Open it in read-only mode.  */
-  fp = fopen (TESTFILE, "r");
-  if (fp == NULL)
-    goto skip;
-  {
-    char buf[8];
-    if (fread (buf, 1, 7, fp) < 7)
-      goto skip;
-    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);
+      /* Open it in read-only mode.  */
+      fp = fopen (TESTFILE, "r");
+      if (fp == NULL)
+	goto skip;
+      /* Verify that the pending writes before the fpurge were really
+	 discarded.  */
+      {
+	char buf[8];
+	if (fread (buf, 1, 7, fp) < 7)
+	  goto skip;
+	ASSERT (memcmp (buf, "foogars", 7) == 0);
+      }
+      /* Discard the buffered 'h'.  */
+      if (check_filepos)
+	ASSERT (ftell (fp) == 7);
+      ASSERT (fpurge (fp) == 0);
+      /* Verify that when discarding pending input, the file position is
+	 advanced to match the end of the previously read input.  */
+      if (check_filepos)
+	ASSERT (ftell (fp) == 8);
+      ASSERT (getc (fp) == EOF);
+      ASSERT (fclose (fp) == 0);
 
-  /* The file's contents is now "foogarsh".  */
+      /* The file's contents is now "foogarsh".  */
 
-  /* Ensure that purging a read does not corrupt subsequent writes.  */
-  fp = fopen (TESTFILE, "r+");
-  if (fp == NULL)
-    goto skip;
-  if (fseek (fp, -1, SEEK_END))
-    goto skip;
-  ASSERT (getc (fp) == 'h');
-  ASSERT (getc (fp) == EOF);
-  ASSERT (fpurge (fp) == 0);
-  ASSERT (putc ('!', fp) == '!');
-  ASSERT (fclose (fp) == 0);
-  fp = fopen (TESTFILE, "r");
-  if (fp == NULL)
-    goto skip;
-  {
-    char buf[10];
-    ASSERT (fread (buf, 1, 10, fp) == 9);
-    ASSERT (memcmp (buf, "foogarsh!", 9) == 0);
-  }
-  ASSERT (fclose (fp) == 0);
+      /* Ensure that purging a read does not corrupt subsequent writes.  */
+      fp = fopen (TESTFILE, "r+");
+      if (fp == NULL)
+	goto skip;
+      if (fseek (fp, -1, SEEK_END))
+	goto skip;
+      ASSERT (getc (fp) == 'h');
+      ASSERT (getc (fp) == EOF);
+      if (check_filepos)
+	ASSERT (ftell (fp) == 8);
+      ASSERT (fpurge (fp) == 0);
+      if (check_filepos)
+	ASSERT (ftell (fp) == 8);
+      ASSERT (putc ('!', fp) == '!');
+      ASSERT (fclose (fp) == 0);
+      fp = fopen (TESTFILE, "r");
+      if (fp == NULL)
+	goto skip;
+      {
+	char buf[10];
+	ASSERT (fread (buf, 1, 10, fp) == 9);
+	ASSERT (memcmp (buf, "foogarsh!", 9) == 0);
+      }
+      ASSERT (fclose (fp) == 0);
 
-  /* The file's contents is now "foogarsh!".  */
+      /* The file's contents is now "foogarsh!".  */
+    }
 
   remove (TESTFILE);
   return 0;