sys_time: Override 'struct timeval' on some native Windows platforms.
[gnulib.git] / lib / select.c
1 /* Emulation for select(2)
2    Contributed by Paolo Bonzini.
3
4    Copyright 2008-2012 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 #include <config.h>
23 #include <alloca.h>
24 #include <assert.h>
25
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
27 /* Native Windows.  */
28
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <limits.h>
32
33 #include <winsock2.h>
34 #include <windows.h>
35 #include <io.h>
36 #include <stdio.h>
37 #include <conio.h>
38 #include <time.h>
39
40 /* Get the overridden 'struct timeval'.  */
41 #include <sys/time.h>
42
43 #include "msvc-nothrow.h"
44
45 #undef select
46
47 struct bitset {
48   unsigned char in[FD_SETSIZE / CHAR_BIT];
49   unsigned char out[FD_SETSIZE / CHAR_BIT];
50 };
51
52 /* Declare data structures for ntdll functions.  */
53 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
54   ULONG NamedPipeType;
55   ULONG NamedPipeConfiguration;
56   ULONG MaximumInstances;
57   ULONG CurrentInstances;
58   ULONG InboundQuota;
59   ULONG ReadDataAvailable;
60   ULONG OutboundQuota;
61   ULONG WriteQuotaAvailable;
62   ULONG NamedPipeState;
63   ULONG NamedPipeEnd;
64 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
65
66 typedef struct _IO_STATUS_BLOCK
67 {
68   union {
69     DWORD Status;
70     PVOID Pointer;
71   } u;
72   ULONG_PTR Information;
73 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
74
75 typedef enum _FILE_INFORMATION_CLASS {
76   FilePipeLocalInformation = 24
77 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
78
79 typedef DWORD (WINAPI *PNtQueryInformationFile)
80          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
81
82 #ifndef PIPE_BUF
83 #define PIPE_BUF        512
84 #endif
85
86 /* Optimized test whether a HANDLE refers to a console.
87    See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>.  */
88 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
89
90 static BOOL
91 IsSocketHandle (HANDLE h)
92 {
93   WSANETWORKEVENTS ev;
94
95   if (IsConsoleHandle (h))
96     return FALSE;
97
98   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
99      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
100   ev.lNetworkEvents = 0xDEADBEEF;
101   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
102   return ev.lNetworkEvents != 0xDEADBEEF;
103 }
104
105 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
106    H).  */
107
108 static int
109 windows_poll_handle (HANDLE h, int fd,
110                      struct bitset *rbits,
111                      struct bitset *wbits,
112                      struct bitset *xbits)
113 {
114   BOOL read, write, except;
115   int i, ret;
116   INPUT_RECORD *irbuffer;
117   DWORD avail, nbuffer;
118   BOOL bRet;
119   IO_STATUS_BLOCK iosb;
120   FILE_PIPE_LOCAL_INFORMATION fpli;
121   static PNtQueryInformationFile NtQueryInformationFile;
122   static BOOL once_only;
123
124   read = write = except = FALSE;
125   switch (GetFileType (h))
126     {
127     case FILE_TYPE_DISK:
128       read = TRUE;
129       write = TRUE;
130       break;
131
132     case FILE_TYPE_PIPE:
133       if (!once_only)
134         {
135           NtQueryInformationFile = (PNtQueryInformationFile)
136             GetProcAddress (GetModuleHandle ("ntdll.dll"),
137                             "NtQueryInformationFile");
138           once_only = TRUE;
139         }
140
141       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
142         {
143           if (avail)
144             read = TRUE;
145         }
146       else if (GetLastError () == ERROR_BROKEN_PIPE)
147         ;
148
149       else
150         {
151           /* It was the write-end of the pipe.  Check if it is writable.
152              If NtQueryInformationFile fails, optimistically assume the pipe is
153              writable.  This could happen on Windows 9x, where
154              NtQueryInformationFile is not available, or if we inherit a pipe
155              that doesn't permit FILE_READ_ATTRIBUTES access on the write end
156              (I think this should not happen since Windows XP SP2; WINE seems
157              fine too).  Otherwise, ensure that enough space is available for
158              atomic writes.  */
159           memset (&iosb, 0, sizeof (iosb));
160           memset (&fpli, 0, sizeof (fpli));
161
162           if (!NtQueryInformationFile
163               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
164                                          FilePipeLocalInformation)
165               || fpli.WriteQuotaAvailable >= PIPE_BUF
166               || (fpli.OutboundQuota < PIPE_BUF &&
167                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
168             write = TRUE;
169         }
170       break;
171
172     case FILE_TYPE_CHAR:
173       write = TRUE;
174       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
175         break;
176
177       ret = WaitForSingleObject (h, 0);
178       if (ret == WAIT_OBJECT_0)
179         {
180           if (!IsConsoleHandle (h))
181             {
182               read = TRUE;
183               break;
184             }
185
186           nbuffer = avail = 0;
187           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
188
189           /* Screen buffers handles are filtered earlier.  */
190           assert (bRet);
191           if (nbuffer == 0)
192             {
193               except = TRUE;
194               break;
195             }
196
197           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
198           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
199           if (!bRet || avail == 0)
200             {
201               except = TRUE;
202               break;
203             }
204
205           for (i = 0; i < avail; i++)
206             if (irbuffer[i].EventType == KEY_EVENT)
207               read = TRUE;
208         }
209       break;
210
211     default:
212       ret = WaitForSingleObject (h, 0);
213       write = TRUE;
214       if (ret == WAIT_OBJECT_0)
215         read = TRUE;
216
217       break;
218     }
219
220   ret = 0;
221   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
222     {
223       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
224       ret++;
225     }
226
227   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
228     {
229       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
230       ret++;
231     }
232
233   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
234     {
235       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
236       ret++;
237     }
238
239   return ret;
240 }
241
242 int
243 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
244             struct timeval *timeout)
245 #undef timeval
246 {
247   static struct timeval tv0;
248   static HANDLE hEvent;
249   HANDLE h, handle_array[FD_SETSIZE + 2];
250   fd_set handle_rfds, handle_wfds, handle_xfds;
251   struct bitset rbits, wbits, xbits;
252   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
253   DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
254   MSG msg;
255   int i, fd, rc;
256
257   if (nfds > FD_SETSIZE)
258     nfds = FD_SETSIZE;
259
260   if (!timeout)
261     wait_timeout = INFINITE;
262   else
263     {
264       wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
265
266       /* select is also used as a portable usleep.  */
267       if (!rfds && !wfds && !xfds)
268         {
269           Sleep (wait_timeout);
270           return 0;
271         }
272     }
273
274   if (!hEvent)
275     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
276
277   handle_array[0] = hEvent;
278   nhandles = 1;
279   nsock = 0;
280
281   /* Copy descriptors to bitsets.  At the same time, eliminate
282      bits in the "wrong" direction for console input buffers
283      and screen buffers, because screen buffers are waitable
284      and they will block until a character is available.  */
285   memset (&rbits, 0, sizeof (rbits));
286   memset (&wbits, 0, sizeof (wbits));
287   memset (&xbits, 0, sizeof (xbits));
288   memset (anyfds_in, 0, sizeof (anyfds_in));
289   if (rfds)
290     for (i = 0; i < rfds->fd_count; i++)
291       {
292         fd = rfds->fd_array[i];
293         h = (HANDLE) _get_osfhandle (fd);
294         if (IsConsoleHandle (h)
295             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
296           continue;
297
298         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
299         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
300       }
301   else
302     rfds = (fd_set *) alloca (sizeof (fd_set));
303
304   if (wfds)
305     for (i = 0; i < wfds->fd_count; i++)
306       {
307         fd = wfds->fd_array[i];
308         h = (HANDLE) _get_osfhandle (fd);
309         if (IsConsoleHandle (h)
310             && GetNumberOfConsoleInputEvents (h, &nbuffer))
311           continue;
312
313         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
314         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
315       }
316   else
317     wfds = (fd_set *) alloca (sizeof (fd_set));
318
319   if (xfds)
320     for (i = 0; i < xfds->fd_count; i++)
321       {
322         fd = xfds->fd_array[i];
323         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
325       }
326   else
327     xfds = (fd_set *) alloca (sizeof (fd_set));
328
329   /* Zero all the fd_sets, including the application's.  */
330   FD_ZERO (rfds);
331   FD_ZERO (wfds);
332   FD_ZERO (xfds);
333   FD_ZERO (&handle_rfds);
334   FD_ZERO (&handle_wfds);
335   FD_ZERO (&handle_xfds);
336
337   /* Classify handles.  Create fd sets for sockets, poll the others. */
338   for (i = 0; i < nfds; i++)
339     {
340       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
341         continue;
342
343       h = (HANDLE) _get_osfhandle (i);
344       if (!h)
345         {
346           errno = EBADF;
347           return -1;
348         }
349
350       if (IsSocketHandle (h))
351         {
352           int requested = FD_CLOSE;
353
354           /* See above; socket handles are mapped onto select, but we
355              need to map descriptors to handles.  */
356           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
357             {
358               requested |= FD_READ | FD_ACCEPT;
359               FD_SET ((SOCKET) h, rfds);
360               FD_SET ((SOCKET) h, &handle_rfds);
361             }
362           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
363             {
364               requested |= FD_WRITE | FD_CONNECT;
365               FD_SET ((SOCKET) h, wfds);
366               FD_SET ((SOCKET) h, &handle_wfds);
367             }
368           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
369             {
370               requested |= FD_OOB;
371               FD_SET ((SOCKET) h, xfds);
372               FD_SET ((SOCKET) h, &handle_xfds);
373             }
374
375           WSAEventSelect ((SOCKET) h, hEvent, requested);
376           nsock++;
377         }
378       else
379         {
380           handle_array[nhandles++] = h;
381
382           /* Poll now.  If we get an event, do not wait below.  */
383           if (wait_timeout != 0
384               && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
385             wait_timeout = 0;
386         }
387     }
388
389   if (wait_timeout == 0 || nsock == 0)
390     rc = 0;
391   else
392     {
393       /* See if we need to wait in the loop below.  If any select is ready,
394          do MsgWaitForMultipleObjects anyway to dispatch messages, but
395          no need to call select again.  */
396       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
397       if (rc == 0)
398         {
399           /* Restore the fd_sets for the other select we do below.  */
400           memcpy (&handle_rfds, rfds, sizeof (fd_set));
401           memcpy (&handle_wfds, wfds, sizeof (fd_set));
402           memcpy (&handle_xfds, xfds, sizeof (fd_set));
403         }
404       else
405         wait_timeout = 0;
406     }
407
408   for (;;)
409     {
410       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
411                                        wait_timeout, QS_ALLINPUT);
412
413       if (ret == WAIT_OBJECT_0 + nhandles)
414         {
415           /* new input of some other kind */
416           BOOL bRet;
417           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
418             {
419               TranslateMessage (&msg);
420               DispatchMessage (&msg);
421             }
422         }
423       else
424         break;
425     }
426
427   /* If we haven't done it yet, check the status of the sockets.  */
428   if (rc == 0 && nsock > 0)
429     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
430
431   /* Now fill in the results.  */
432   FD_ZERO (rfds);
433   FD_ZERO (wfds);
434   FD_ZERO (xfds);
435
436   /* Place a sentinel at the end of the array.  */
437   handle_array[nhandles] = NULL;
438   nhandles = 1;
439   for (i = 0; i < nfds; i++)
440     {
441       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
442         continue;
443
444       h = (HANDLE) _get_osfhandle (i);
445       if (h != handle_array[nhandles])
446         {
447           /* Perform handle->descriptor mapping.  Don't update rc, as these
448              results are counted in the return value of Winsock's select.  */
449           WSAEventSelect ((SOCKET) h, NULL, 0);
450           if (FD_ISSET (h, &handle_rfds))
451             FD_SET (i, rfds);
452           if (FD_ISSET (h, &handle_wfds))
453             FD_SET (i, wfds);
454           if (FD_ISSET (h, &handle_xfds))
455             FD_SET (i, xfds);
456         }
457       else
458         {
459           /* Not a socket.  */
460           nhandles++;
461           windows_poll_handle (h, i, &rbits, &wbits, &xbits);
462           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
463             {
464               rc++;
465               FD_SET (i, rfds);
466             }
467           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
468             {
469               rc++;
470               FD_SET (i, wfds);
471             }
472           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
473             {
474               rc++;
475               FD_SET (i, xfds);
476             }
477         }
478     }
479
480   return rc;
481 }
482
483 #else /* ! Native Windows.  */
484
485 #include <sys/select.h>
486
487 #undef select
488
489 int
490 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
491             struct timeval *timeout)
492 {
493   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
494   if (nfds == 0)
495     {
496       nfds = 1;
497       rfds = NULL;
498       wfds = NULL;
499       xfds = NULL;
500     }
501   return select (nfds, rfds, wfds, xfds, timeout);
502 }
503
504 #endif