(root)/
glibc-2.38/
support/
tst-support-open-dev-null-range.c
       1  /* Tests for support_open_dev_null_range.
       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 <dirent.h>
      21  #include <fcntl.h>
      22  #include <limits.h>
      23  #include <support/check.h>
      24  #include <support/support.h>
      25  #include <support/xunistd.h>
      26  #include <sys/resource.h>
      27  #include <stdlib.h>
      28  
      29  #ifndef PATH_MAX
      30  # define PATH_MAX 1024
      31  #endif
      32  
      33  #include <stdio.h>
      34  
      35  static void
      36  check_path (int fd)
      37  {
      38    char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd);
      39    char file_path[PATH_MAX];
      40    ssize_t file_path_length
      41      = readlink (proc_fd_path, file_path, sizeof (file_path));
      42    if (file_path_length < 0)
      43      FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path,
      44  		sizeof (file_path));
      45  
      46    free (proc_fd_path);
      47    file_path[file_path_length] = '\0';
      48    TEST_COMPARE_STRING (file_path, "/dev/null");
      49  }
      50  
      51  static int
      52  number_of_opened_files (void)
      53  {
      54    DIR *fds = opendir ("/proc/self/fd");
      55    if (fds == NULL)
      56      FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m");
      57  
      58    int r = 0;
      59    while (true)
      60      {
      61        errno = 0;
      62        struct dirent64 *e = readdir64 (fds);
      63        if (e == NULL)
      64          {
      65            if (errno != 0)
      66              FAIL_EXIT1 ("readdir: %m");
      67            break;
      68          }
      69  
      70        if (e->d_name[0] == '.')
      71          continue;
      72  
      73        char *endptr;
      74        long int fd = strtol (e->d_name, &endptr, 10);
      75        if (*endptr != '\0' || fd < 0 || fd > INT_MAX)
      76          FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s",
      77                      e->d_name);
      78  
      79        /* Skip the descriptor which is used to enumerate the
      80           descriptors.  */
      81        if (fd == dirfd (fds))
      82          continue;
      83  
      84        r = r + 1;
      85      }
      86  
      87    closedir (fds);
      88  
      89    return r;
      90  }
      91  
      92  static int
      93  do_test (void)
      94  {
      95    const int nfds1 = 8;
      96    int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600);
      97    for (int i = 0; i < nfds1; i++)
      98      {
      99        TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1);
     100        check_path (lowfd + i);
     101      }
     102  
     103    /* create some gaps.  */
     104    xclose (lowfd + 1);
     105    xclose (lowfd + 5);
     106    xclose (lowfd + 6);
     107  
     108    const int nfds2 = 16;
     109    int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600);
     110    for (int i = 0; i < nfds2; i++)
     111      {
     112        TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1);
     113        check_path (lowfd2 + i);
     114      }
     115  
     116    /* Decrease the maximum number of files.  */
     117    {
     118      struct rlimit rl;
     119      if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
     120        FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
     121  
     122      rl.rlim_cur = number_of_opened_files ();
     123  
     124      if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
     125        FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
     126    }
     127  
     128    const int nfds3 = 16;
     129    int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600);
     130    for (int i = 0; i < nfds3; i++)
     131      {
     132        TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1);
     133        check_path (lowfd3 + i);
     134      }
     135  
     136    /* create a lot of gaps to trigger the range extension.  */
     137    xclose (lowfd3 + 1);
     138    xclose (lowfd3 + 3);
     139    xclose (lowfd3 + 5);
     140    xclose (lowfd3 + 7);
     141    xclose (lowfd3 + 9);
     142    xclose (lowfd3 + 11);
     143    xclose (lowfd3 + 13);
     144  
     145    const int nfds4 = 16;
     146    int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600);
     147    for (int i = 0; i < nfds4; i++)
     148      {
     149        TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1);
     150        check_path (lowfd4 + i);
     151      }
     152  
     153    return 0;
     154  }
     155  
     156  #include <support/test-driver.c>