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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14513
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
1 /* Non-blocking I/O for pipe or socket descriptors.
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
2 Copyright (C) 2011 Free Software Foundation, Inc.
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
3
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
4 This program is free software: you can redistribute it and/or modify
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
6 the Free Software Foundation; either version 3 of the License, or
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
7 (at your option) any later version.
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
8
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
12 GNU General Public License for more details.
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
13
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
16
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
17 #include <config.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
18
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
19 /* Specification. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
20 #include "nonblocking.h"
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
21
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
22 #include <errno.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
23
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
24 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
25 /* Native Woe32 API. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
26
14516
8b5a7d072ac7 nonblocking: fix mingw test failures
Eric Blake <eblake@redhat.com>
parents: 14513
diff changeset
27 # include <sys/ioctl.h>
14513
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
28 # include <sys/socket.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
29 # include <unistd.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
30
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
31 /* Get declarations of the Win32 API functions. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
32 # define WIN32_LEAN_AND_MEAN
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
33 # include <windows.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
34
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
35 int
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
36 get_nonblocking_flag (int desc)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
37 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
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
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
44 if (GetFileType (h) == FILE_TYPE_PIPE)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
45 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
46 /* h is a pipe or socket. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
47 DWORD state;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
48 if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
49 /* h is a pipe. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
50 return (state & PIPE_NOWAIT) != 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
51 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
52 /* h is a socket. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
53 errno = ENOSYS;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
54 return -1;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
55 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
56 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
57 /* Win32 does not support non-blocking on regular files. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
58 return 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
59 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
60
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
61 int
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
62 set_nonblocking_flag (int desc, bool value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
63 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
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
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
70 if (GetFileType (h) == FILE_TYPE_PIPE)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
71 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
72 /* h is a pipe or socket. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
73 DWORD state;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
74 if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0))
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
75 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
76 /* h is a pipe. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
77 if ((state & PIPE_NOWAIT) != 0)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
78 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
79 if (value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
80 return 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
81 state &= ~PIPE_NOWAIT;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
82 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
83 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
84 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
85 if (!value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
86 return 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
87 state |= PIPE_NOWAIT;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
88 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
89 if (SetNamedPipeHandleState (h, &state, NULL, NULL))
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
90 return 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
91 errno = EINVAL;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
92 return -1;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
93 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
94 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
95 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
96 /* h is a socket. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
97 int v = value;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
98 return ioctl (desc, FIONBIO, &v);
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
99 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
100 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
101 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
102 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
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
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
106 errno = ENOTSUP;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
107 return -1;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
108 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
109 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
110
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
111 #else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
112 /* Unix API. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
113
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
114 # include <fcntl.h>
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
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
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
117 # error Please port nonblocking to your platform
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
118 # endif
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
119
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
120 /* We don't need the gnulib replacement of fcntl() here. */
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
121 # undef fcntl
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
122
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
123 int
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
124 get_nonblocking_flag (int desc)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
125 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
126 int fcntl_flags;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
127
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
128 fcntl_flags = fcntl (desc, F_GETFL, 0);
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
129 if (fcntl_flags < 0)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
130 return -1;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
131 return (fcntl_flags & O_NONBLOCK) != 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
132 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
133
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
134 int
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
135 set_nonblocking_flag (int desc, bool value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
136 {
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
137 int fcntl_flags;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
138
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
139 fcntl_flags = fcntl (desc, F_GETFL, 0);
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
140 if (fcntl_flags < 0)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
141 return -1;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
142 if (((fcntl_flags & O_NONBLOCK) != 0) == value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
143 return 0;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
144 if (value)
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
145 fcntl_flags |= O_NONBLOCK;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
146 else
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
147 fcntl_flags &= ~O_NONBLOCK;
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
148 return fcntl (desc, F_SETFL, fcntl_flags);
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
149 }
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
150
d6c2edffe836 nonblocking: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
151 #endif