(root)/
tar-1.35/
gnu/
getdtablesize.c
       1  /* getdtablesize() function: Return maximum possible file descriptor value + 1.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2008.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  /* Specification.  */
      21  #include <unistd.h>
      22  
      23  #if defined _WIN32 && ! defined __CYGWIN__
      24  
      25  # include <stdio.h>
      26  
      27  # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      28  #  include "msvc-inval.h"
      29  # endif
      30  
      31  # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      32  static int
      33  _setmaxstdio_nothrow (int newmax)
      34  {
      35    int result;
      36  
      37    TRY_MSVC_INVAL
      38      {
      39        result = _setmaxstdio (newmax);
      40      }
      41    CATCH_MSVC_INVAL
      42      {
      43        result = -1;
      44      }
      45    DONE_MSVC_INVAL;
      46  
      47    return result;
      48  }
      49  # else
      50  #  define _setmaxstdio_nothrow _setmaxstdio
      51  # endif
      52  
      53  /* Cache for the previous getdtablesize () result.  Safe to cache because
      54     Windows also lacks setrlimit.  */
      55  static int dtablesize;
      56  
      57  int
      58  getdtablesize (void)
      59  {
      60    if (dtablesize == 0)
      61      {
      62        /* We are looking for the number N such that the valid file descriptors
      63           are 0..N-1.  It can be obtained through a loop as follows:
      64             {
      65               int fd;
      66               for (fd = 3; fd < 65536; fd++)
      67                 if (dup2 (0, fd) == -1)
      68                   break;
      69               return fd;
      70             }
      71           On Windows XP, the result is 2048.
      72           The drawback of this loop is that it allocates memory for a libc
      73           internal array that is never freed.
      74  
      75           The number N can also be obtained as the upper bound for
      76           _getmaxstdio ().  _getmaxstdio () returns the maximum number of open
      77           FILE objects.  The sanity check in _setmaxstdio reveals the maximum
      78           number of file descriptors.  This too allocates memory, but it is
      79           freed when we call _setmaxstdio with the original value.  */
      80        int orig_max_stdio = _getmaxstdio ();
      81        unsigned int bound;
      82        for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
      83          ;
      84        _setmaxstdio_nothrow (orig_max_stdio);
      85        dtablesize = bound;
      86      }
      87    return dtablesize;
      88  }
      89  
      90  #else
      91  
      92  # include <limits.h>
      93  # include <sys/resource.h>
      94  
      95  # ifndef RLIM_SAVED_CUR
      96  #  define RLIM_SAVED_CUR RLIM_INFINITY
      97  # endif
      98  # ifndef RLIM_SAVED_MAX
      99  #  define RLIM_SAVED_MAX RLIM_INFINITY
     100  # endif
     101  
     102  # ifdef __CYGWIN__
     103    /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it
     104       hits the compile-time constant hard limit of 3200.  We might as
     105       well just report the hard limit.  */
     106  #  define rlim_cur rlim_max
     107  # endif
     108  
     109  int
     110  getdtablesize (void)
     111  {
     112    struct rlimit lim;
     113  
     114    if (getrlimit (RLIMIT_NOFILE, &lim) == 0
     115        && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX
     116        && lim.rlim_cur != RLIM_INFINITY
     117        && lim.rlim_cur != RLIM_SAVED_CUR
     118        && lim.rlim_cur != RLIM_SAVED_MAX)
     119      return lim.rlim_cur;
     120  
     121    return INT_MAX;
     122  }
     123  
     124  #endif