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