* 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 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
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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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
--- /dev/null
+# 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])
+])
--- /dev/null
+# 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
+])
--- /dev/null
+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
+
--- /dev/null
+Files:
+tests/test-freading.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-freading
+check_PROGRAMS += test-freading
+MOSTLYCLEANFILES += t-freading.tmp
--- /dev/null
+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
+
--- /dev/null
+Files:
+tests/test-fwriting.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fwriting
+check_PROGRAMS += test-fwriting
+MOSTLYCLEANFILES += t-fwriting.tmp
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}