Implement freading and fwriting.
authorEric Blake <ebb9@byu.net>
Thu, 26 Apr 2007 13:16:50 +0000 (13:16 +0000)
committerEric Blake <ebb9@byu.net>
Thu, 26 Apr 2007 13:16:50 +0000 (13:16 +0000)
* 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.

14 files changed:
ChangeLog
MODULES.html.sh
lib/freading.c [new file with mode: 0644]
lib/freading.h [new file with mode: 0644]
lib/fwriting.c [new file with mode: 0644]
lib/fwriting.h [new file with mode: 0644]
m4/freading.m4 [new file with mode: 0644]
m4/fwriting.m4 [new file with mode: 0644]
modules/freading [new file with mode: 0644]
modules/freading-tests [new file with mode: 0644]
modules/fwriting [new file with mode: 0644]
modules/fwriting-tests [new file with mode: 0644]
tests/test-freading.c [new file with mode: 0644]
tests/test-fwriting.c [new file with mode: 0644]

index 2285867..6d6d954 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-04-26  Eric Blake  <ebb9@byu.net>
+       and Bruno Haible  <bruno@clisp.org>
+
+       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.
+
 2007-04-26  Bruno Haible  <bruno@clisp.org>
 
        * lib/stdio_.h (fseeko, ftello): Check that off_t has the same size as
index 277b09d..179552c 100755 (executable)
@@ -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 (file)
index 0000000..15ad069
--- /dev/null
@@ -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 (file)
index 0000000..e0db1f7
--- /dev/null
@@ -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 (file)
index 0000000..3020537
--- /dev/null
@@ -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 (file)
index 0000000..07037ef
--- /dev/null
@@ -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 (file)
index 0000000..b1f9089
--- /dev/null
@@ -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 (file)
index 0000000..f1fd7dc
--- /dev/null
@@ -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 (file)
index 0000000..fe2e5f5
--- /dev/null
@@ -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 (file)
index 0000000..fea9a69
--- /dev/null
@@ -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 (file)
index 0000000..0903a04
--- /dev/null
@@ -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 (file)
index 0000000..f4258d4
--- /dev/null
@@ -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 (file)
index 0000000..02414e5
--- /dev/null
@@ -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 <bruno@clisp.org>, 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 (file)
index 0000000..24279f3
--- /dev/null
@@ -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 <bruno@clisp.org>, 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;
+}