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