Blame lib/getdtablesize.c

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