diff options
author | Bruno Haible <bruno@clisp.org> | 2003-09-18 15:57:53 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2009-06-23 12:11:00 +0200 |
commit | 3ac79c15c81d28d9090618a64ccb5308ed8e0eb7 (patch) | |
tree | 2463d6c3aea859cdde3b9606912e58a22efbf487 /gettext-tools | |
parent | bf4d1fb1029711bebd86141ff4f6955af992ed5a (diff) | |
download | external_gettext-3ac79c15c81d28d9090618a64ccb5308ed8e0eb7.zip external_gettext-3ac79c15c81d28d9090618a64ccb5308ed8e0eb7.tar.gz external_gettext-3ac79c15c81d28d9090618a64ccb5308ed8e0eb7.tar.bz2 |
Use fwriteerror() for reliable signalling of write error during stream output.
Diffstat (limited to 'gettext-tools')
-rw-r--r-- | gettext-tools/ChangeLog | 4 | ||||
-rw-r--r-- | gettext-tools/lib/ChangeLog | 11 | ||||
-rw-r--r-- | gettext-tools/lib/Makefile.am | 1 | ||||
-rw-r--r-- | gettext-tools/lib/Makefile.msvc | 4 | ||||
-rw-r--r-- | gettext-tools/lib/Makefile.vms | 4 | ||||
-rw-r--r-- | gettext-tools/lib/fwriteerror.c | 122 | ||||
-rw-r--r-- | gettext-tools/lib/fwriteerror.h | 51 | ||||
-rw-r--r-- | gettext-tools/src/ChangeLog | 15 | ||||
-rw-r--r-- | gettext-tools/src/write-java.c | 3 | ||||
-rw-r--r-- | gettext-tools/src/write-mo.c | 3 | ||||
-rw-r--r-- | gettext-tools/src/write-po.c | 3 | ||||
-rw-r--r-- | gettext-tools/src/write-tcl.c | 3 | ||||
-rw-r--r-- | gettext-tools/windows/gettextlib.def | 1 |
13 files changed, 221 insertions, 4 deletions
diff --git a/gettext-tools/ChangeLog b/gettext-tools/ChangeLog index c1aac57..9ed08e3 100644 --- a/gettext-tools/ChangeLog +++ b/gettext-tools/ChangeLog @@ -1,3 +1,7 @@ +2003-09-14 Bruno Haible <bruno@clisp.org> + + * windows/gettextlib.def: Export fwriteerror. + 2003-09-13 Bruno Haible <bruno@clisp.org> * windows/gettextlib.def: Export close_stdout. diff --git a/gettext-tools/lib/ChangeLog b/gettext-tools/lib/ChangeLog index 5948692..3a70d78 100644 --- a/gettext-tools/lib/ChangeLog +++ b/gettext-tools/lib/ChangeLog @@ -1,3 +1,14 @@ +2003-09-14 Bruno Haible <bruno@clisp.org> + + * fwriteerror.h: New file. + * fwriteerror.c: New file. + * Makefile.am (libgettextlib_la_SOURCES): Add fwriteerror.h, + fwriteerror.c. + * Makefile.msvc (OBJECTS): Add fwriteerror.obj. + (fwriteerror.obj): New rule. + * Makefile.vms (OBJECTS): Add fwriteerror.obj. + (fwriteerror.obj): New rule. + 2003-09-13 Bruno Haible <bruno@clisp.org> * closeout.h: New file, from gnulib with modifications. diff --git a/gettext-tools/lib/Makefile.am b/gettext-tools/lib/Makefile.am index 3e437bb..b6addbb 100644 --- a/gettext-tools/lib/Makefile.am +++ b/gettext-tools/lib/Makefile.am @@ -46,6 +46,7 @@ libgettextlib_la_SOURCES = \ findprog.h findprog.c \ fstrcmp.h fstrcmp.c \ full-write.h full-write.c \ + fwriteerror.h fwriteerror.c \ gcd.h gcd.c \ getopt.h getopt.c getopt1.c \ hash.h hash.c \ diff --git a/gettext-tools/lib/Makefile.msvc b/gettext-tools/lib/Makefile.msvc index f90705c..b099e97 100644 --- a/gettext-tools/lib/Makefile.msvc +++ b/gettext-tools/lib/Makefile.msvc @@ -93,6 +93,7 @@ OBJECTS = \ findprog.obj \ fstrcmp.obj \ full-write.obj \ + fwriteerror.obj \ gcd.obj \ getopt.obj getopt1.obj \ hash.obj \ @@ -171,6 +172,9 @@ fstrcmp.obj : fstrcmp.c full-write.obj : full-write.c $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c full-write.c +fwriteerror.obj : fwriteerror.c + $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c fwriteerror.c + gcd.obj : gcd.c $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c gcd.c diff --git a/gettext-tools/lib/Makefile.vms b/gettext-tools/lib/Makefile.vms index bd70f25..e199087 100644 --- a/gettext-tools/lib/Makefile.vms +++ b/gettext-tools/lib/Makefile.vms @@ -51,6 +51,7 @@ OBJECTS = \ findprog.obj, \ fstrcmp.obj, \ full-write.obj, \ + fwriteerror.obj, \ gcd.obj, \ getopt.obj, getopt1.obj, \ hash.obj, \ @@ -132,6 +133,9 @@ fstrcmp.obj : fstrcmp.c full-write.obj : full-write.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) full-write.c +fwriteerror.obj : fwriteerror.c + $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) fwriteerror.c + gcd.obj : gcd.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) gcd.c diff --git a/gettext-tools/lib/fwriteerror.c b/gettext-tools/lib/fwriteerror.c new file mode 100644 index 0000000..364db86 --- /dev/null +++ b/gettext-tools/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 diff --git a/gettext-tools/lib/fwriteerror.h b/gettext-tools/lib/fwriteerror.h new file mode 100644 index 0000000..82cf5f1 --- /dev/null +++ b/gettext-tools/lib/fwriteerror.h @@ -0,0 +1,51 @@ +/* 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. */ + +/* There are two approaches for detecting a write error on a stream opened + for writing: + + (a) Test the return value of every fwrite() or fprintf() call, and react + immediately. + (b) Just before fclose(), test the error indicator in the stream and + the return value of the final fflush() or fclose() call. + + The benefit of (a) is that non file related errors (such that ENOMEM during + fprintf) and temporary error conditions can be diagnosed accurately. + + A theoretical benefit of (a) is also that, on POSIX systems, in the case of + an ENOSPC error, errno is set and can be used by error() to provide a more + accurate error message. But in practice, this benefit is not big because + users can easily figure out by themselves why a file cannot be written to, + and furthermore the function fwriteerror() can provide errno as well. + + The big drawback of (a) is extensive error checking code: Every function + which does stream output must return an error indicator. + + This file provides support for (b). */ + +#include <stdio.h> + +/* Write out the not yet written buffered contents of the stream FP, and then + test whether some error occurred on the stream FP. FP must be a stream + opened for writing. + Return 0 if no error occurred. In this case it can be assumed that + fclose (fp) will succeed. + Return -1 and set errno if there was an error. The errno value will be 0 + if the cause of the error cannot be determined. + */ +extern int fwriteerror (FILE *fp); diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index daa38c8..8fa8b84 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,18 @@ +2003-09-14 Bruno Haible <bruno@clisp.org> + + * write-mo.c: Include fwriterror.h. + (msgdomain_write_mo): Use fwriteerror, to get right errno value in + error message about write error. + * write-po.c: Include fwriterror.h. + (msgdomain_list_print): Use fwriteerror, to get right errno value in + error message about write error. + * write-java.c: Include fwriterror.h. + (msgdomain_write_java): Use fwriteerror, to get right errno value in + error message about write error. + * write-tcl.c: Include fwriterror.h. + (msgdomain_write_tcl): Use fwriteerror, to get right errno value in + error message about write error. + 2003-09-18 Bruno Haible <bruno@clisp.org> * xgettext.c (from_current_source_encoding): Use multiline_error, diff --git a/gettext-tools/src/write-java.c b/gettext-tools/src/write-java.c index da8c76d..d8b200b 100644 --- a/gettext-tools/src/write-java.c +++ b/gettext-tools/src/write-java.c @@ -74,6 +74,7 @@ #include "po-charset.h" #include "xmalloc.h" #include "pathname.h" +#include "fwriteerror.h" #include "tmpdir.h" #include "utf8-ucs4.h" #include "gettext.h" @@ -1151,7 +1152,7 @@ msgdomain_write_java (message_list_ty *mlp, const char *canon_encoding, write_java_code (java_file, class_name, mlp, assume_java2); - if (fflush (java_file) || ferror (java_file)) + if (fwriteerror (java_file)) { error (0, errno, _("error while writing \"%s\" file"), java_file_name); fclose (java_file); diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c index 53e6901..adba883 100644 --- a/gettext-tools/src/write-mo.c +++ b/gettext-tools/src/write-mo.c @@ -44,6 +44,7 @@ #include "format.h" #include "xmalloc.h" #include "binary-io.h" +#include "fwriteerror.h" #include "exit.h" #include "gettext.h" @@ -701,7 +702,7 @@ msgdomain_write_mo (message_list_ty *mlp, write_table (output_file, mlp); /* Make sure nothing went wrong. */ - if (fflush (output_file) || ferror (output_file)) + if (fwriteerror (output_file)) error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), file_name); diff --git a/gettext-tools/src/write-po.c b/gettext-tools/src/write-po.c index 985179e..4befb10 100644 --- a/gettext-tools/src/write-po.c +++ b/gettext-tools/src/write-po.c @@ -42,6 +42,7 @@ #include "write-properties.h" #include "xmalloc.h" #include "strstr.h" +#include "fwriteerror.h" #include "exit.h" #include "error-progname.h" #include "error.h" @@ -1091,7 +1092,7 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename, msgdomain_list_print_po (mdlp, fp, debug); /* Make sure nothing went wrong. */ - if (fflush (fp) || ferror (fp)) + if (fwriteerror (fp)) error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), filename); diff --git a/gettext-tools/src/write-tcl.c b/gettext-tools/src/write-tcl.c index b99a103..4b0146b 100644 --- a/gettext-tools/src/write-tcl.c +++ b/gettext-tools/src/write-tcl.c @@ -36,6 +36,7 @@ #include "po-charset.h" #include "xmalloc.h" #include "pathname.h" +#include "fwriteerror.h" #include "exit.h" #include "utf8-ucs4.h" #include "gettext.h" @@ -197,7 +198,7 @@ but the Tcl message catalog format doesn't support plural handling\n"))); write_msg (output_file, mlp, frobbed_locale_name); /* Make sure nothing went wrong. */ - if (fflush (output_file) || ferror (output_file)) + if (fwriteerror (output_file)) error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), file_name); diff --git a/gettext-tools/windows/gettextlib.def b/gettext-tools/windows/gettextlib.def index 96c6653..d28f12e 100644 --- a/gettext-tools/windows/gettextlib.def +++ b/gettext-tools/windows/gettextlib.def @@ -45,6 +45,7 @@ find_entry find_in_path fstrcmp full_write +fwriteerror gcd getopt_long get_version |