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 <[EMAIL PROTECTED]> and Bruno Haible <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED]
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 <[EMAIL PROTECTED]>, 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 <[EMAIL PROTECTED]>, 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; +}
signature.asc
Description: OpenPGP digital signature