mbsnrtowcs: Work around Solaris 11.4 bug.
[gnulib.git] / lib / nonblocking.c
bloba325fadcc614dfc7d51ab15feece3b433d34a121
1 /* Non-blocking I/O for pipe or socket descriptors.
2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #include <config.h>
19 /* Specification. */
20 #include "nonblocking.h"
22 #include <errno.h>
24 #if defined _WIN32 && ! defined __CYGWIN__
25 /* Native Windows API. */
27 # include <sys/ioctl.h>
28 # include <sys/socket.h>
29 # include <unistd.h>
31 /* Get declarations of the native Windows API functions. */
32 # define WIN32_LEAN_AND_MEAN
33 # include <windows.h>
35 # if GNULIB_MSVC_NOTHROW
36 # include "msvc-nothrow.h"
37 # else
38 # include <io.h>
39 # endif
41 int
42 get_nonblocking_flag (int desc)
44 HANDLE h = (HANDLE) _get_osfhandle (desc);
45 if (h == INVALID_HANDLE_VALUE)
47 errno = EBADF;
48 return -1;
50 if (GetFileType (h) == FILE_TYPE_PIPE)
52 /* h is a pipe or socket. */
53 DWORD state;
54 if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
55 /* h is a pipe. */
56 return (state & PIPE_NOWAIT) != 0;
57 else
58 /* h is a socket. */
59 errno = ENOSYS;
60 return -1;
62 else
63 /* The native Windows API does not support non-blocking on regular
64 files. */
65 return 0;
68 int
69 set_nonblocking_flag (int desc, bool value)
71 HANDLE h = (HANDLE) _get_osfhandle (desc);
72 if (h == INVALID_HANDLE_VALUE)
74 errno = EBADF;
75 return -1;
77 if (GetFileType (h) == FILE_TYPE_PIPE)
79 /* h is a pipe or socket. */
80 DWORD state;
81 if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
83 /* h is a pipe. */
84 if ((state & PIPE_NOWAIT) != 0)
86 if (value)
87 return 0;
88 state &= ~PIPE_NOWAIT;
90 else
92 if (!value)
93 return 0;
94 state |= PIPE_NOWAIT;
96 if (SetNamedPipeHandleState (h, &state, NULL, NULL))
97 return 0;
98 errno = EINVAL;
99 return -1;
101 else
103 /* h is a socket. */
104 int v = value;
105 return ioctl (desc, FIONBIO, &v);
108 else
110 /* The native Windows API does not support non-blocking on regular
111 files. */
112 if (!value)
113 return 0;
114 errno = ENOTSUP;
115 return -1;
119 #else
120 /* Unix API. */
122 # include <fcntl.h>
124 # if GNULIB_defined_O_NONBLOCK
125 # error Please port nonblocking to your platform
126 # endif
128 /* We don't need the gnulib replacement of fcntl() here. */
129 # undef fcntl
132 get_nonblocking_flag (int desc)
134 int fcntl_flags;
136 fcntl_flags = fcntl (desc, F_GETFL, 0);
137 if (fcntl_flags < 0)
138 return -1;
139 return (fcntl_flags & O_NONBLOCK) != 0;
143 set_nonblocking_flag (int desc, bool value)
145 int fcntl_flags;
147 fcntl_flags = fcntl (desc, F_GETFL, 0);
148 if (fcntl_flags < 0)
149 return -1;
150 if (((fcntl_flags & O_NONBLOCK) != 0) == value)
151 return 0;
152 if (value)
153 fcntl_flags |= O_NONBLOCK;
154 else
155 fcntl_flags &= ~O_NONBLOCK;
156 return fcntl (desc, F_SETFL, fcntl_flags);
159 #endif