Blame gnulib/tests/getdtablesize.c

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