stdio-write.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /* POSIX compatible FILE stream write function.
  2. Copyright (C) 2008-2023 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2008.
  4. This file is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. This file is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <stdio.h>
  17. /* Replace these functions only if module 'nonblocking' or module 'sigpipe' is
  18. requested. */
  19. #if GNULIB_NONBLOCKING || GNULIB_SIGPIPE
  20. /* On native Windows platforms, SIGPIPE does not exist. When write() is
  21. called on a pipe with no readers, WriteFile() fails with error
  22. GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
  23. error EINVAL. This write() function is at the basis of the function
  24. which flushes the buffer of a FILE stream. */
  25. # if defined _WIN32 && ! defined __CYGWIN__
  26. # include <errno.h>
  27. # include <signal.h>
  28. # include <io.h>
  29. # define WIN32_LEAN_AND_MEAN /* avoid including junk */
  30. # include <windows.h>
  31. # if GNULIB_MSVC_NOTHROW
  32. # include "msvc-nothrow.h"
  33. # else
  34. # include <io.h>
  35. # endif
  36. /* Don't assume that UNICODE is not defined. */
  37. # undef GetNamedPipeHandleState
  38. # define GetNamedPipeHandleState GetNamedPipeHandleStateA
  39. # if GNULIB_NONBLOCKING
  40. # define CLEAR_ERRNO \
  41. errno = 0;
  42. # define HANDLE_ENOSPC \
  43. if (errno == ENOSPC && ferror (stream)) \
  44. { \
  45. int fd = fileno (stream); \
  46. if (fd >= 0) \
  47. { \
  48. HANDLE h = (HANDLE) _get_osfhandle (fd); \
  49. if (GetFileType (h) == FILE_TYPE_PIPE) \
  50. { \
  51. /* h is a pipe or socket. */ \
  52. DWORD state; \
  53. if (GetNamedPipeHandleState (h, &state, NULL, NULL, \
  54. NULL, NULL, 0) \
  55. && (state & PIPE_NOWAIT) != 0) \
  56. /* h is a pipe in non-blocking mode. \
  57. Change errno from ENOSPC to EAGAIN. */ \
  58. errno = EAGAIN; \
  59. } \
  60. } \
  61. } \
  62. else
  63. # else
  64. # define CLEAR_ERRNO
  65. # define HANDLE_ENOSPC
  66. # endif
  67. # if GNULIB_SIGPIPE
  68. # define CLEAR_LastError \
  69. SetLastError (0);
  70. # define HANDLE_ERROR_NO_DATA \
  71. if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \
  72. { \
  73. int fd = fileno (stream); \
  74. if (fd >= 0 \
  75. && GetFileType ((HANDLE) _get_osfhandle (fd)) \
  76. == FILE_TYPE_PIPE) \
  77. { \
  78. /* Try to raise signal SIGPIPE. */ \
  79. raise (SIGPIPE); \
  80. /* If it is currently blocked or ignored, change errno from \
  81. EINVAL to EPIPE. */ \
  82. errno = EPIPE; \
  83. } \
  84. } \
  85. else
  86. # else
  87. # define CLEAR_LastError
  88. # define HANDLE_ERROR_NO_DATA
  89. # endif
  90. # define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \
  91. if (ferror (stream)) \
  92. return (EXPRESSION); \
  93. else \
  94. { \
  95. RETTYPE ret; \
  96. CLEAR_ERRNO \
  97. CLEAR_LastError \
  98. ret = (EXPRESSION); \
  99. if (FAILED) \
  100. { \
  101. HANDLE_ENOSPC \
  102. HANDLE_ERROR_NO_DATA \
  103. ; \
  104. } \
  105. return ret; \
  106. }
  107. # if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */
  108. int
  109. printf (const char *format, ...)
  110. {
  111. int retval;
  112. va_list args;
  113. va_start (args, format);
  114. retval = vfprintf (stdout, format, args);
  115. va_end (args);
  116. return retval;
  117. }
  118. # endif
  119. # if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */
  120. int
  121. fprintf (FILE *stream, const char *format, ...)
  122. {
  123. int retval;
  124. va_list args;
  125. va_start (args, format);
  126. retval = vfprintf (stream, format, args);
  127. va_end (args);
  128. return retval;
  129. }
  130. # endif
  131. # if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */
  132. int
  133. vprintf (const char *format, va_list args)
  134. {
  135. return vfprintf (stdout, format, args);
  136. }
  137. # endif
  138. # if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */
  139. int
  140. vfprintf (FILE *stream, const char *format, va_list args)
  141. #undef vfprintf
  142. {
  143. CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF)
  144. }
  145. # endif
  146. int
  147. putchar (int c)
  148. {
  149. return fputc (c, stdout);
  150. }
  151. int
  152. fputc (int c, FILE *stream)
  153. #undef fputc
  154. {
  155. CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF)
  156. }
  157. int
  158. fputs (const char *string, FILE *stream)
  159. #undef fputs
  160. {
  161. CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF)
  162. }
  163. int
  164. puts (const char *string)
  165. #undef puts
  166. {
  167. FILE *stream = stdout;
  168. CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF)
  169. }
  170. size_t
  171. fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
  172. #undef fwrite
  173. {
  174. CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n)
  175. }
  176. # endif
  177. #endif