Code

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