Blame lib/getdtablesize.c

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