bug-gnulib
[Top][All Lists]
Advanced

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

Re: no new modules 'freading', 'fwriting'


From: Eric Blake
Subject: Re: no new modules 'freading', 'fwriting'
Date: Wed, 25 Apr 2007 11:18:36 -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

According to Bruno Haible on 4/13/2007 6:30 PM:
> I got these working reasonably only on glibc. Portability problems occurred
> on Solaris, OSF/1, AIX, MacOS X, IRIX, HP-UX. If someone wants to continue,
> here's the code.

What sort of problems?  I got it the tests to work on both cygwin and
mingw as follows, so I think it is worth checking it in as a starting
point.  I have not done so yet, in case you have feedback first.

Two files attached; first, the diff from your original; second, the
overall diff.  I just deleted the use of fflush after reading in your
tests, as that is not portable without the fflush module (which still
doesn't work on at least mingw).  Also, on mingw, freading reports false
after fseek, and flush reports false after fflush, but I think both of
these conditions are okay.  In other words, the functionality of freading
is not so much to determine whether the last operation was a read, but to
determine whether a reposition must take place before attempting a write
to avoid undefined behavior.  Likewise, fwriting is not so much to
determine whether the last operation was a write, but whether a fflush is
required before switching back to read.

Maybe it is worth changing the specification comments to state that it is
possible for both freading and fwriting to be false (only if the file is
read-write; and the last action was open, reposition (fseek, fsetpos, or
rewind), EOF on reading, or fflush on writing, since those are the actions
that must occur on transition between read and write according to POSIX),
but that it is never possible to have both freading and fwriting true at
once.

2007-04-25  Eric Blake  <address@hidden>
        and Bruno Haible  <address@hidden>

        Implement freading and fwriting.
        * lib/freading.c: New file.
        * lib/freading.h: Likewise.
        * m4/freading.m4: Likewise.
        * modules/freading: Likewise.
        * modules/freading-tests: Likewise.
        * tests/test-freading.c: Likewise.
        * lib/fwriting.c: New file.
        * lib/fwriting.h: Likewise.
        * m4/fwriting.m4: Likewise.
        * modules/fwriting: Likewise.
        * modules/fwriting-tests: Likewise.
        * tests/test-fwriting.c: Likewise.
        * MODULES.html.sh (File stream based Input/Output): Mention them.

-- 
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
diff --git a/build-aux/link-warning.h b/build-aux/link-warning.h
diff --git a/lib/dummy.c b/lib/dummy.c
diff --git a/lib/fflush.c b/lib/fflush.c
diff --git a/lib/fpurge.h b/lib/fpurge.h
diff --git a/lib/freading.c b/lib/freading.c
index c937926..15ad069 100644
--- a/lib/freading.c
+++ b/lib/freading.c
@@ -36,9 +36,7 @@ freading (FILE *fp)
              && (fp->_flags & _IO_CURRENTLY_PUTTING) == 0
              && fp->_IO_read_base != NULL));
 #elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, 
Cygwin */
-  /* This is only an approximation.  */
-  return !((fp->_flags & (__SRW | __SWR)) != 0
-          && fp->_bf._base != NULL && fp->_p > fp->_bf._base);
+  return (fp->_flags & __SRD) != 0;
 #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw 
*/
   return (fp->_flag & _IOREAD) != 0;
 #else
diff --git a/lib/freading.h b/lib/freading.h
diff --git a/lib/fwriting.c b/lib/fwriting.c
index f58658b..3020537 100644
--- a/lib/fwriting.c
+++ b/lib/fwriting.c
@@ -29,9 +29,7 @@ fwriting (FILE *fp)
 #if defined _IO_ferror_unlocked     /* GNU libc, BeOS */
   return (fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) != 0;
 #elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, 
Cygwin */
-  /* This is only an approximation.  */
-  return !((fp->_flags & (__SRW | __SRD)) != 0
-          && fp->_bf._base != NULL && fp->_r > 0);
+  return (fp->_flags & __SWR) != 0;
 #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw 
*/
   return (fp->_flag & _IOWRT) != 0;
 #else
diff --git a/lib/fwriting.h b/lib/fwriting.h
diff --git a/lib/stdbool_.h b/lib/stdbool_.h
diff --git a/lib/unistd_.h b/lib/unistd_.h
diff --git a/m4/absolute-header.m4 b/m4/absolute-header.m4
diff --git a/m4/fpurge.m4 b/m4/fpurge.m4
diff --git a/m4/freading.m4 b/m4/freading.m4
diff --git a/m4/ftello.m4 b/m4/ftello.m4
diff --git a/m4/fwriting.m4 b/m4/fwriting.m4
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
diff --git a/m4/onceonly_2_57.m4 b/m4/onceonly_2_57.m4
diff --git a/m4/stdbool.m4 b/m4/stdbool.m4
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
diff --git a/modules/freading-tests b/modules/freading-tests
index 7b87926..fea9a69 100644
--- a/modules/freading-tests
+++ b/modules/freading-tests
@@ -8,4 +8,4 @@ configure.ac:
 Makefile.am:
 TESTS += test-freading
 check_PROGRAMS += test-freading
-
+MOSTLYCLEANFILES += t-freading.tmp
diff --git a/modules/fwriting-tests b/modules/fwriting-tests
index 531351e..f4258d4 100644
--- a/modules/fwriting-tests
+++ b/modules/fwriting-tests
@@ -8,4 +8,4 @@ configure.ac:
 Makefile.am:
 TESTS += test-fwriting
 check_PROGRAMS += test-fwriting
-
+MOSTLYCLEANFILES += t-fwriting.tmp
diff --git a/tests/test-fpurge.c b/tests/test-fpurge.c
diff --git a/tests/test-freading.c b/tests/test-freading.c
index 933d415..02414e5 100644
--- a/tests/test-freading.c
+++ b/tests/test-freading.c
@@ -32,7 +32,7 @@ main ()
 {
   FILE *fp;
 
-  /* Create a file with some contents.  */
+  /* Create a file with some contents.  Write-only file is never reading.  */
   fp = fopen (TESTFILE, "w");
   if (fp == NULL)
     goto skip;
@@ -43,7 +43,7 @@ main ()
   if (fclose (fp))
     goto skip;
 
-  /* Open it in read-only mode.  */
+  /* Open it in read-only mode.  Read-only file is always reading.  */
   fp = fopen (TESTFILE, "r");
   if (fp == NULL)
     goto skip;
@@ -57,18 +57,17 @@ main ()
   if (fgetc (fp) != 'b')
     goto skip;
   ASSERT (freading (fp));
-  fflush (fp);
-  ASSERT (freading (fp));
-  if (fgetc (fp) != 'a')
-    goto skip;
-  ASSERT (freading (fp));
   if (fseek (fp, 0, SEEK_END))
     goto skip;
   ASSERT (freading (fp));
   if (fclose (fp))
     goto skip;
 
-  /* Open it in read-write mode.  */
+  /* Open it in read-write mode.  POSIX requires a reposition (fseek,
+     fsetpos, rewind) or EOF when transitioning from read to write;
+     freading is only deterministic after input or output, but this
+     test case should be portable even on open, after reposition, and
+     at EOF.  */
   fp = fopen (TESTFILE, "r+");
   if (fp == NULL)
     goto skip;
@@ -78,25 +77,22 @@ main ()
   ASSERT (freading (fp));
   if (fseek (fp, 2, SEEK_CUR))
     goto skip;
-  ASSERT (freading (fp));
+  /* freading (fp)) is undefined here, but fwriting is false.  */
   if (fgetc (fp) != 'b')
     goto skip;
   ASSERT (freading (fp));
-  fflush (fp);
-  ASSERT (freading (fp));
-  if (fgetc (fp) != 'a')
+  if (fseek (fp, 0, SEEK_CUR) != 0)
     goto skip;
-  ASSERT (freading (fp));
   if (fputc ('z', fp) != 'z')
     goto skip;
   ASSERT (!freading (fp));
   if (fseek (fp, 0, SEEK_END))
     goto skip;
-  /* freading (fp)) is undefined here.  */
+  ASSERT (!freading (fp));
   if (fclose (fp))
     goto skip;
 
-  /* Open it in append mode.  */
+  /* Open it in append mode.  Write-only file is never reading.  */
   fp = fopen (TESTFILE, "a");
   if (fp == NULL)
     goto skip;
diff --git a/tests/test-fseeko.c b/tests/test-fseeko.c
diff --git a/tests/test-ftello.c b/tests/test-ftello.c
diff --git a/tests/test-fwriting.c b/tests/test-fwriting.c
index f677db7..24279f3 100644
--- a/tests/test-fwriting.c
+++ b/tests/test-fwriting.c
@@ -32,7 +32,7 @@ main ()
 {
   FILE *fp;
 
-  /* Create a file with some contents.  */
+  /* Create a file with some contents.  Write-only file is always writing.  */
   fp = fopen (TESTFILE, "w");
   if (fp == NULL)
     goto skip;
@@ -43,7 +43,7 @@ main ()
   if (fclose (fp))
     goto skip;
 
-  /* Open it in read-only mode.  */
+  /* Open it in read-only mode.  Read-only file is never writing.  */
   fp = fopen (TESTFILE, "r");
   if (fp == NULL)
     goto skip;
@@ -57,18 +57,17 @@ main ()
   if (fgetc (fp) != 'b')
     goto skip;
   ASSERT (!fwriting (fp));
-  fflush (fp);
-  ASSERT (!fwriting (fp));
-  if (fgetc (fp) != 'a')
-    goto skip;
-  ASSERT (!fwriting (fp));
   if (fseek (fp, 0, SEEK_END))
     goto skip;
   ASSERT (!fwriting (fp));
   if (fclose (fp))
     goto skip;
 
-  /* Open it in read-write mode.  */
+  /* Open it in read-write mode.  POSIX requires a reposition (fseek,
+     fsetpos, rewind) or fflush when transitioning from write to read,
+     fwriting is only deterministic after input or output, but this
+     test case should be portable even on open, after reposition, and
+     after fflush.  */
   fp = fopen (TESTFILE, "r+");
   if (fp == NULL)
     goto skip;
@@ -82,17 +81,14 @@ main ()
   if (fgetc (fp) != 'b')
     goto skip;
   ASSERT (!fwriting (fp));
-  fflush (fp);
-  ASSERT (!fwriting (fp));
-  if (fgetc (fp) != 'a')
+  if (fseek (fp, 0, SEEK_CUR) != 0)
     goto skip;
-  ASSERT (!fwriting (fp));
   if (fputc ('z', fp) != 'z')
     goto skip;
   ASSERT (fwriting (fp));
   if (fseek (fp, 0, SEEK_END))
     goto skip;
-  /* fwriting (fp) is undefined here.  */
+  /* fwriting (fp) is undefined here, but freading is false.  */
   if (fclose (fp))
     goto skip;
 
diff --git a/tests/test-stdbool.c b/tests/test-stdbool.c
diff --git a/tests/test-stdio.c b/tests/test-stdio.c
diff --git a/tests/test-unistd.c b/tests/test-unistd.c
diff --git a/ChangeLog b/ChangeLog
index 6218a8e..721bbc9 100644
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 277b09d..179552c 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2196,6 +2196,8 @@ func_all_modules ()
   func_module closeout
   func_module fopen-safer
   func_module fpending
+  func_module freading
+  func_module fwriting
   func_module getpass
   func_module getpass-gnu
   func_module stdlib-safer
diff --git a/lib/freading.c b/lib/freading.c
new file mode 100644
index 0000000..15ad069
--- /dev/null
+++ b/lib/freading.c
@@ -0,0 +1,47 @@
+/* Retrieve information about a FILE stream.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "freading.h"
+
+/* Don't use glibc's __freading function, see
+   <http://sourceware.org/bugzilla/show_bug.cgi?id=4359>  */
+#if !(HAVE___FREADING && !defined __GLIBC__)
+
+bool
+freading (FILE *fp)
+{
+  /* Most systems provide FILE as a struct and the necessary bitmask in
+     <stdio.h>, because they need it for implementing getc() and putc() as
+     fast macros.  */
+#if defined _IO_ferror_unlocked     /* GNU libc, BeOS */
+  return ((fp->_flags & _IO_NO_WRITES) != 0
+         || ((fp->_flags & _IO_NO_READS) == 0
+             && (fp->_flags & _IO_CURRENTLY_PUTTING) == 0
+             && fp->_IO_read_base != NULL));
+#elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, 
Cygwin */
+  return (fp->_flags & __SRD) != 0;
+#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw 
*/
+  return (fp->_flag & _IOREAD) != 0;
+#else
+ #error "Please port gnulib freading.c to your platform!"
+#endif
+}
+
+#endif
diff --git a/lib/freading.h b/lib/freading.h
new file mode 100644
index 0000000..e0db1f7
--- /dev/null
+++ b/lib/freading.h
@@ -0,0 +1,44 @@
+/* Retrieve information about a FILE stream.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+/* Return true if the stream STREAM is opened read-only, or if the last
+   operation on the stream was a read operation.  Return false if the stream
+   supports writing and the last operation on it was a write operation or
+   there was no such operation.
+   STREAM must not be wide-character oriented.  */
+
+#if HAVE___FREADING && !defined __GLIBC__ /* Solaris >= 7, not glibc >= 2.2  */
+
+# include <stdio_ext.h>
+# define freading(stream) (__freading (stream) != 0)
+
+#else
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+extern bool freading (FILE *stream);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/lib/fwriting.c b/lib/fwriting.c
new file mode 100644
index 0000000..3020537
--- /dev/null
+++ b/lib/fwriting.c
@@ -0,0 +1,38 @@
+/* Retrieve information about a FILE stream.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "fwriting.h"
+
+bool
+fwriting (FILE *fp)
+{
+  /* Most systems provide FILE as a struct and the necessary bitmask in
+     <stdio.h>, because they need it for implementing getc() and putc() as
+     fast macros.  */
+#if defined _IO_ferror_unlocked     /* GNU libc, BeOS */
+  return (fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) != 0;
+#elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, 
Cygwin */
+  return (fp->_flags & __SWR) != 0;
+#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw 
*/
+  return (fp->_flag & _IOWRT) != 0;
+#else
+ #error "Please port gnulib fwriting.c to your platform!"
+#endif
+}
diff --git a/lib/fwriting.h b/lib/fwriting.h
new file mode 100644
index 0000000..07037ef
--- /dev/null
+++ b/lib/fwriting.h
@@ -0,0 +1,44 @@
+/* Retrieve information about a FILE stream.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+/* Return true if the stream STREAM is opened write-only or append-only, or
+   if the last operation on the stream was a write operation.  Return false
+   if the stream supports reading and the last operation on it was a read
+   operation or there was no such operation.
+   STREAM must not be wide-character oriented.  */
+
+#if HAVE___FWRITING /* glibc >= 2.2, Solaris >= 7 */
+
+# include <stdio_ext.h>
+# define fwriting(stream) (__fwriting (stream) != 0)
+
+#else
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+extern bool fwriting (FILE *stream);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/m4/freading.m4 b/m4/freading.m4
new file mode 100644
index 0000000..b1f9089
--- /dev/null
+++ b/m4/freading.m4
@@ -0,0 +1,10 @@
+# freading.m4 serial 1
+dnl Copyright (C) 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FREADING],
+[
+  AC_CHECK_FUNCS_ONCE([__freading])
+])
diff --git a/m4/fwriting.m4 b/m4/fwriting.m4
new file mode 100644
index 0000000..f1fd7dc
--- /dev/null
+++ b/m4/fwriting.m4
@@ -0,0 +1,13 @@
+# fwriting.m4 serial 1
+dnl Copyright (C) 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FWRITING],
+[
+  AC_CHECK_FUNCS_ONCE([__fwriting])
+  if test $ac_cv_func___fwriting = no; then
+    AC_LIBOBJ([fwriting])
+  fi
+])
diff --git a/modules/freading b/modules/freading
new file mode 100644
index 0000000..fe2e5f5
--- /dev/null
+++ b/modules/freading
@@ -0,0 +1,26 @@
+Description:
+freading() function: Determine whether a FILE stream is currently doing 
reading.
+
+Files:
+lib/freading.h
+lib/freading.c
+m4/freading.m4
+
+Depends-on:
+stdbool
+
+configure.ac:
+gl_FUNC_FREADING
+
+Makefile.am:
+lib_SOURCES += freading.c
+
+Include:
+"freading.h"
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible, Eric Blake
+
diff --git a/modules/freading-tests b/modules/freading-tests
new file mode 100644
index 0000000..fea9a69
--- /dev/null
+++ b/modules/freading-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-freading.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-freading
+check_PROGRAMS += test-freading
+MOSTLYCLEANFILES += t-freading.tmp
diff --git a/modules/fwriting b/modules/fwriting
new file mode 100644
index 0000000..0903a04
--- /dev/null
+++ b/modules/fwriting
@@ -0,0 +1,25 @@
+Description:
+fwriting() function: Determine whether a FILE stream is currently doing 
writing.
+
+Files:
+lib/fwriting.h
+lib/fwriting.c
+m4/fwriting.m4
+
+Depends-on:
+stdbool
+
+configure.ac:
+gl_FUNC_FWRITING
+
+Makefile.am:
+
+Include:
+"fwriting.h"
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible, Eric Blake
+
diff --git a/modules/fwriting-tests b/modules/fwriting-tests
new file mode 100644
index 0000000..f4258d4
--- /dev/null
+++ b/modules/fwriting-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-fwriting.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fwriting
+check_PROGRAMS += test-fwriting
+MOSTLYCLEANFILES += t-fwriting.tmp
diff --git a/tests/test-freading.c b/tests/test-freading.c
new file mode 100644
index 0000000..02414e5
--- /dev/null
+++ b/tests/test-freading.c
@@ -0,0 +1,111 @@
+/* Test of freading() function.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Bruno Haible <address@hidden>, 2007.  */
+
+#include <config.h>
+
+#include "freading.h"
+
+#include <stdlib.h>
+
+#define ASSERT(expr) if (!(expr)) abort ();
+
+#define TESTFILE "t-freading.tmp"
+
+int
+main ()
+{
+  FILE *fp;
+
+  /* Create a file with some contents.  Write-only file is never reading.  */
+  fp = fopen (TESTFILE, "w");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fwrite ("foobarsh", 1, 8, fp) < 8)
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in read-only mode.  Read-only file is always reading.  */
+  fp = fopen (TESTFILE, "r");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (freading (fp));
+  if (fgetc (fp) != 'f')
+    goto skip;
+  ASSERT (freading (fp));
+  if (fseek (fp, 2, SEEK_CUR))
+    goto skip;
+  ASSERT (freading (fp));
+  if (fgetc (fp) != 'b')
+    goto skip;
+  ASSERT (freading (fp));
+  if (fseek (fp, 0, SEEK_END))
+    goto skip;
+  ASSERT (freading (fp));
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in read-write mode.  POSIX requires a reposition (fseek,
+     fsetpos, rewind) or EOF when transitioning from read to write;
+     freading is only deterministic after input or output, but this
+     test case should be portable even on open, after reposition, and
+     at EOF.  */
+  fp = fopen (TESTFILE, "r+");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fgetc (fp) != 'f')
+    goto skip;
+  ASSERT (freading (fp));
+  if (fseek (fp, 2, SEEK_CUR))
+    goto skip;
+  /* freading (fp)) is undefined here, but fwriting is false.  */
+  if (fgetc (fp) != 'b')
+    goto skip;
+  ASSERT (freading (fp));
+  if (fseek (fp, 0, SEEK_CUR) != 0)
+    goto skip;
+  if (fputc ('z', fp) != 'z')
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fseek (fp, 0, SEEK_END))
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in append mode.  Write-only file is never reading.  */
+  fp = fopen (TESTFILE, "a");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fwrite ("bla", 1, 3, fp) < 3)
+    goto skip;
+  ASSERT (!freading (fp));
+  if (fclose (fp))
+    goto skip;
+
+  return 0;
+
+ skip:
+  fprintf (stderr, "Skipping test: file operations failed.\n");
+  return 77;
+}
diff --git a/tests/test-fwriting.c b/tests/test-fwriting.c
new file mode 100644
index 0000000..24279f3
--- /dev/null
+++ b/tests/test-fwriting.c
@@ -0,0 +1,111 @@
+/* Test of fwriting() function.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Bruno Haible <address@hidden>, 2007.  */
+
+#include <config.h>
+
+#include "fwriting.h"
+
+#include <stdlib.h>
+
+#define ASSERT(expr) if (!(expr)) abort ();
+
+#define TESTFILE "t-fwriting.tmp"
+
+int
+main ()
+{
+  FILE *fp;
+
+  /* Create a file with some contents.  Write-only file is always writing.  */
+  fp = fopen (TESTFILE, "w");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (fwriting (fp));
+  if (fwrite ("foobarsh", 1, 8, fp) < 8)
+    goto skip;
+  ASSERT (fwriting (fp));
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in read-only mode.  Read-only file is never writing.  */
+  fp = fopen (TESTFILE, "r");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fgetc (fp) != 'f')
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fseek (fp, 2, SEEK_CUR))
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fgetc (fp) != 'b')
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fseek (fp, 0, SEEK_END))
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in read-write mode.  POSIX requires a reposition (fseek,
+     fsetpos, rewind) or fflush when transitioning from write to read,
+     fwriting is only deterministic after input or output, but this
+     test case should be portable even on open, after reposition, and
+     after fflush.  */
+  fp = fopen (TESTFILE, "r+");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fgetc (fp) != 'f')
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fseek (fp, 2, SEEK_CUR))
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fgetc (fp) != 'b')
+    goto skip;
+  ASSERT (!fwriting (fp));
+  if (fseek (fp, 0, SEEK_CUR) != 0)
+    goto skip;
+  if (fputc ('z', fp) != 'z')
+    goto skip;
+  ASSERT (fwriting (fp));
+  if (fseek (fp, 0, SEEK_END))
+    goto skip;
+  /* fwriting (fp) is undefined here, but freading is false.  */
+  if (fclose (fp))
+    goto skip;
+
+  /* Open it in append mode.  */
+  fp = fopen (TESTFILE, "a");
+  if (fp == NULL)
+    goto skip;
+  ASSERT (fwriting (fp));
+  if (fwrite ("bla", 1, 3, fp) < 3)
+    goto skip;
+  ASSERT (fwriting (fp));
+  if (fclose (fp))
+    goto skip;
+
+  return 0;
+
+ skip:
+  fprintf (stderr, "Skipping test: file operations failed.\n");
+  return 77;
+}

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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