Code

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