(root)/
glibc-2.38/
io/
tst-closefrom.c
       1  /* Smoke test for the closefrom.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library 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 GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <sys/resource.h>
      22  #include <unistd.h>
      23  
      24  #include <support/check.h>
      25  #include <support/descriptors.h>
      26  #include <support/xunistd.h>
      27  #include <support/support.h>
      28  
      29  #include <array_length.h>
      30  
      31  #define NFDS 100
      32  
      33  static int
      34  closefrom_test (void)
      35  {
      36    struct support_descriptors *descrs = support_descriptors_list ();
      37  
      38    int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
      39  
      40    const int maximum_fd = lowfd + NFDS - 1;
      41    const int half_fd = lowfd + NFDS / 2;
      42    const int gap = lowfd + NFDS / 4;
      43  
      44    /* Close half of the descriptors and check result.  */
      45    closefrom (half_fd);
      46  
      47    for (int i = half_fd; i <= maximum_fd; i++)
      48      {
      49        TEST_COMPARE (fcntl (i, F_GETFL), -1);
      50        TEST_COMPARE (errno, EBADF);
      51      }
      52    for (int i = lowfd; i < half_fd; i++)
      53      TEST_VERIFY (fcntl (i, F_GETFL) > -1);
      54  
      55    /* Create some gaps, close up to a threshold, and check result.  */
      56    xclose (lowfd + 35);
      57    xclose (lowfd + 38);
      58    xclose (lowfd + 42);
      59    xclose (lowfd + 46);
      60  
      61    /* Close half of the descriptors and check result.  */
      62    closefrom (gap);
      63    for (int i = gap + 1; i < maximum_fd; i++)
      64      {
      65        TEST_COMPARE (fcntl (i, F_GETFL), -1);
      66        TEST_COMPARE (errno, EBADF);
      67      }
      68    for (int i = lowfd; i < gap; i++)
      69      TEST_VERIFY (fcntl (i, F_GETFL) > -1);
      70  
      71    /* Close the remmaining but the last one.  */
      72    closefrom (lowfd + 1);
      73    for (int i = lowfd + 1; i <= maximum_fd; i++)
      74      {
      75        TEST_COMPARE (fcntl (i, F_GETFL), -1);
      76        TEST_COMPARE (errno, EBADF);
      77      }
      78    TEST_VERIFY (fcntl (lowfd, F_GETFL) > -1);
      79  
      80    /* Close the last one.  */
      81    closefrom (lowfd);
      82    TEST_COMPARE (fcntl (lowfd, F_GETFL), -1);
      83    TEST_COMPARE (errno, EBADF);
      84  
      85    /* Double check by check the /proc.  */
      86    support_descriptors_check (descrs);
      87    support_descriptors_free (descrs);
      88  
      89    return 0;
      90  }
      91  
      92  /* Check if closefrom works even when no new file descriptors can be
      93     created.  */
      94  static int
      95  closefrom_test_file_desc_limit (void)
      96  {
      97    int max_fd = NFDS;
      98    {
      99      struct rlimit rl;
     100      if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
     101        FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
     102  
     103      max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd);
     104      rl.rlim_cur = max_fd;
     105  
     106      if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
     107        FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
     108    }
     109  
     110    /* Exhauste the file descriptor limit.  */
     111    int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
     112    for (;;)
     113      {
     114        int fd = open ("/dev/null", O_RDONLY, 0600);
     115        if (fd == -1)
     116  	{
     117  	  if (errno != EMFILE)
     118  	    FAIL_EXIT1 ("open: %m");
     119  	  break;
     120  	}
     121        TEST_VERIFY_EXIT (fd < max_fd);
     122      }
     123  
     124    closefrom (lowfd);
     125    for (int i = lowfd; i < NFDS; i++)
     126      {
     127        TEST_COMPARE (fcntl (i, F_GETFL), -1);
     128        TEST_COMPARE (errno, EBADF);
     129      }
     130  
     131    return 0;
     132  }
     133  
     134  static int
     135  do_test (void)
     136  {
     137    closefrom_test ();
     138    closefrom_test_file_desc_limit ();
     139  
     140    return 0;
     141  }
     142  
     143  #include <support/test-driver.c>