version 1.1, 2012/02/21 22:57:48
|
version 1.1.1.3, 2021/03/17 13:38:46
|
Line 1
|
Line 1
|
/* POSIX compatible FILE stream write function. |
/* POSIX compatible FILE stream write function. |
Copyright (C) 2008 Free Software Foundation, Inc. | Copyright (C) 2008-2019 Free Software Foundation, Inc. |
Written by Bruno Haible <bruno@clisp.org>, 2008. |
Written by Bruno Haible <bruno@clisp.org>, 2008. |
|
|
This program is free software: you can redistribute it and/or modify |
This program is free software: you can redistribute it and/or modify |
Line 13
|
Line 13
|
GNU General Public License for more details. |
GNU General Public License for more details. |
|
|
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
|
|
#include <config.h> |
#include <config.h> |
|
|
/* Specification. */ |
/* Specification. */ |
#include <stdio.h> |
#include <stdio.h> |
|
|
/* Replace these functions only if module 'sigpipe' is requested. */ | /* Replace these functions only if module 'nonblocking' or module 'sigpipe' is |
#if GNULIB_SIGPIPE | requested. */ |
| #if GNULIB_NONBLOCKING || GNULIB_SIGPIPE |
|
|
/* On native Windows platforms, SIGPIPE does not exist. When write() is |
/* On native Windows platforms, SIGPIPE does not exist. When write() is |
called on a pipe with no readers, WriteFile() fails with error |
called on a pipe with no readers, WriteFile() fails with error |
Line 29
|
Line 30
|
error EINVAL. This write() function is at the basis of the function |
error EINVAL. This write() function is at the basis of the function |
which flushes the buffer of a FILE stream. */ |
which flushes the buffer of a FILE stream. */ |
|
|
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | # if defined _WIN32 && ! defined __CYGWIN__ |
|
|
# include <errno.h> |
# include <errno.h> |
# include <signal.h> |
# include <signal.h> |
Line 38
|
Line 39
|
# define WIN32_LEAN_AND_MEAN /* avoid including junk */ |
# define WIN32_LEAN_AND_MEAN /* avoid including junk */ |
# include <windows.h> |
# include <windows.h> |
|
|
|
# if GNULIB_MSVC_NOTHROW |
|
# include "msvc-nothrow.h" |
|
# else |
|
# include <io.h> |
|
# endif |
|
|
|
# if GNULIB_NONBLOCKING |
|
# define CLEAR_ERRNO \ |
|
errno = 0; |
|
# define HANDLE_ENOSPC \ |
|
if (errno == ENOSPC && ferror (stream)) \ |
|
{ \ |
|
int fd = fileno (stream); \ |
|
if (fd >= 0) \ |
|
{ \ |
|
HANDLE h = (HANDLE) _get_osfhandle (fd); \ |
|
if (GetFileType (h) == FILE_TYPE_PIPE) \ |
|
{ \ |
|
/* h is a pipe or socket. */ \ |
|
DWORD state; \ |
|
if (GetNamedPipeHandleState (h, &state, NULL, NULL, \ |
|
NULL, NULL, 0) \ |
|
&& (state & PIPE_NOWAIT) != 0) \ |
|
/* h is a pipe in non-blocking mode. \ |
|
Change errno from ENOSPC to EAGAIN. */ \ |
|
errno = EAGAIN; \ |
|
} \ |
|
} \ |
|
} \ |
|
else |
|
# else |
|
# define CLEAR_ERRNO |
|
# define HANDLE_ENOSPC |
|
# endif |
|
|
|
# if GNULIB_SIGPIPE |
|
# define CLEAR_LastError \ |
|
SetLastError (0); |
|
# define HANDLE_ERROR_NO_DATA \ |
|
if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \ |
|
{ \ |
|
int fd = fileno (stream); \ |
|
if (fd >= 0 \ |
|
&& GetFileType ((HANDLE) _get_osfhandle (fd)) \ |
|
== FILE_TYPE_PIPE) \ |
|
{ \ |
|
/* Try to raise signal SIGPIPE. */ \ |
|
raise (SIGPIPE); \ |
|
/* If it is currently blocked or ignored, change errno from \ |
|
EINVAL to EPIPE. */ \ |
|
errno = EPIPE; \ |
|
} \ |
|
} \ |
|
else |
|
# else |
|
# define CLEAR_LastError |
|
# define HANDLE_ERROR_NO_DATA |
|
# endif |
|
|
# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ |
# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ |
if (ferror (stream)) \ | if (ferror (stream)) \ |
return (EXPRESSION); \ | return (EXPRESSION); \ |
else \ | else \ |
{ \ | { \ |
RETTYPE ret; \ | RETTYPE ret; \ |
SetLastError (0); \ | CLEAR_ERRNO \ |
ret = (EXPRESSION); \ | CLEAR_LastError \ |
if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \ | ret = (EXPRESSION); \ |
{ \ | if (FAILED) \ |
int fd = fileno (stream); \ | { \ |
if (fd >= 0 \ | HANDLE_ENOSPC \ |
&& GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\ | HANDLE_ERROR_NO_DATA \ |
{ \ | ; \ |
/* Try to raise signal SIGPIPE. */ \ | } \ |
raise (SIGPIPE); \ | return ret; \ |
/* If it is currently blocked or ignored, change errno from \ | |
EINVAL to EPIPE. */ \ | |
errno = EPIPE; \ | |
} \ | |
} \ | |
return ret; \ | |
} |
} |
|
|
# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ |
# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ |
Line 92 fprintf (FILE *stream, const char *format, ...)
|
Line 146 fprintf (FILE *stream, const char *format, ...)
|
} |
} |
# endif |
# endif |
|
|
# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vprintf.c */ | # if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ |
int |
int |
vprintf (const char *format, va_list args) |
vprintf (const char *format, va_list args) |
{ |
{ |
Line 100 vprintf (const char *format, va_list args)
|
Line 154 vprintf (const char *format, va_list args)
|
} |
} |
# endif |
# endif |
|
|
# if !REPLACE_VPRINTF_POSIX /* avoid collision with vfprintf.c */ | # if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ |
int |
int |
vfprintf (FILE *stream, const char *format, va_list args) |
vfprintf (FILE *stream, const char *format, va_list args) |
#undef vfprintf |
#undef vfprintf |