| /* POSIX compatible FILE stream read function. |
| Copyright (C) 2008-2022 Free Software Foundation, Inc. |
| Written by Bruno Haible <bruno@clisp.org>, 2011. |
| |
| This file is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Lesser General Public License as |
| published by the Free Software Foundation; either version 2.1 of the |
| License, or (at your option) any later version. |
| |
| This file is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public License |
| along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
| |
| #include <config.h> |
| |
| /* Specification. */ |
| #include <stdio.h> |
| |
| /* Replace these functions only if module 'nonblocking' is requested. */ |
| #if GNULIB_NONBLOCKING |
| |
| /* On native Windows platforms, when read() is called on a non-blocking pipe |
| with an empty buffer, ReadFile() fails with error GetLastError() = |
| ERROR_NO_DATA, and read() in consequence fails with error EINVAL. This |
| read() function is at the basis of the function which fills the buffer of |
| a FILE stream. */ |
| |
| # if defined _WIN32 && ! defined __CYGWIN__ |
| |
| # include <errno.h> |
| # include <io.h> |
| |
| # define WIN32_LEAN_AND_MEAN /* avoid including junk */ |
| # include <windows.h> |
| |
| # if GNULIB_MSVC_NOTHROW |
| # include "msvc-nothrow.h" |
| # else |
| # include <io.h> |
| # endif |
| |
| /* Don't assume that UNICODE is not defined. */ |
| # undef GetNamedPipeHandleState |
| # define GetNamedPipeHandleState GetNamedPipeHandleStateA |
| |
| # define CALL_WITH_ERRNO_FIX(RETTYPE, EXPRESSION, FAILED) \ |
| if (ferror (stream)) \ |
| return (EXPRESSION); \ |
| else \ |
| { \ |
| RETTYPE ret; \ |
| SetLastError (0); \ |
| ret = (EXPRESSION); \ |
| if (FAILED) \ |
| { \ |
| if (GetLastError () == ERROR_NO_DATA && 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 EINVAL to EAGAIN. */ \ |
| errno = EAGAIN; \ |
| } \ |
| } \ |
| } \ |
| } \ |
| return ret; \ |
| } |
| |
| /* Enable this function definition only if gnulib's <stdio.h> has prepared it. |
| Otherwise we get a function definition conflict with mingw64's <stdio.h>. */ |
| # if GNULIB_SCANF |
| int |
| scanf (const char *format, ...) |
| { |
| int retval; |
| va_list args; |
| |
| va_start (args, format); |
| retval = vfscanf (stdin, format, args); |
| va_end (args); |
| |
| return retval; |
| } |
| # endif |
| |
| /* Enable this function definition only if gnulib's <stdio.h> has prepared it. |
| Otherwise we get a function definition conflict with mingw64's <stdio.h>. */ |
| # if GNULIB_FSCANF |
| int |
| fscanf (FILE *stream, const char *format, ...) |
| { |
| int retval; |
| va_list args; |
| |
| va_start (args, format); |
| retval = vfscanf (stream, format, args); |
| va_end (args); |
| |
| return retval; |
| } |
| # endif |
| |
| /* Enable this function definition only if gnulib's <stdio.h> has prepared it. |
| Otherwise we get a function definition conflict with mingw64's <stdio.h>. */ |
| # if GNULIB_VSCANF |
| int |
| vscanf (const char *format, va_list args) |
| { |
| return vfscanf (stdin, format, args); |
| } |
| # endif |
| |
| /* Enable this function definition only if gnulib's <stdio.h> has prepared it. |
| Otherwise we get a function definition conflict with mingw64's <stdio.h>. */ |
| # if GNULIB_VFSCANF |
| int |
| vfscanf (FILE *stream, const char *format, va_list args) |
| #undef vfscanf |
| { |
| CALL_WITH_ERRNO_FIX (int, vfscanf (stream, format, args), ret == EOF) |
| } |
| # endif |
| |
| int |
| getchar (void) |
| { |
| return fgetc (stdin); |
| } |
| |
| int |
| fgetc (FILE *stream) |
| #undef fgetc |
| { |
| CALL_WITH_ERRNO_FIX (int, fgetc (stream), ret == EOF) |
| } |
| |
| char * |
| fgets (char *s, int n, FILE *stream) |
| #undef fgets |
| { |
| CALL_WITH_ERRNO_FIX (char *, fgets (s, n, stream), ret == NULL) |
| } |
| |
| /* We intentionally don't bother to fix gets. */ |
| |
| size_t |
| fread (void *ptr, size_t s, size_t n, FILE *stream) |
| #undef fread |
| { |
| CALL_WITH_ERRNO_FIX (size_t, fread (ptr, s, n, stream), ret < n) |
| } |
| |
| # endif |
| #endif |