summaryrefslogtreecommitdiff
path: root/lib/fwriteerror.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2003-09-15 19:15:22 +0000
committerBruno Haible <bruno@clisp.org>2003-09-15 19:15:22 +0000
commit96a66d44e6496b976ff6ece7d836f2a37f2c7ed1 (patch)
tree0e33a7ee75197ae0df61b5815db76fd0eea44316 /lib/fwriteerror.c
parent3da65b40b04469445ecc2a2222b914fd6c6eb826 (diff)
downloadgnulib-96a66d44e6496b976ff6ece7d836f2a37f2c7ed1.tar.gz
New module 'fwriteerror'.
Diffstat (limited to 'lib/fwriteerror.c')
-rw-r--r--lib/fwriteerror.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/fwriteerror.c b/lib/fwriteerror.c
new file mode 100644
index 0000000000..364db86093
--- /dev/null
+++ b/lib/fwriteerror.c
@@ -0,0 +1,122 @@
+/* Detect write error on a stream.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "fwriteerror.h"
+
+#include <errno.h>
+
+int
+fwriteerror (FILE *fp)
+{
+ /* Need to
+ 1. test the error indicator of the stream,
+ 2. flush the buffers (what fclose() would do), testing for error again.
+ We can equally well swap these steps; this leads to smaller code. */
+
+ /* Clear errno, so that on non-POSIX systems the caller doesn't see a
+ wrong value of errno when we return -1. */
+ errno = 0;
+
+ if (fflush (fp))
+ return -1; /* errno is set here */
+
+ if (ferror (fp))
+ {
+ /* The stream had an error earlier, but its errno was lost. If the
+ error was not temporary, we can get the same errno by writing and
+ flushing one more byte. We can do so because at this point the
+ stream's contents is garbage anyway. */
+ if (fputc ('\0', fp) == EOF)
+ return -1; /* errno is set here */
+ if (fflush (fp))
+ return -1; /* errno is set here */
+ /* Give up on errno. */
+ errno = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+#if TEST
+
+/* Name of a file on which writing fails. On systems without /dev/full,
+ you can choose a filename on a full filesystem. */
+#define UNWRITABLE_FILE "/dev/full"
+
+int
+main ()
+{
+ static int sizes[] =
+ {
+ 511, 512, 513,
+ 1023, 1024, 1025,
+ 2047, 2048, 2049,
+ 4095, 4096, 4097,
+ 8191, 8192, 8193
+ };
+ static char dummy[8193];
+ unsigned int i, j;
+
+ for (i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++)
+ {
+ size_t size = sizes[i];
+
+ for (j = 0; j < 2; j++)
+ {
+ /* Run a test depending on i and j:
+ Write size bytes and then calls fflush if j==1. */
+ FILE *stream = fopen (UNWRITABLE_FILE, "w");
+
+ if (stream == NULL)
+ {
+ fprintf (stderr, "Test %u:%u: could not open file\n", i, j);
+ continue;
+ }
+
+ fwrite (dummy, 347, 1, stream);
+ fwrite (dummy, size - 347, 1, stream);
+ if (j)
+ fflush (stream);
+
+ if (fwriteerror (stream) == -1)
+ {
+ if (errno != ENOSPC)
+ fprintf (stderr, "Test %u:%u: fwriteerror ok, errno = %d\n",
+ i, j, errno);
+ }
+ else
+ fprintf (stderr, "Test %u:%u: fwriteerror found no error!\n",
+ i, j);
+
+ if (fclose (stream))
+ fprintf (stderr, "Test %u:%u: fclose failed, errno = %d\n",
+ i, j, errno);
+ }
+ }
+
+ return 0;
+}
+
+#endif