(root)/
glibc-2.38/
posix/
tst-posix_spawn-fd.c
       1  /* Test that spawn file action functions work without file limit.
       2     Copyright (C) 2016-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 <spawn.h>
      22  #include <stdbool.h>
      23  #include <stdio.h>
      24  #include <sys/resource.h>
      25  #include <unistd.h>
      26  
      27  /* _SC_OPEN_MAX value.  */
      28  static long maxfd;
      29  
      30  /* A positive but unused file descriptor, used for testing
      31     purposes.  */
      32  static int invalid_fd;
      33  
      34  /* Indicate that errors have been encountered.  */
      35  static bool errors;
      36  
      37  static posix_spawn_file_actions_t actions;
      38  
      39  static void
      40  one_test (const char *name, int (*func) (int), int fd,
      41            bool expect_success)
      42  {
      43    int ret = func (fd);
      44    if (expect_success)
      45      {
      46        if (ret != 0)
      47          {
      48            errno = ret;
      49            printf ("error: posix_spawn_file_actions_%s (%d): %m\n", name, fd);
      50            errors = true;
      51          }
      52      }
      53    else if (ret != EBADF)
      54      {
      55        if (ret == 0)
      56            printf ("error: posix_spawn_file_actions_%s (%d):"
      57                    " unexpected success\n", name, fd);
      58        else
      59          {
      60            errno = ret;
      61            printf ("error: posix_spawn_file_actions_%s (%d): %m\n", name, fd);
      62          }
      63        errors = true;
      64      }
      65  }
      66  
      67  static void
      68  all_tests (const char *name, int (*func) (int))
      69  {
      70    one_test (name, func, 0, true);
      71    one_test (name, func, invalid_fd, true);
      72    one_test (name, func, -1, false);
      73    one_test (name, func, -2, false);
      74    if (maxfd >= 0)
      75      one_test (name, func, maxfd, false);
      76  }
      77  
      78  static int
      79  addopen (int fd)
      80  {
      81    return posix_spawn_file_actions_addopen
      82      (&actions, fd, "/dev/null", O_RDONLY, 0);
      83  }
      84  
      85  static int
      86  adddup2 (int fd)
      87  {
      88    return posix_spawn_file_actions_adddup2 (&actions, fd, 1);
      89  }
      90  
      91  static int
      92  adddup2_reverse (int fd)
      93  {
      94    return posix_spawn_file_actions_adddup2 (&actions, 1, fd);
      95  }
      96  
      97  static int
      98  addclose (int fd)
      99  {
     100    return posix_spawn_file_actions_addclose (&actions, fd);
     101  }
     102  
     103  static void
     104  all_functions (void)
     105  {
     106    all_tests ("addopen", addopen);
     107    all_tests ("adddup2", adddup2);
     108    all_tests ("adddup2", adddup2_reverse);
     109    all_tests ("adddup2", addclose);
     110  }
     111  
     112  static int
     113  do_test (void)
     114  {
     115    /* Try to eliminate the file descriptor limit.  */
     116    {
     117      struct rlimit limit;
     118      if (getrlimit (RLIMIT_NOFILE, &limit) < 0)
     119        {
     120          printf ("error: getrlimit: %m\n");
     121          return 1;
     122        }
     123      limit.rlim_cur = RLIM_INFINITY;
     124      if (setrlimit (RLIMIT_NOFILE, &limit) < 0)
     125        printf ("warning: setrlimit: %m\n");
     126    }
     127  
     128    maxfd = sysconf (_SC_OPEN_MAX);
     129    printf ("info: _SC_OPEN_MAX: %ld\n", maxfd);
     130  
     131    invalid_fd = dup (0);
     132    if (invalid_fd < 0)
     133      {
     134        printf ("error: dup: %m\n");
     135        return 1;
     136      }
     137    if (close (invalid_fd) < 0)
     138      {
     139        printf ("error: close: %m\n");
     140        return 1;
     141      }
     142  
     143    int ret = posix_spawn_file_actions_init (&actions);
     144    if (ret != 0)
     145      {
     146        errno = ret;
     147        printf ("error: posix_spawn_file_actions_init: %m\n");
     148        return 1;
     149      }
     150  
     151    all_functions ();
     152  
     153    ret = posix_spawn_file_actions_destroy (&actions);
     154    if (ret != 0)
     155      {
     156        errno = ret;
     157        printf ("error: posix_spawn_file_actions_destroy: %m\n");
     158        return 1;
     159      }
     160  
     161    return errors;
     162  }
     163  
     164  #define TEST_FUNCTION do_test ()
     165  #include "../test-skeleton.c"