From a8f956440539cf954fb92e2396cc58e2a111455f Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 26 Apr 2007 13:16:50 +0000 Subject: [PATCH] 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. --- ChangeLog | 18 ++++++++ MODULES.html.sh | 2 + lib/freading.c | 47 +++++++++++++++++++++ lib/freading.h | 44 ++++++++++++++++++++ lib/fwriting.c | 38 +++++++++++++++++ lib/fwriting.h | 44 ++++++++++++++++++++ m4/freading.m4 | 10 +++++ m4/fwriting.m4 | 13 ++++++ modules/freading | 26 ++++++++++++ modules/freading-tests | 11 +++++ modules/fwriting | 25 +++++++++++ modules/fwriting-tests | 11 +++++ tests/test-freading.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-fwriting.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 511 insertions(+) create mode 100644 lib/freading.c create mode 100644 lib/freading.h create mode 100644 lib/fwriting.c create mode 100644 lib/fwriting.h create mode 100644 m4/freading.m4 create mode 100644 m4/fwriting.m4 create mode 100644 modules/freading create mode 100644 modules/freading-tests create mode 100644 modules/fwriting create mode 100644 modules/fwriting-tests create mode 100644 tests/test-freading.c create mode 100644 tests/test-fwriting.c diff --git a/ChangeLog b/ChangeLog index 22858679d..6d6d954db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2007-04-26 Eric Blake + and Bruno Haible + + 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 * lib/stdio_.h (fseeko, ftello): Check that off_t has the same size as diff --git a/MODULES.html.sh b/MODULES.html.sh index 277b09d62..179552c94 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 000000000..15ad06916 --- /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 + +/* Specification. */ +#include "freading.h" + +/* Don't use glibc's __freading function, see + */ +#if !(HAVE___FREADING && !defined __GLIBC__) + +bool +freading (FILE *fp) +{ + /* Most systems provide FILE as a struct and the necessary bitmask in + , 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 000000000..e0db1f7d0 --- /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 +#include + +/* 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 +# 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 000000000..302053733 --- /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 + +/* Specification. */ +#include "fwriting.h" + +bool +fwriting (FILE *fp) +{ + /* Most systems provide FILE as a struct and the necessary bitmask in + , 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 000000000..07037ef12 --- /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 +#include + +/* 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 +# 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 000000000..b1f9089a2 --- /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 000000000..f1fd7dc2a --- /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 000000000..fe2e5f595 --- /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 000000000..fea9a69e7 --- /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 000000000..0903a04fb --- /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 000000000..f4258d494 --- /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 000000000..02414e5d0 --- /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 , 2007. */ + +#include + +#include "freading.h" + +#include + +#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 000000000..24279f313 --- /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 , 2007. */ + +#include + +#include "fwriting.h" + +#include + +#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; +} -- 2.11.0