Annotation of embedaddon/libiconv/srclib/stdio-write.c, revision 1.1.1.3
1.1 misho 1: /* POSIX compatible FILE stream write function.
1.1.1.3 ! misho 2: Copyright (C) 2008-2019 Free Software Foundation, Inc.
1.1 misho 3: Written by Bruno Haible <bruno@clisp.org>, 2008.
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
1.1.1.3 ! misho 16: along with this program. If not, see <https://www.gnu.org/licenses/>. */
1.1 misho 17:
18: #include <config.h>
19:
20: /* Specification. */
21: #include <stdio.h>
22:
1.1.1.2 misho 23: /* Replace these functions only if module 'nonblocking' or module 'sigpipe' is
24: requested. */
25: #if GNULIB_NONBLOCKING || GNULIB_SIGPIPE
1.1 misho 26:
27: /* On native Windows platforms, SIGPIPE does not exist. When write() is
28: called on a pipe with no readers, WriteFile() fails with error
29: GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
30: error EINVAL. This write() function is at the basis of the function
31: which flushes the buffer of a FILE stream. */
32:
1.1.1.3 ! misho 33: # if defined _WIN32 && ! defined __CYGWIN__
1.1 misho 34:
35: # include <errno.h>
36: # include <signal.h>
37: # include <io.h>
38:
39: # define WIN32_LEAN_AND_MEAN /* avoid including junk */
40: # include <windows.h>
41:
1.1.1.3 ! misho 42: # if GNULIB_MSVC_NOTHROW
! 43: # include "msvc-nothrow.h"
! 44: # else
! 45: # include <io.h>
! 46: # endif
! 47:
1.1.1.2 misho 48: # if GNULIB_NONBLOCKING
49: # define CLEAR_ERRNO \
50: errno = 0;
51: # define HANDLE_ENOSPC \
52: if (errno == ENOSPC && ferror (stream)) \
53: { \
54: int fd = fileno (stream); \
55: if (fd >= 0) \
56: { \
57: HANDLE h = (HANDLE) _get_osfhandle (fd); \
58: if (GetFileType (h) == FILE_TYPE_PIPE) \
59: { \
60: /* h is a pipe or socket. */ \
61: DWORD state; \
62: if (GetNamedPipeHandleState (h, &state, NULL, NULL, \
63: NULL, NULL, 0) \
64: && (state & PIPE_NOWAIT) != 0) \
65: /* h is a pipe in non-blocking mode. \
66: Change errno from ENOSPC to EAGAIN. */ \
67: errno = EAGAIN; \
68: } \
69: } \
70: } \
71: else
72: # else
73: # define CLEAR_ERRNO
74: # define HANDLE_ENOSPC
75: # endif
76:
77: # if GNULIB_SIGPIPE
78: # define CLEAR_LastError \
79: SetLastError (0);
80: # define HANDLE_ERROR_NO_DATA \
81: if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \
82: { \
83: int fd = fileno (stream); \
84: if (fd >= 0 \
85: && GetFileType ((HANDLE) _get_osfhandle (fd)) \
86: == FILE_TYPE_PIPE) \
87: { \
88: /* Try to raise signal SIGPIPE. */ \
89: raise (SIGPIPE); \
90: /* If it is currently blocked or ignored, change errno from \
91: EINVAL to EPIPE. */ \
92: errno = EPIPE; \
93: } \
94: } \
95: else
96: # else
97: # define CLEAR_LastError
98: # define HANDLE_ERROR_NO_DATA
99: # endif
100:
1.1 misho 101: # define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \
1.1.1.2 misho 102: if (ferror (stream)) \
103: return (EXPRESSION); \
104: else \
105: { \
106: RETTYPE ret; \
107: CLEAR_ERRNO \
108: CLEAR_LastError \
109: ret = (EXPRESSION); \
110: if (FAILED) \
111: { \
112: HANDLE_ENOSPC \
113: HANDLE_ERROR_NO_DATA \
114: ; \
115: } \
116: return ret; \
1.1 misho 117: }
118:
119: # if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */
120: int
121: printf (const char *format, ...)
122: {
123: int retval;
124: va_list args;
125:
126: va_start (args, format);
127: retval = vfprintf (stdout, format, args);
128: va_end (args);
129:
130: return retval;
131: }
132: # endif
133:
134: # if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */
135: int
136: fprintf (FILE *stream, const char *format, ...)
137: {
138: int retval;
139: va_list args;
140:
141: va_start (args, format);
142: retval = vfprintf (stream, format, args);
143: va_end (args);
144:
145: return retval;
146: }
147: # endif
148:
1.1.1.2 misho 149: # if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */
1.1 misho 150: int
151: vprintf (const char *format, va_list args)
152: {
153: return vfprintf (stdout, format, args);
154: }
155: # endif
156:
1.1.1.2 misho 157: # if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */
1.1 misho 158: int
159: vfprintf (FILE *stream, const char *format, va_list args)
160: #undef vfprintf
161: {
162: CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF)
163: }
164: # endif
165:
166: int
167: putchar (int c)
168: {
169: return fputc (c, stdout);
170: }
171:
172: int
173: fputc (int c, FILE *stream)
174: #undef fputc
175: {
176: CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF)
177: }
178:
179: int
180: fputs (const char *string, FILE *stream)
181: #undef fputs
182: {
183: CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF)
184: }
185:
186: int
187: puts (const char *string)
188: #undef puts
189: {
190: FILE *stream = stdout;
191: CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF)
192: }
193:
194: size_t
195: fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
196: #undef fwrite
197: {
198: CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n)
199: }
200:
201: # endif
202: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>