nonblocking: fix mingw test failures
[gnulib.git] / lib / nonblocking.c
1 /* Non-blocking I/O for pipe or socket descriptors.
2    Copyright (C) 2011 Free Software Foundation, Inc.
3
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.
8
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.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include "nonblocking.h"
21
22 #include <errno.h>
23
24 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
25 /* Native Woe32 API.  */
26
27 # include <sys/ioctl.h>
28 # include <sys/socket.h>
29 # include <unistd.h>
30
31 /* Get declarations of the Win32 API functions.  */
32 # define WIN32_LEAN_AND_MEAN
33 # include <windows.h>
34
35 int
36 get_nonblocking_flag (int desc)
37 {
38   HANDLE h = (HANDLE) _get_osfhandle (desc);
39   if (h == INVALID_HANDLE_VALUE)
40     {
41       errno = EBADF;
42       return -1;
43     }
44   if (GetFileType (h) == FILE_TYPE_PIPE)
45     {
46       /* h is a pipe or socket.  */
47       DWORD state;
48       if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
49         /* h is a pipe.  */
50         return (state & PIPE_NOWAIT) != 0;
51       else
52         /* h is a socket.  */
53         errno = ENOSYS;
54         return -1;
55     }
56   else
57     /* Win32 does not support non-blocking on regular files.  */
58     return 0;
59 }
60
61 int
62 set_nonblocking_flag (int desc, bool value)
63 {
64   HANDLE h = (HANDLE) _get_osfhandle (desc);
65   if (h == INVALID_HANDLE_VALUE)
66     {
67       errno = EBADF;
68       return -1;
69     }
70   if (GetFileType (h) == FILE_TYPE_PIPE)
71     {
72       /* h is a pipe or socket.  */
73       DWORD state;
74       if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
75         {
76           /* h is a pipe.  */
77           if ((state & PIPE_NOWAIT) != 0)
78             {
79               if (value)
80                 return 0;
81               state &= ~PIPE_NOWAIT;
82             }
83           else
84             {
85               if (!value)
86                 return 0;
87               state |= PIPE_NOWAIT;
88             }
89           if (SetNamedPipeHandleState (h, &state, NULL, NULL))
90             return 0;
91           errno = EINVAL;
92           return -1;
93         }
94       else
95         {
96           /* h is a socket.  */
97           int v = value;
98           return ioctl (desc, FIONBIO, &v);
99         }
100     }
101   else
102     {
103       /* Win32 does not support non-blocking on regular files.  */
104       if (!value)
105         return 0;
106       errno = ENOTSUP;
107       return -1;
108     }
109 }
110
111 #else
112 /* Unix API.  */
113
114 # include <fcntl.h>
115
116 # if !O_NONBLOCK
117 #  error Please port nonblocking to your platform
118 # endif
119
120 /* We don't need the gnulib replacement of fcntl() here.  */
121 # undef fcntl
122
123 int
124 get_nonblocking_flag (int desc)
125 {
126   int fcntl_flags;
127
128   fcntl_flags = fcntl (desc, F_GETFL, 0);
129   if (fcntl_flags < 0)
130     return -1;
131   return (fcntl_flags & O_NONBLOCK) != 0;
132 }
133
134 int
135 set_nonblocking_flag (int desc, bool value)
136 {
137   int fcntl_flags;
138
139   fcntl_flags = fcntl (desc, F_GETFL, 0);
140   if (fcntl_flags < 0)
141     return -1;
142   if (((fcntl_flags & O_NONBLOCK) != 0) == value)
143     return 0;
144   if (value)
145     fcntl_flags |= O_NONBLOCK;
146   else
147     fcntl_flags &= ~O_NONBLOCK;
148   return fcntl (desc, F_SETFL, fcntl_flags);
149 }
150
151 #endif