Blame lib/getdtablesize.c

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