1/* Test that spawn file action functions work without file limit.
2 Copyright (C) 2016-2022 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. */
28static long maxfd;
29
30/* A positive but unused file descriptor, used for testing
31 purposes. */
32static int invalid_fd;
33
34/* Indicate that errors have been encountered. */
35static bool errors;
36
37static posix_spawn_file_actions_t actions;
38
39static void
40one_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 (format: "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 (format: "error: posix_spawn_file_actions_%s (%d):"
57 " unexpected success\n", name, fd);
58 else
59 {
60 errno = ret;
61 printf (format: "error: posix_spawn_file_actions_%s (%d): %m\n", name, fd);
62 }
63 errors = true;
64 }
65}
66
67static void
68all_tests (const char *name, int (*func) (int))
69{
70 one_test (name, func, fd: 0, true);
71 one_test (name, func, fd: invalid_fd, true);
72 one_test (name, func, fd: -1, false);
73 one_test (name, func, fd: -2, false);
74 if (maxfd >= 0)
75 one_test (name, func, fd: maxfd, false);
76}
77
78static int
79addopen (int fd)
80{
81 return posix_spawn_file_actions_addopen
82 (file_actions: &actions, fd: fd, path: "/dev/null", O_RDONLY, mode: 0);
83}
84
85static int
86adddup2 (int fd)
87{
88 return posix_spawn_file_actions_adddup2 (file_actions: &actions, fd: fd, newfd: 1);
89}
90
91static int
92adddup2_reverse (int fd)
93{
94 return posix_spawn_file_actions_adddup2 (file_actions: &actions, fd: 1, newfd: fd);
95}
96
97static int
98addclose (int fd)
99{
100 return posix_spawn_file_actions_addclose (file_actions: &actions, fd: fd);
101}
102
103static void
104all_functions (void)
105{
106 all_tests (name: "addopen", func: addopen);
107 all_tests (name: "adddup2", func: adddup2);
108 all_tests (name: "adddup2", func: adddup2_reverse);
109 all_tests (name: "adddup2", func: addclose);
110}
111
112static int
113do_test (void)
114{
115 /* Try to eliminate the file descriptor limit. */
116 {
117 struct rlimit limit;
118 if (getrlimit (RLIMIT_NOFILE, rlimits: &limit) < 0)
119 {
120 printf (format: "error: getrlimit: %m\n");
121 return 1;
122 }
123 limit.rlim_cur = RLIM_INFINITY;
124 if (setrlimit (RLIMIT_NOFILE, rlimits: &limit) < 0)
125 printf (format: "warning: setrlimit: %m\n");
126 }
127
128 maxfd = sysconf (_SC_OPEN_MAX);
129 printf (format: "info: _SC_OPEN_MAX: %ld\n", maxfd);
130
131 invalid_fd = dup (fd: 0);
132 if (invalid_fd < 0)
133 {
134 printf (format: "error: dup: %m\n");
135 return 1;
136 }
137 if (close (fd: invalid_fd) < 0)
138 {
139 printf (format: "error: close: %m\n");
140 return 1;
141 }
142
143 int ret = posix_spawn_file_actions_init (file_actions: &actions);
144 if (ret != 0)
145 {
146 errno = ret;
147 printf (format: "error: posix_spawn_file_actions_init: %m\n");
148 return 1;
149 }
150
151 all_functions ();
152
153 ret = posix_spawn_file_actions_destroy (file_actions: &actions);
154 if (ret != 0)
155 {
156 errno = ret;
157 printf (format: "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"
166

source code of glibc/posix/tst-posix_spawn-fd.c