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