Seventh batch for 2.20
[git/git.git] / compat / poll / poll.c
CommitLineData
49521af8
EFL
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
f0bd6649 4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
49521af8
EFL
5
6 This file is part of gnulib.
7
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.
12
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.
17
18 You should have received a copy of the GNU General Public License along
48425792 19 with this program; if not, see <http://www.gnu.org/licenses/>. */
49521af8
EFL
20
21/* Tell gcc not to warn about the (nfd < 0) tests, below. */
22#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
23# pragma GCC diagnostic ignored "-Wtype-limits"
24#endif
25
98c573a9
JS
26#if defined(WIN32)
27# include <malloc.h>
28#endif
49521af8
EFL
29
30#include <sys/types.h>
f0bd6649 31
49521af8
EFL
32#include <errno.h>
33#include <limits.h>
34#include <assert.h>
35
36#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
37# define WIN32_NATIVE
8453c125 38# if defined (_MSC_VER) && !defined(_WIN32_WINNT)
56fb3ddc
RJ
39# define _WIN32_WINNT 0x0502
40# endif
49521af8
EFL
41# include <winsock2.h>
42# include <windows.h>
43# include <io.h>
44# include <stdio.h>
45# include <conio.h>
46#else
47# include <sys/time.h>
48# include <sys/socket.h>
98c573a9
JS
49# ifndef NO_SYS_SELECT_H
50# include <sys/select.h>
51# endif
49521af8
EFL
52# include <unistd.h>
53#endif
54
d7e357fb
JS
55/* Specification. */
56#include "poll.h"
57
49521af8
EFL
58#ifdef HAVE_SYS_IOCTL_H
59# include <sys/ioctl.h>
60#endif
61#ifdef HAVE_SYS_FILIO_H
62# include <sys/filio.h>
63#endif
64
65#include <time.h>
66
67#ifndef INFTIM
68# define INFTIM (-1)
69#endif
70
71/* BeOS does not have MSG_PEEK. */
72#ifndef MSG_PEEK
73# define MSG_PEEK 0
74#endif
75
76#ifdef WIN32_NATIVE
77
7c00bc39 78#define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
49521af8
EFL
79
80static BOOL
81IsSocketHandle (HANDLE h)
82{
83 WSANETWORKEVENTS ev;
84
85 if (IsConsoleHandle (h))
86 return FALSE;
87
88 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
89 WSAEnumNetworkEvents instead distinguishes the two correctly. */
90 ev.lNetworkEvents = 0xDEADBEEF;
91 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
92 return ev.lNetworkEvents != 0xDEADBEEF;
93}
94
95/* Declare data structures for ntdll functions. */
96typedef struct _FILE_PIPE_LOCAL_INFORMATION {
97 ULONG NamedPipeType;
98 ULONG NamedPipeConfiguration;
99 ULONG MaximumInstances;
100 ULONG CurrentInstances;
101 ULONG InboundQuota;
102 ULONG ReadDataAvailable;
103 ULONG OutboundQuota;
104 ULONG WriteQuotaAvailable;
105 ULONG NamedPipeState;
106 ULONG NamedPipeEnd;
107} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
108
109typedef struct _IO_STATUS_BLOCK
110{
111 union {
112 DWORD Status;
113 PVOID Pointer;
114 } u;
115 ULONG_PTR Information;
116} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
117
118typedef enum _FILE_INFORMATION_CLASS {
119 FilePipeLocalInformation = 24
120} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
121
122typedef DWORD (WINAPI *PNtQueryInformationFile)
123 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
124
125# ifndef PIPE_BUF
126# define PIPE_BUF 512
127# endif
128
129/* Compute revents values for file handle H. If some events cannot happen
130 for the handle, eliminate them from *P_SOUGHT. */
131
132static int
133win32_compute_revents (HANDLE h, int *p_sought)
134{
135 int i, ret, happened;
136 INPUT_RECORD *irbuffer;
137 DWORD avail, nbuffer;
138 BOOL bRet;
139 IO_STATUS_BLOCK iosb;
140 FILE_PIPE_LOCAL_INFORMATION fpli;
141 static PNtQueryInformationFile NtQueryInformationFile;
142 static BOOL once_only;
143
144 switch (GetFileType (h))
145 {
146 case FILE_TYPE_PIPE:
147 if (!once_only)
148 {
149 NtQueryInformationFile = (PNtQueryInformationFile)
150 GetProcAddress (GetModuleHandle ("ntdll.dll"),
151 "NtQueryInformationFile");
152 once_only = TRUE;
153 }
154
155 happened = 0;
156 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
157 {
158 if (avail)
159 happened |= *p_sought & (POLLIN | POLLRDNORM);
160 }
161 else if (GetLastError () == ERROR_BROKEN_PIPE)
162 happened |= POLLHUP;
163
164 else
165 {
166 /* It was the write-end of the pipe. Check if it is writable.
167 If NtQueryInformationFile fails, optimistically assume the pipe is
168 writable. This could happen on Win9x, where NtQueryInformationFile
169 is not available, or if we inherit a pipe that doesn't permit
170 FILE_READ_ATTRIBUTES access on the write end (I think this should
171 not happen since WinXP SP2; WINE seems fine too). Otherwise,
172 ensure that enough space is available for atomic writes. */
173 memset (&iosb, 0, sizeof (iosb));
174 memset (&fpli, 0, sizeof (fpli));
175
176 if (!NtQueryInformationFile
177 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
178 FilePipeLocalInformation)
179 || fpli.WriteQuotaAvailable >= PIPE_BUF
180 || (fpli.OutboundQuota < PIPE_BUF &&
181 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
182 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
183 }
184 return happened;
185
186 case FILE_TYPE_CHAR:
187 ret = WaitForSingleObject (h, 0);
188 if (!IsConsoleHandle (h))
189 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
190
191 nbuffer = avail = 0;
192 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
193 if (bRet)
194 {
195 /* Input buffer. */
196 *p_sought &= POLLIN | POLLRDNORM;
197 if (nbuffer == 0)
198 return POLLHUP;
199 if (!*p_sought)
200 return 0;
201
202 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
203 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
204 if (!bRet || avail == 0)
205 return POLLHUP;
206
207 for (i = 0; i < avail; i++)
208 if (irbuffer[i].EventType == KEY_EVENT)
209 return *p_sought;
210 return 0;
211 }
212 else
213 {
214 /* Screen buffer. */
215 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
216 return *p_sought;
217 }
218
219 default:
220 ret = WaitForSingleObject (h, 0);
221 if (ret == WAIT_OBJECT_0)
222 return *p_sought & ~(POLLPRI | POLLRDBAND);
223
224 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
225 }
226}
227
228/* Convert fd_sets returned by select into revents values. */
229
230static int
231win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
232{
233 int happened = 0;
234
235 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
236 happened |= (POLLIN | POLLRDNORM) & sought;
237
238 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
239 {
240 int r, error;
241
242 char data[64];
243 WSASetLastError (0);
244 r = recv (h, data, sizeof (data), MSG_PEEK);
245 error = WSAGetLastError ();
246 WSASetLastError (0);
247
248 if (r > 0 || error == WSAENOTCONN)
249 happened |= (POLLIN | POLLRDNORM) & sought;
250
251 /* Distinguish hung-up sockets from other errors. */
252 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
253 || error == WSAECONNABORTED || error == WSAENETRESET)
254 happened |= POLLHUP;
255
256 else
257 happened |= POLLERR;
258 }
259
260 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
261 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
262
263 if (lNetworkEvents & FD_OOB)
264 happened |= (POLLPRI | POLLRDBAND) & sought;
265
266 return happened;
267}
268
269#else /* !MinGW */
270
271/* Convert select(2) returned fd_sets into poll(2) revents values. */
272static int
273compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
274{
275 int happened = 0;
276 if (FD_ISSET (fd, rfds))
277 {
278 int r;
279 int socket_errno;
280
281# if defined __MACH__ && defined __APPLE__
282 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
283 for some kinds of descriptors. Detect if this descriptor is a
284 connected socket, a server socket, or something else using a
285 0-byte recv, and use ioctl(2) to detect POLLHUP. */
286 r = recv (fd, NULL, 0, MSG_PEEK);
287 socket_errno = (r < 0) ? errno : 0;
288 if (r == 0 || socket_errno == ENOTSOCK)
289 ioctl (fd, FIONREAD, &r);
290# else
291 char data[64];
292 r = recv (fd, data, sizeof (data), MSG_PEEK);
293 socket_errno = (r < 0) ? errno : 0;
294# endif
295 if (r == 0)
296 happened |= POLLHUP;
297
298 /* If the event happened on an unconnected server socket,
299 that's fine. */
300 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
301 happened |= (POLLIN | POLLRDNORM) & sought;
302
303 /* Distinguish hung-up sockets from other errors. */
304 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
305 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
306 happened |= POLLHUP;
307
a6772946
JS
308 /* some systems can't use recv() on non-socket, including HP NonStop */
309 else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
310 happened |= (POLLIN | POLLRDNORM) & sought;
311
49521af8
EFL
312 else
313 happened |= POLLERR;
314 }
315
316 if (FD_ISSET (fd, wfds))
317 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
318
319 if (FD_ISSET (fd, efds))
320 happened |= (POLLPRI | POLLRDBAND) & sought;
321
322 return happened;
323}
324#endif /* !MinGW */
325
326int
f0bd6649 327poll (struct pollfd *pfd, nfds_t nfd, int timeout)
49521af8
EFL
328{
329#ifndef WIN32_NATIVE
330 fd_set rfds, wfds, efds;
331 struct timeval tv;
332 struct timeval *ptv;
333 int maxfd, rc;
334 nfds_t i;
335
336# ifdef _SC_OPEN_MAX
337 static int sc_open_max = -1;
338
339 if (nfd < 0
340 || (nfd > sc_open_max
341 && (sc_open_max != -1
342 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
343 {
344 errno = EINVAL;
345 return -1;
346 }
347# else /* !_SC_OPEN_MAX */
348# ifdef OPEN_MAX
349 if (nfd < 0 || nfd > OPEN_MAX)
350 {
351 errno = EINVAL;
352 return -1;
353 }
354# endif /* OPEN_MAX -- else, no check is needed */
355# endif /* !_SC_OPEN_MAX */
356
357 /* EFAULT is not necessary to implement, but let's do it in the
358 simplest case. */
32fde657 359 if (!pfd && nfd)
49521af8
EFL
360 {
361 errno = EFAULT;
362 return -1;
363 }
364
365 /* convert timeout number into a timeval structure */
366 if (timeout == 0)
367 {
368 ptv = &tv;
369 ptv->tv_sec = 0;
370 ptv->tv_usec = 0;
371 }
372 else if (timeout > 0)
373 {
374 ptv = &tv;
375 ptv->tv_sec = timeout / 1000;
376 ptv->tv_usec = (timeout % 1000) * 1000;
377 }
378 else if (timeout == INFTIM)
379 /* wait forever */
380 ptv = NULL;
381 else
382 {
383 errno = EINVAL;
384 return -1;
385 }
386
387 /* create fd sets and determine max fd */
388 maxfd = -1;
389 FD_ZERO (&rfds);
390 FD_ZERO (&wfds);
391 FD_ZERO (&efds);
392 for (i = 0; i < nfd; i++)
393 {
394 if (pfd[i].fd < 0)
395 continue;
396
397 if (pfd[i].events & (POLLIN | POLLRDNORM))
398 FD_SET (pfd[i].fd, &rfds);
399
400 /* see select(2): "the only exceptional condition detectable
401 is out-of-band data received on a socket", hence we push
402 POLLWRBAND events onto wfds instead of efds. */
403 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
404 FD_SET (pfd[i].fd, &wfds);
405 if (pfd[i].events & (POLLPRI | POLLRDBAND))
406 FD_SET (pfd[i].fd, &efds);
407 if (pfd[i].fd >= maxfd
408 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
409 | POLLRDNORM | POLLRDBAND
410 | POLLWRNORM | POLLWRBAND)))
411 {
412 maxfd = pfd[i].fd;
413 if (maxfd > FD_SETSIZE)
414 {
415 errno = EOVERFLOW;
416 return -1;
417 }
418 }
419 }
420
421 /* examine fd sets */
422 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
423 if (rc < 0)
424 return rc;
425
426 /* establish results */
427 rc = 0;
428 for (i = 0; i < nfd; i++)
429 if (pfd[i].fd < 0)
430 pfd[i].revents = 0;
431 else
432 {
433 int happened = compute_revents (pfd[i].fd, pfd[i].events,
434 &rfds, &wfds, &efds);
435 if (happened)
436 {
437 pfd[i].revents = happened;
438 rc++;
439 }
61b2a1ac
RB
440 else
441 {
442 pfd[i].revents = 0;
443 }
49521af8
EFL
444 }
445
446 return rc;
447#else
448 static struct timeval tv0;
449 static HANDLE hEvent;
450 WSANETWORKEVENTS ev;
451 HANDLE h, handle_array[FD_SETSIZE + 2];
ef8b53e7 452 DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0;
49521af8
EFL
453 fd_set rfds, wfds, xfds;
454 BOOL poll_again;
455 MSG msg;
456 int rc = 0;
457 nfds_t i;
458
459 if (nfd < 0 || timeout < -1)
460 {
461 errno = EINVAL;
462 return -1;
463 }
464
ef8b53e7
ET
465 if (timeout != INFTIM)
466 {
467 orig_timeout = timeout;
468 start = GetTickCount();
469 }
470
49521af8
EFL
471 if (!hEvent)
472 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
473
f0bd6649 474restart:
49521af8
EFL
475 handle_array[0] = hEvent;
476 nhandles = 1;
477 FD_ZERO (&rfds);
478 FD_ZERO (&wfds);
479 FD_ZERO (&xfds);
480
481 /* Classify socket handles and create fd sets. */
482 for (i = 0; i < nfd; i++)
483 {
484 int sought = pfd[i].events;
485 pfd[i].revents = 0;
486 if (pfd[i].fd < 0)
487 continue;
488 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
489 | POLLPRI | POLLRDBAND)))
490 continue;
491
492 h = (HANDLE) _get_osfhandle (pfd[i].fd);
493 assert (h != NULL);
494 if (IsSocketHandle (h))
495 {
496 int requested = FD_CLOSE;
497
498 /* see above; socket handles are mapped onto select. */
499 if (sought & (POLLIN | POLLRDNORM))
500 {
501 requested |= FD_READ | FD_ACCEPT;
502 FD_SET ((SOCKET) h, &rfds);
503 }
504 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
505 {
506 requested |= FD_WRITE | FD_CONNECT;
507 FD_SET ((SOCKET) h, &wfds);
508 }
509 if (sought & (POLLPRI | POLLRDBAND))
510 {
511 requested |= FD_OOB;
512 FD_SET ((SOCKET) h, &xfds);
513 }
514
515 if (requested)
516 WSAEventSelect ((SOCKET) h, hEvent, requested);
517 }
518 else
519 {
520 /* Poll now. If we get an event, do not poll again. Also,
521 screen buffer handles are waitable, and they'll block until
522 a character is available. win32_compute_revents eliminates
523 bits for the "wrong" direction. */
524 pfd[i].revents = win32_compute_revents (h, &sought);
525 if (sought)
526 handle_array[nhandles++] = h;
527 if (pfd[i].revents)
528 timeout = 0;
529 }
530 }
531
532 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
533 {
534 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
535 no need to call select again. */
536 poll_again = FALSE;
537 wait_timeout = 0;
538 }
539 else
540 {
541 poll_again = TRUE;
542 if (timeout == INFTIM)
543 wait_timeout = INFINITE;
544 else
545 wait_timeout = timeout;
546 }
547
548 for (;;)
549 {
550 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
551 wait_timeout, QS_ALLINPUT);
552
553 if (ret == WAIT_OBJECT_0 + nhandles)
554 {
555 /* new input of some other kind */
556 BOOL bRet;
557 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
558 {
559 TranslateMessage (&msg);
560 DispatchMessage (&msg);
561 }
562 }
563 else
564 break;
565 }
566
567 if (poll_again)
568 select (0, &rfds, &wfds, &xfds, &tv0);
569
570 /* Place a sentinel at the end of the array. */
571 handle_array[nhandles] = NULL;
572 nhandles = 1;
573 for (i = 0; i < nfd; i++)
574 {
575 int happened;
576
577 if (pfd[i].fd < 0)
578 continue;
579 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
580 POLLOUT | POLLWRNORM | POLLWRBAND)))
581 continue;
582
583 h = (HANDLE) _get_osfhandle (pfd[i].fd);
584 if (h != handle_array[nhandles])
585 {
586 /* It's a socket. */
587 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
1c31596a 588 WSAEventSelect ((SOCKET) h, NULL, 0);
49521af8
EFL
589
590 /* If we're lucky, WSAEnumNetworkEvents already provided a way
591 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
592 if (FD_ISSET ((SOCKET) h, &rfds)
593 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
594 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
595 if (FD_ISSET ((SOCKET) h, &wfds))
596 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
597 if (FD_ISSET ((SOCKET) h, &xfds))
598 ev.lNetworkEvents |= FD_OOB;
599
600 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
601 ev.lNetworkEvents);
602 }
603 else
604 {
605 /* Not a socket. */
606 int sought = pfd[i].events;
607 happened = win32_compute_revents (h, &sought);
608 nhandles++;
609 }
610
611 if ((pfd[i].revents |= happened) != 0)
612 rc++;
613 }
614
ef8b53e7
ET
615 if (!rc && orig_timeout && timeout != INFTIM)
616 {
617 elapsed = GetTickCount() - start;
618 timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed;
619 }
620
621 if (!rc && timeout)
f0bd6649 622 {
76e7c8a7 623 SleepEx (1, TRUE);
f0bd6649
EFL
624 goto restart;
625 }
626
49521af8
EFL
627 return rc;
628#endif
629}