Blame gl/getdtablesize.c

Packit Service 4684c1
/* getdtablesize() function: Return maximum possible file descriptor value + 1.
Packit Service 4684c1
   Copyright (C) 2008-2020 Free Software Foundation, Inc.
Packit Service 4684c1
   Written by Bruno Haible <bruno@clisp.org>, 2008.
Packit Service 4684c1
Packit Service 4684c1
   This program is free software: you can redistribute it and/or modify
Packit Service 4684c1
   it under the terms of the GNU Lesser General Public License as published by
Packit Service 4684c1
   the Free Software Foundation; either version 2.1 of the License, or
Packit Service 4684c1
   (at your option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   This program is distributed in the hope that it will be useful,
Packit Service 4684c1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 4684c1
   GNU Lesser General Public License for more details.
Packit Service 4684c1
Packit Service 4684c1
   You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service 4684c1
Packit Service 4684c1
#include <config.h>
Packit Service 4684c1
Packit Service 4684c1
/* Specification.  */
Packit Service 4684c1
#include <unistd.h>
Packit Service 4684c1
Packit Service 4684c1
#if defined _WIN32 && ! defined __CYGWIN__
Packit Service 4684c1
Packit Service 4684c1
# include <stdio.h>
Packit Service 4684c1
Packit Service 4684c1
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
Packit Service 4684c1
#  include "msvc-inval.h"
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
Packit Service 4684c1
static int
Packit Service 4684c1
_setmaxstdio_nothrow (int newmax)
Packit Service 4684c1
{
Packit Service 4684c1
  int result;
Packit Service 4684c1
Packit Service 4684c1
  TRY_MSVC_INVAL
Packit Service 4684c1
    {
Packit Service 4684c1
      result = _setmaxstdio (newmax);
Packit Service 4684c1
    }
Packit Service 4684c1
  CATCH_MSVC_INVAL
Packit Service 4684c1
    {
Packit Service 4684c1
      result = -1;
Packit Service 4684c1
    }
Packit Service 4684c1
  DONE_MSVC_INVAL;
Packit Service 4684c1
Packit Service 4684c1
  return result;
Packit Service 4684c1
}
Packit Service 4684c1
# else
Packit Service 4684c1
#  define _setmaxstdio_nothrow _setmaxstdio
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
/* Cache for the previous getdtablesize () result.  Safe to cache because
Packit Service 4684c1
   Windows also lacks setrlimit.  */
Packit Service 4684c1
static int dtablesize;
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
getdtablesize (void)
Packit Service 4684c1
{
Packit Service 4684c1
  if (dtablesize == 0)
Packit Service 4684c1
    {
Packit Service 4684c1
      /* We are looking for the number N such that the valid file descriptors
Packit Service 4684c1
         are 0..N-1.  It can be obtained through a loop as follows:
Packit Service 4684c1
           {
Packit Service 4684c1
             int fd;
Packit Service 4684c1
             for (fd = 3; fd < 65536; fd++)
Packit Service 4684c1
               if (dup2 (0, fd) == -1)
Packit Service 4684c1
                 break;
Packit Service 4684c1
             return fd;
Packit Service 4684c1
           }
Packit Service 4684c1
         On Windows XP, the result is 2048.
Packit Service 4684c1
         The drawback of this loop is that it allocates memory for a libc
Packit Service 4684c1
         internal array that is never freed.
Packit Service 4684c1
Packit Service 4684c1
         The number N can also be obtained as the upper bound for
Packit Service 4684c1
         _getmaxstdio ().  _getmaxstdio () returns the maximum number of open
Packit Service 4684c1
         FILE objects.  The sanity check in _setmaxstdio reveals the maximum
Packit Service 4684c1
         number of file descriptors.  This too allocates memory, but it is
Packit Service 4684c1
         freed when we call _setmaxstdio with the original value.  */
Packit Service 4684c1
      int orig_max_stdio = _getmaxstdio ();
Packit Service 4684c1
      unsigned int bound;
Packit Service 4684c1
      for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
Packit Service 4684c1
        ;
Packit Service 4684c1
      _setmaxstdio_nothrow (orig_max_stdio);
Packit Service 4684c1
      dtablesize = bound;
Packit Service 4684c1
    }
Packit Service 4684c1
  return dtablesize;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#else
Packit Service 4684c1
Packit Service 4684c1
# include <limits.h>
Packit Service 4684c1
# include <sys/resource.h>
Packit Service 4684c1
Packit Service 4684c1
# ifndef RLIM_SAVED_CUR
Packit Service 4684c1
#  define RLIM_SAVED_CUR RLIM_INFINITY
Packit Service 4684c1
# endif
Packit Service 4684c1
# ifndef RLIM_SAVED_MAX
Packit Service 4684c1
#  define RLIM_SAVED_MAX RLIM_INFINITY
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
# ifdef __CYGWIN__
Packit Service 4684c1
  /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it
Packit Service 4684c1
     hits the compile-time constant hard limit of 3200.  We might as
Packit Service 4684c1
     well just report the hard limit.  */
Packit Service 4684c1
#  define rlim_cur rlim_max
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
getdtablesize (void)
Packit Service 4684c1
{
Packit Service 4684c1
  struct rlimit lim;
Packit Service 4684c1
Packit Service 4684c1
  if (getrlimit (RLIMIT_NOFILE, &lim) == 0
Packit Service 4684c1
      && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX
Packit Service 4684c1
      && lim.rlim_cur != RLIM_INFINITY
Packit Service 4684c1
      && lim.rlim_cur != RLIM_SAVED_CUR
Packit Service 4684c1
      && lim.rlim_cur != RLIM_SAVED_MAX)
Packit Service 4684c1
    return lim.rlim_cur;
Packit Service 4684c1
Packit Service 4684c1
  return INT_MAX;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#endif