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