Mercurial > hg > octave-jordi > gnulib-hg
annotate lib/nonblocking.c @ 14532:0b3f0c54fbc8
nonblocking: provide O_NONBLOCK for mingw
Mingw is the only known platform that lacks O_NONBLOCK (possibly
via the alternate spelling O_NDELAY). But mingw also lacks any
files where open() needs to enforce non-blocking behavior, and
lacks openat(), so it is relatively simple to provide a non-zero
flag. A future patches will make use of O_NONBLOCK for pipe2.
* modules/nonblocking (Depends-on): Add open.
(configure.ac): Set new witness macro.
* m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Provide default for it.
* modules/fcntl-h (Makefile.am): Substitute it.
* lib/fcntl.in.h (O_NONBLOCK): Guarantee non-zero definition when
nonblocking module is in use.
* lib/nonblocking.c: Adjust portability test.
* lib/open.c (open): Don't let native open see gnulib flag.
* tests/test-fcntl-h.c (main): Enhance test.
* tests/test-open.h (test_open): Likewise.
* doc/posix-headers/fcntl.texi (fcntl.h): Document the replacement.
Signed-off-by: Eric Blake <eblake@redhat.com>
author | Eric Blake <eblake@redhat.com> |
---|---|
date | Fri, 08 Apr 2011 10:15:54 -0600 |
parents | 8b5a7d072ac7 |
children | b86e9061a6d0 |
rev | line source |
---|---|
14513 | 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 | |
14516
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
27 # include <sys/ioctl.h> |
14513 | 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); | |
14516
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
39 if (h == INVALID_HANDLE_VALUE) |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
40 { |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
41 errno = EBADF; |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
42 return -1; |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
43 } |
14513 | 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); | |
14516
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
65 if (h == INVALID_HANDLE_VALUE) |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
66 { |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
67 errno = EBADF; |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
68 return -1; |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
69 } |
14513 | 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. */ | |
14516
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
104 if (!value) |
8b5a7d072ac7
nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents:
14513
diff
changeset
|
105 return 0; |
14513 | 106 errno = ENOTSUP; |
107 return -1; | |
108 } | |
109 } | |
110 | |
111 #else | |
112 /* Unix API. */ | |
113 | |
114 # include <fcntl.h> | |
115 | |
14532
0b3f0c54fbc8
nonblocking: provide O_NONBLOCK for mingw
Eric Blake <eblake@redhat.com>
parents:
14516
diff
changeset
|
116 # if GNULIB_defined_O_NONBLOCK |
14513 | 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 |