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