fchmod-tests, fchmodat tests, lchmod tests: Add more tests.
[gnulib.git] / lib / select.c
blobdb53d7871633c083600ba07e4c747ec94400bb6c
1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2021 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, see <https://www.gnu.org/licenses/>. */
21 #include <config.h>
23 /* Specification. */
24 #include <sys/select.h>
26 #if defined _WIN32 && ! defined __CYGWIN__
27 /* Native Windows. */
29 #include <alloca.h>
30 #include <assert.h>
31 #include <sys/types.h>
32 #include <errno.h>
33 #include <limits.h>
35 #include <winsock2.h>
36 #include <windows.h>
37 #include <io.h>
38 #include <stdio.h>
39 #include <conio.h>
40 #include <time.h>
42 /* Get the overridden 'struct timeval'. */
43 #include <sys/time.h>
45 #if GNULIB_MSVC_NOTHROW
46 # include "msvc-nothrow.h"
47 #else
48 # include <io.h>
49 #endif
51 #undef select
53 /* Don't assume that UNICODE is not defined. */
54 #undef GetModuleHandle
55 #define GetModuleHandle GetModuleHandleA
56 #undef PeekConsoleInput
57 #define PeekConsoleInput PeekConsoleInputA
58 #undef CreateEvent
59 #define CreateEvent CreateEventA
60 #undef PeekMessage
61 #define PeekMessage PeekMessageA
62 #undef DispatchMessage
63 #define DispatchMessage DispatchMessageA
65 /* Avoid warnings from gcc -Wcast-function-type. */
66 #define GetProcAddress \
67 (void *) GetProcAddress
69 struct bitset {
70 unsigned char in[FD_SETSIZE / CHAR_BIT];
71 unsigned char out[FD_SETSIZE / CHAR_BIT];
74 /* Declare data structures for ntdll functions. */
75 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
76 ULONG NamedPipeType;
77 ULONG NamedPipeConfiguration;
78 ULONG MaximumInstances;
79 ULONG CurrentInstances;
80 ULONG InboundQuota;
81 ULONG ReadDataAvailable;
82 ULONG OutboundQuota;
83 ULONG WriteQuotaAvailable;
84 ULONG NamedPipeState;
85 ULONG NamedPipeEnd;
86 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
88 typedef struct _IO_STATUS_BLOCK
90 union {
91 DWORD Status;
92 PVOID Pointer;
93 } u;
94 ULONG_PTR Information;
95 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
97 typedef enum _FILE_INFORMATION_CLASS {
98 FilePipeLocalInformation = 24
99 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
101 typedef DWORD (WINAPI *PNtQueryInformationFile)
102 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
104 #ifndef PIPE_BUF
105 #define PIPE_BUF 512
106 #endif
108 static BOOL IsConsoleHandle (HANDLE h)
110 DWORD mode;
111 return GetConsoleMode (h, &mode) != 0;
114 static BOOL
115 IsSocketHandle (HANDLE h)
117 WSANETWORKEVENTS ev;
119 if (IsConsoleHandle (h))
120 return FALSE;
122 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
123 WSAEnumNetworkEvents instead distinguishes the two correctly. */
124 ev.lNetworkEvents = 0xDEADBEEF;
125 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
126 return ev.lNetworkEvents != 0xDEADBEEF;
129 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
130 H). */
132 static int
133 windows_poll_handle (HANDLE h, int fd,
134 struct bitset *rbits,
135 struct bitset *wbits,
136 struct bitset *xbits)
138 BOOL read, write, except;
139 int i, ret;
140 INPUT_RECORD *irbuffer;
141 DWORD avail, nbuffer;
142 BOOL bRet;
143 IO_STATUS_BLOCK iosb;
144 FILE_PIPE_LOCAL_INFORMATION fpli;
145 static PNtQueryInformationFile NtQueryInformationFile;
146 static BOOL once_only;
148 read = write = except = FALSE;
149 switch (GetFileType (h))
151 case FILE_TYPE_DISK:
152 read = TRUE;
153 write = TRUE;
154 break;
156 case FILE_TYPE_PIPE:
157 if (!once_only)
159 NtQueryInformationFile = (PNtQueryInformationFile)
160 GetProcAddress (GetModuleHandle ("ntdll.dll"),
161 "NtQueryInformationFile");
162 once_only = TRUE;
165 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
167 if (avail)
168 read = TRUE;
170 else if (GetLastError () == ERROR_BROKEN_PIPE)
173 else
175 /* It was the write-end of the pipe. Check if it is writable.
176 If NtQueryInformationFile fails, optimistically assume the pipe is
177 writable. This could happen on Windows 9x, where
178 NtQueryInformationFile is not available, or if we inherit a pipe
179 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
180 (I think this should not happen since Windows XP SP2; WINE seems
181 fine too). Otherwise, ensure that enough space is available for
182 atomic writes. */
183 memset (&iosb, 0, sizeof (iosb));
184 memset (&fpli, 0, sizeof (fpli));
186 if (!NtQueryInformationFile
187 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
188 FilePipeLocalInformation)
189 || fpli.WriteQuotaAvailable >= PIPE_BUF
190 || (fpli.OutboundQuota < PIPE_BUF &&
191 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
192 write = TRUE;
194 break;
196 case FILE_TYPE_CHAR:
197 write = TRUE;
198 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
199 break;
201 ret = WaitForSingleObject (h, 0);
202 if (ret == WAIT_OBJECT_0)
204 if (!IsConsoleHandle (h))
206 read = TRUE;
207 break;
210 nbuffer = avail = 0;
211 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
213 /* Screen buffers handles are filtered earlier. */
214 assert (bRet);
215 if (nbuffer == 0)
217 except = TRUE;
218 break;
221 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
222 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
223 if (!bRet || avail == 0)
225 except = TRUE;
226 break;
229 for (i = 0; i < avail; i++)
230 if (irbuffer[i].EventType == KEY_EVENT)
231 read = TRUE;
233 break;
235 default:
236 ret = WaitForSingleObject (h, 0);
237 write = TRUE;
238 if (ret == WAIT_OBJECT_0)
239 read = TRUE;
241 break;
244 ret = 0;
245 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
247 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
248 ret++;
251 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
253 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
254 ret++;
257 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
259 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
260 ret++;
263 return ret;
267 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
268 struct timeval *timeout)
269 #undef timeval
271 static struct timeval tv0;
272 static HANDLE hEvent;
273 HANDLE h, handle_array[FD_SETSIZE + 2];
274 fd_set handle_rfds, handle_wfds, handle_xfds;
275 struct bitset rbits, wbits, xbits;
276 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
277 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
278 MSG msg;
279 int i, fd, rc;
280 clock_t tend;
282 if (nfds > FD_SETSIZE)
283 nfds = FD_SETSIZE;
285 if (!timeout)
286 wait_timeout = INFINITE;
287 else
289 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
291 /* select is also used as a portable usleep. */
292 if (!rfds && !wfds && !xfds)
294 Sleep (wait_timeout);
295 return 0;
299 if (!hEvent)
300 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
302 handle_array[0] = hEvent;
303 nhandles = 1;
304 nsock = 0;
306 /* Copy descriptors to bitsets. At the same time, eliminate
307 bits in the "wrong" direction for console input buffers
308 and screen buffers, because screen buffers are waitable
309 and they will block until a character is available. */
310 memset (&rbits, 0, sizeof (rbits));
311 memset (&wbits, 0, sizeof (wbits));
312 memset (&xbits, 0, sizeof (xbits));
313 memset (anyfds_in, 0, sizeof (anyfds_in));
314 if (rfds)
315 for (i = 0; i < rfds->fd_count; i++)
317 fd = rfds->fd_array[i];
318 h = (HANDLE) _get_osfhandle (fd);
319 if (IsConsoleHandle (h)
320 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
321 continue;
323 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
326 else
327 rfds = (fd_set *) alloca (sizeof (fd_set));
329 if (wfds)
330 for (i = 0; i < wfds->fd_count; i++)
332 fd = wfds->fd_array[i];
333 h = (HANDLE) _get_osfhandle (fd);
334 if (IsConsoleHandle (h)
335 && GetNumberOfConsoleInputEvents (h, &nbuffer))
336 continue;
338 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
339 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
341 else
342 wfds = (fd_set *) alloca (sizeof (fd_set));
344 if (xfds)
345 for (i = 0; i < xfds->fd_count; i++)
347 fd = xfds->fd_array[i];
348 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
349 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
351 else
352 xfds = (fd_set *) alloca (sizeof (fd_set));
354 /* Zero all the fd_sets, including the application's. */
355 FD_ZERO (rfds);
356 FD_ZERO (wfds);
357 FD_ZERO (xfds);
358 FD_ZERO (&handle_rfds);
359 FD_ZERO (&handle_wfds);
360 FD_ZERO (&handle_xfds);
362 /* Classify handles. Create fd sets for sockets, poll the others. */
363 for (i = 0; i < nfds; i++)
365 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
366 continue;
368 h = (HANDLE) _get_osfhandle (i);
369 if (!h)
371 errno = EBADF;
372 return -1;
375 if (IsSocketHandle (h))
377 int requested = FD_CLOSE;
379 /* See above; socket handles are mapped onto select, but we
380 need to map descriptors to handles. */
381 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
383 requested |= FD_READ | FD_ACCEPT;
384 FD_SET ((SOCKET) h, rfds);
385 FD_SET ((SOCKET) h, &handle_rfds);
387 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
389 requested |= FD_WRITE | FD_CONNECT;
390 FD_SET ((SOCKET) h, wfds);
391 FD_SET ((SOCKET) h, &handle_wfds);
393 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
395 requested |= FD_OOB;
396 FD_SET ((SOCKET) h, xfds);
397 FD_SET ((SOCKET) h, &handle_xfds);
400 WSAEventSelect ((SOCKET) h, hEvent, requested);
401 nsock++;
403 else
405 handle_array[nhandles++] = h;
407 /* Poll now. If we get an event, do not wait below. */
408 if (wait_timeout != 0
409 && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
410 wait_timeout = 0;
414 /* Place a sentinel at the end of the array. */
415 handle_array[nhandles] = NULL;
417 /* When will the waiting period expire? */
418 if (wait_timeout != INFINITE)
419 tend = clock () + wait_timeout;
421 restart:
422 if (wait_timeout == 0 || nsock == 0)
423 rc = 0;
424 else
426 /* See if we need to wait in the loop below. If any select is ready,
427 do MsgWaitForMultipleObjects anyway to dispatch messages, but
428 no need to call select again. */
429 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
430 if (rc == 0)
432 /* Restore the fd_sets for the other select we do below. */
433 memcpy (&handle_rfds, rfds, sizeof (fd_set));
434 memcpy (&handle_wfds, wfds, sizeof (fd_set));
435 memcpy (&handle_xfds, xfds, sizeof (fd_set));
437 else
438 wait_timeout = 0;
441 /* How much is left to wait? */
442 if (wait_timeout != INFINITE)
444 clock_t tnow = clock ();
445 if (tend >= tnow)
446 wait_timeout = tend - tnow;
447 else
448 wait_timeout = 0;
451 for (;;)
453 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
454 wait_timeout, QS_ALLINPUT);
456 if (ret == WAIT_OBJECT_0 + nhandles)
458 /* new input of some other kind */
459 BOOL bRet;
460 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
462 TranslateMessage (&msg);
463 DispatchMessage (&msg);
466 else
467 break;
470 /* If we haven't done it yet, check the status of the sockets. */
471 if (rc == 0 && nsock > 0)
472 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
474 if (nhandles > 1)
476 /* Count results that are not counted in the return value of select. */
477 nhandles = 1;
478 for (i = 0; i < nfds; i++)
480 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
481 continue;
483 h = (HANDLE) _get_osfhandle (i);
484 if (h == handle_array[nhandles])
486 /* Not a socket. */
487 nhandles++;
488 windows_poll_handle (h, i, &rbits, &wbits, &xbits);
489 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
490 || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
491 || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
492 rc++;
496 if (rc == 0
497 && (wait_timeout == INFINITE
498 /* If NHANDLES > 1, but no bits are set, it means we've
499 been told incorrectly that some handle was signaled.
500 This happens with anonymous pipes, which always cause
501 MsgWaitForMultipleObjects to exit immediately, but no
502 data is found ready to be read by windows_poll_handle.
503 To avoid a total failure (whereby we return zero and
504 don't wait at all), let's poll in a more busy loop. */
505 || (wait_timeout != 0 && nhandles > 1)))
507 /* Sleep 1 millisecond to avoid busy wait and retry with the
508 original fd_sets. */
509 memcpy (&handle_rfds, rfds, sizeof (fd_set));
510 memcpy (&handle_wfds, wfds, sizeof (fd_set));
511 memcpy (&handle_xfds, xfds, sizeof (fd_set));
512 SleepEx (1, TRUE);
513 goto restart;
515 if (timeout && wait_timeout == 0 && rc == 0)
516 timeout->tv_sec = timeout->tv_usec = 0;
519 /* Now fill in the results. */
520 FD_ZERO (rfds);
521 FD_ZERO (wfds);
522 FD_ZERO (xfds);
523 nhandles = 1;
524 for (i = 0; i < nfds; i++)
526 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
527 continue;
529 h = (HANDLE) _get_osfhandle (i);
530 if (h != handle_array[nhandles])
532 /* Perform handle->descriptor mapping. */
533 WSAEventSelect ((SOCKET) h, NULL, 0);
534 if (FD_ISSET (h, &handle_rfds))
535 FD_SET (i, rfds);
536 if (FD_ISSET (h, &handle_wfds))
537 FD_SET (i, wfds);
538 if (FD_ISSET (h, &handle_xfds))
539 FD_SET (i, xfds);
541 else
543 /* Not a socket. */
544 nhandles++;
545 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
546 FD_SET (i, rfds);
547 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
548 FD_SET (i, wfds);
549 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
550 FD_SET (i, xfds);
554 return rc;
557 #else /* ! Native Windows. */
559 #include <stddef.h> /* NULL */
560 #include <errno.h>
561 #include <unistd.h>
563 #undef select
566 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
567 struct timeval *timeout)
569 int i;
571 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
572 if (nfds < 0 || nfds > FD_SETSIZE)
574 errno = EINVAL;
575 return -1;
577 for (i = 0; i < nfds; i++)
579 if (((rfds && FD_ISSET (i, rfds))
580 || (wfds && FD_ISSET (i, wfds))
581 || (xfds && FD_ISSET (i, xfds)))
582 && dup2 (i, i) != i)
583 return -1;
586 /* Interix 3.5 has a bug: it does not support nfds == 0. */
587 if (nfds == 0)
589 nfds = 1;
590 rfds = NULL;
591 wfds = NULL;
592 xfds = NULL;
594 return select (nfds, rfds, wfds, xfds, timeout);
597 #endif