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