Blame lib/getdtablesize.c

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