]>
Commit | Line | Data |
---|---|---|
dc6c21da TT |
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 | |
86 | int | |
87 | scanf (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 | |
103 | int | |
104 | fscanf (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 | |
120 | int | |
121 | vscanf (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 | |
130 | int | |
131 | vfscanf (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 | ||
138 | int | |
139 | getchar (void) | |
140 | { | |
141 | return fgetc (stdin); | |
142 | } | |
143 | ||
144 | int | |
145 | fgetc (FILE *stream) | |
146 | #undef fgetc | |
147 | { | |
148 | CALL_WITH_ERRNO_FIX (int, fgetc (stream), ret == EOF) | |
149 | } | |
150 | ||
151 | char * | |
152 | fgets (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 | ||
160 | size_t | |
161 | fread (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 |