stdio-read.c revision 1.1.1.1
1/* POSIX compatible FILE stream read function.
2   Copyright (C) 2008-2022 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2011.
4
5   This file is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License as
7   published by the Free Software Foundation; either version 2.1 of the
8   License, or (at your option) any later version.
9
10   This file 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 Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program.  If not, see <https://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' is requested.  */
24#if GNULIB_NONBLOCKING
25
26/* On native Windows platforms, when read() is called on a non-blocking pipe
27   with an empty buffer, ReadFile() fails with error GetLastError() =
28   ERROR_NO_DATA, and read() in consequence fails with error EINVAL.  This
29   read() function is at the basis of the function which fills the buffer of
30   a FILE stream.  */
31
32# if defined _WIN32 && ! defined __CYGWIN__
33
34#  include <errno.h>
35#  include <io.h>
36
37#  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
38#  include <windows.h>
39
40#  if GNULIB_MSVC_NOTHROW
41#   include "msvc-nothrow.h"
42#  else
43#   include <io.h>
44#  endif
45
46/* Don't assume that UNICODE is not defined.  */
47#  undef GetNamedPipeHandleState
48#  define GetNamedPipeHandleState GetNamedPipeHandleStateA
49
50#  define CALL_WITH_ERRNO_FIX(RETTYPE, EXPRESSION, FAILED) \
51  if (ferror (stream))                                                        \
52    return (EXPRESSION);                                                      \
53  else                                                                        \
54    {                                                                         \
55      RETTYPE ret;                                                            \
56      SetLastError (0);                                                       \
57      ret = (EXPRESSION);                                                     \
58      if (FAILED)                                                             \
59        {                                                                     \
60          if (GetLastError () == ERROR_NO_DATA && ferror (stream))            \
61            {                                                                 \
62              int fd = fileno (stream);                                       \
63              if (fd >= 0)                                                    \
64                {                                                             \
65                  HANDLE h = (HANDLE) _get_osfhandle (fd);                    \
66                  if (GetFileType (h) == FILE_TYPE_PIPE)                      \
67                    {                                                         \
68                      /* h is a pipe or socket.  */                           \
69                      DWORD state;                                            \
70                      if (GetNamedPipeHandleState (h, &state, NULL, NULL,     \
71                                                   NULL, NULL, 0)             \
72                          && (state & PIPE_NOWAIT) != 0)                      \
73                        /* h is a pipe in non-blocking mode.                  \
74                           Change errno from EINVAL to EAGAIN.  */            \
75                        errno = EAGAIN;                                       \
76                    }                                                         \
77                }                                                             \
78            }                                                                 \
79        }                                                                     \
80      return ret;                                                             \
81    }
82
83/* Enable this function definition only if gnulib's <stdio.h> has prepared it.
84   Otherwise we get a function definition conflict with mingw64's <stdio.h>.  */
85#  if GNULIB_SCANF
86int
87scanf (const char *format, ...)
88{
89  int retval;
90  va_list args;
91
92  va_start (args, format);
93  retval = vfscanf (stdin, format, args);
94  va_end (args);
95
96  return retval;
97}
98#  endif
99
100/* Enable this function definition only if gnulib's <stdio.h> has prepared it.
101   Otherwise we get a function definition conflict with mingw64's <stdio.h>.  */
102#  if GNULIB_FSCANF
103int
104fscanf (FILE *stream, const char *format, ...)
105{
106  int retval;
107  va_list args;
108
109  va_start (args, format);
110  retval = vfscanf (stream, format, args);
111  va_end (args);
112
113  return retval;
114}
115#  endif
116
117/* Enable this function definition only if gnulib's <stdio.h> has prepared it.
118   Otherwise we get a function definition conflict with mingw64's <stdio.h>.  */
119#  if GNULIB_VSCANF
120int
121vscanf (const char *format, va_list args)
122{
123  return vfscanf (stdin, format, args);
124}
125#  endif
126
127/* Enable this function definition only if gnulib's <stdio.h> has prepared it.
128   Otherwise we get a function definition conflict with mingw64's <stdio.h>.  */
129#  if GNULIB_VFSCANF
130int
131vfscanf (FILE *stream, const char *format, va_list args)
132#undef vfscanf
133{
134  CALL_WITH_ERRNO_FIX (int, vfscanf (stream, format, args), ret == EOF)
135}
136#  endif
137
138int
139getchar (void)
140{
141  return fgetc (stdin);
142}
143
144int
145fgetc (FILE *stream)
146#undef fgetc
147{
148  CALL_WITH_ERRNO_FIX (int, fgetc (stream), ret == EOF)
149}
150
151char *
152fgets (char *s, int n, FILE *stream)
153#undef fgets
154{
155  CALL_WITH_ERRNO_FIX (char *, fgets (s, n, stream), ret == NULL)
156}
157
158/* We intentionally don't bother to fix gets.  */
159
160size_t
161fread (void *ptr, size_t s, size_t n, FILE *stream)
162#undef fread
163{
164  CALL_WITH_ERRNO_FIX (size_t, fread (ptr, s, n, stream), ret < n)
165}
166
167# endif
168#endif
169