Blame lib/getdtablesize.c

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