• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/libgettextpo/
1/* Detect write error on a stream.
2   Copyright (C) 2003-2006 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include "fwriteerror.h"
22
23#include <errno.h>
24#include <stdbool.h>
25
26static int
27do_fwriteerror (FILE *fp, bool ignore_ebadf)
28{
29  /* State to allow multiple calls to fwriteerror (stdout).  */
30  static bool stdout_closed = false;
31
32  if (fp == stdout)
33    {
34      if (stdout_closed)
35	return 0;
36
37      /* If we are closing stdout, don't attempt to do it later again.  */
38      stdout_closed = true;
39    }
40
41  /* Need to
42     1. test the error indicator of the stream,
43     2. flush the buffers both in userland and in the kernel, through fclose,
44        testing for error again.  */
45
46  /* Clear errno, so that on non-POSIX systems the caller doesn't see a
47     wrong value of errno when we return -1.  */
48  errno = 0;
49
50  if (ferror (fp))
51    {
52      if (fflush (fp))
53	goto close_preserving_errno; /* errno is set here */
54      /* The stream had an error earlier, but its errno was lost.  If the
55	 error was not temporary, we can get the same errno by writing and
56	 flushing one more byte.  We can do so because at this point the
57	 stream's contents is garbage anyway.  */
58      if (fputc ('\0', fp) == EOF)
59	goto close_preserving_errno; /* errno is set here */
60      if (fflush (fp))
61	goto close_preserving_errno; /* errno is set here */
62      /* Give up on errno.  */
63      errno = 0;
64      goto close_preserving_errno;
65    }
66
67  if (ignore_ebadf)
68    {
69      /* We need an explicit fflush to tell whether some output was already
70	 done on FP.  */
71      if (fflush (fp))
72	goto close_preserving_errno; /* errno is set here */
73      if (fclose (fp) && errno != EBADF)
74	return -1; /* errno is set here */
75    }
76  else
77    {
78      if (fclose (fp))
79	return -1; /* errno is set here */
80    }
81
82  return 0;
83
84 close_preserving_errno:
85  /* There's an error.  Nevertheless call fclose(fp), for consistency
86     with the other cases.  */
87  {
88    int saved_errno = errno;
89    fclose (fp);
90    errno = saved_errno;
91    return -1;
92  }
93}
94
95int
96fwriteerror (FILE *fp)
97{
98  return do_fwriteerror (fp, false);
99}
100
101int
102fwriteerror_no_ebadf (FILE *fp)
103{
104  return do_fwriteerror (fp, true);
105}
106
107
108#if TEST
109
110/* Name of a file on which writing fails.  On systems without /dev/full,
111   you can choose a filename on a full filesystem.  */
112#define UNWRITABLE_FILE "/dev/full"
113
114int
115main ()
116{
117  static int sizes[] =
118    {
119       511,  512,  513,
120      1023, 1024, 1025,
121      2047, 2048, 2049,
122      4095, 4096, 4097,
123      8191, 8192, 8193
124    };
125  static char dummy[8193];
126  unsigned int i, j;
127
128  for (i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++)
129    {
130      size_t size = sizes[i];
131
132      for (j = 0; j < 2; j++)
133	{
134	  /* Run a test depending on i and j:
135	     Write size bytes and then calls fflush if j==1.  */
136	  FILE *stream = fopen (UNWRITABLE_FILE, "w");
137
138	  if (stream == NULL)
139	    {
140	      fprintf (stderr, "Test %u:%u: could not open file\n", i, j);
141	      continue;
142	    }
143
144	  fwrite (dummy, 347, 1, stream);
145	  fwrite (dummy, size - 347, 1, stream);
146	  if (j)
147	    fflush (stream);
148
149	  if (fwriteerror (stream) == -1)
150	    {
151	      if (errno != ENOSPC)
152		fprintf (stderr, "Test %u:%u: fwriteerror ok, errno = %d\n",
153			 i, j, errno);
154	    }
155	  else
156	    fprintf (stderr, "Test %u:%u: fwriteerror found no error!\n",
157		     i, j);
158	}
159    }
160
161  return 0;
162}
163
164#endif
165