]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-fd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
10 #include "path-util.h"
11 #include "process-util.h"
12 #include "random-util.h"
13 #include "string-util.h"
17 static void test_close_many(void) {
19 char name0
[] = "/tmp/test-close-many.XXXXXX";
20 char name1
[] = "/tmp/test-close-many.XXXXXX";
21 char name2
[] = "/tmp/test-close-many.XXXXXX";
23 fds
[0] = mkostemp_safe(name0
);
24 fds
[1] = mkostemp_safe(name1
);
25 fds
[2] = mkostemp_safe(name2
);
29 assert_se(fcntl(fds
[0], F_GETFD
) == -1);
30 assert_se(fcntl(fds
[1], F_GETFD
) == -1);
31 assert_se(fcntl(fds
[2], F_GETFD
) >= 0);
40 static void test_close_nointr(void) {
41 char name
[] = "/tmp/test-test-close_nointr.XXXXXX";
44 fd
= mkostemp_safe(name
);
46 assert_se(close_nointr(fd
) >= 0);
47 assert_se(close_nointr(fd
) < 0);
52 static void test_same_fd(void) {
53 _cleanup_close_pair_
int p
[2] = { -1, -1 };
54 _cleanup_close_
int a
= -1, b
= -1, c
= -1;
56 assert_se(pipe2(p
, O_CLOEXEC
) >= 0);
57 assert_se((a
= fcntl(p
[0], F_DUPFD
, 3)) >= 0);
58 assert_se((b
= open("/dev/null", O_RDONLY
|O_CLOEXEC
)) >= 0);
59 assert_se((c
= fcntl(a
, F_DUPFD
, 3)) >= 0);
61 assert_se(same_fd(p
[0], p
[0]) > 0);
62 assert_se(same_fd(p
[1], p
[1]) > 0);
63 assert_se(same_fd(a
, a
) > 0);
64 assert_se(same_fd(b
, b
) > 0);
66 assert_se(same_fd(a
, p
[0]) > 0);
67 assert_se(same_fd(p
[0], a
) > 0);
68 assert_se(same_fd(c
, p
[0]) > 0);
69 assert_se(same_fd(p
[0], c
) > 0);
70 assert_se(same_fd(a
, c
) > 0);
71 assert_se(same_fd(c
, a
) > 0);
73 assert_se(same_fd(p
[0], p
[1]) == 0);
74 assert_se(same_fd(p
[1], p
[0]) == 0);
75 assert_se(same_fd(p
[0], b
) == 0);
76 assert_se(same_fd(b
, p
[0]) == 0);
77 assert_se(same_fd(p
[1], a
) == 0);
78 assert_se(same_fd(a
, p
[1]) == 0);
79 assert_se(same_fd(p
[1], b
) == 0);
80 assert_se(same_fd(b
, p
[1]) == 0);
82 assert_se(same_fd(a
, b
) == 0);
83 assert_se(same_fd(b
, a
) == 0);
86 static void test_open_serialization_fd(void) {
87 _cleanup_close_
int fd
= -1;
89 fd
= open_serialization_fd("test");
92 assert_se(write(fd
, "test\n", 5) == 5);
95 static void test_acquire_data_fd_one(unsigned flags
) {
96 char wbuffer
[196*1024 - 7];
97 char rbuffer
[sizeof(wbuffer
)];
100 fd
= acquire_data_fd("foo", 3, flags
);
104 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 3);
105 assert_se(streq(rbuffer
, "foo"));
109 fd
= acquire_data_fd("", 0, flags
);
113 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 0);
114 assert_se(streq(rbuffer
, ""));
118 random_bytes(wbuffer
, sizeof(wbuffer
));
120 fd
= acquire_data_fd(wbuffer
, sizeof(wbuffer
), flags
);
124 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == sizeof(rbuffer
));
125 assert_se(memcmp(rbuffer
, wbuffer
, sizeof(rbuffer
)) == 0);
130 static void test_acquire_data_fd(void) {
132 test_acquire_data_fd_one(0);
133 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
);
134 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
);
135 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
);
136 test_acquire_data_fd_one(ACQUIRE_NO_PIPE
);
137 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_PIPE
);
138 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
139 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
140 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
|ACQUIRE_NO_TMPFILE
);
143 static void test_fd_move_above_stdio(void) {
144 int original_stdin
, new_fd
;
146 original_stdin
= fcntl(0, F_DUPFD
, 3);
147 assert_se(original_stdin
>= 3);
148 assert_se(close_nointr(0) != EBADF
);
150 new_fd
= open("/dev/null", O_RDONLY
);
151 assert_se(new_fd
== 0);
153 new_fd
= fd_move_above_stdio(new_fd
);
154 assert_se(new_fd
>= 3);
156 assert_se(dup(original_stdin
) == 0);
157 assert_se(close_nointr(original_stdin
) != EBADF
);
158 assert_se(close_nointr(new_fd
) != EBADF
);
161 static void test_rearrange_stdio(void) {
165 r
= safe_fork("rearrange", FORK_WAIT
|FORK_LOG
, &pid
);
169 _cleanup_free_
char *path
= NULL
;
174 safe_close(STDERR_FILENO
); /* Let's close an fd < 2, to make it more interesting */
176 assert_se(rearrange_stdio(-1, -1, -1) >= 0);
178 assert_se(fd_get_path(STDIN_FILENO
, &path
) >= 0);
179 assert_se(path_equal(path
, "/dev/null"));
182 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
183 assert_se(path_equal(path
, "/dev/null"));
186 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
187 assert_se(path_equal(path
, "/dev/null"));
190 safe_close(STDIN_FILENO
);
191 safe_close(STDOUT_FILENO
);
192 safe_close(STDERR_FILENO
);
196 assert_se(pipe(pair
) >= 0);
197 assert_se(pair
[0] == 0);
198 assert_se(pair
[1] == 1);
199 assert_se(fd_move_above_stdio(0) == 3);
201 assert_se(open("/dev/full", O_WRONLY
|O_CLOEXEC
) == 0);
202 assert_se(acquire_data_fd("foobar", 6, 0) == 2);
204 assert_se(rearrange_stdio(2, 0, 1) >= 0);
206 assert_se(write(1, "x", 1) < 0 && errno
== ENOSPC
);
207 assert_se(write(2, "z", 1) == 1);
208 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
209 assert_se(buffer
[0] == 'z');
210 assert_se(read(0, buffer
, sizeof(buffer
)) == 6);
211 assert_se(memcmp(buffer
, "foobar", 6) == 0);
213 assert_se(rearrange_stdio(-1, 1, 2) >= 0);
214 assert_se(write(1, "a", 1) < 0 && errno
== ENOSPC
);
215 assert_se(write(2, "y", 1) == 1);
216 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
217 assert_se(buffer
[0] == 'y');
219 assert_se(fd_get_path(0, &path
) >= 0);
220 assert_se(path_equal(path
, "/dev/null"));
227 static void assert_equal_fd(int fd1
, int fd2
) {
230 uint8_t a
[4096], b
[4096];
233 x
= read(fd1
, a
, sizeof(a
));
236 y
= read(fd2
, b
, sizeof(b
));
244 assert(memcmp(a
, b
, x
) == 0);
248 static void test_fd_duplicate_data_fd(void) {
249 _cleanup_close_
int fd1
= -1, fd2
= -1;
250 _cleanup_(close_pairp
) int sfd
[2] = { -1, -1 };
251 _cleanup_(sigkill_waitp
) pid_t pid
= -1;
255 fd1
= open("/etc/fstab", O_RDONLY
|O_CLOEXEC
);
258 fd2
= fd_duplicate_data_fd(fd1
);
261 assert_se(lseek(fd1
, 0, SEEK_SET
) == 0);
262 assert_equal_fd(fd1
, fd2
);
265 fd1
= safe_close(fd1
);
266 fd2
= safe_close(fd2
);
268 fd1
= acquire_data_fd("hallo", 6, 0);
271 fd2
= fd_duplicate_data_fd(fd1
);
275 fd1
= acquire_data_fd("hallo", 6, 0);
278 assert_equal_fd(fd1
, fd2
);
280 fd1
= safe_close(fd1
);
281 fd2
= safe_close(fd2
);
283 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0, sfd
) >= 0);
285 r
= safe_fork("(sd-pipe)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
291 sfd
[0] = safe_close(sfd
[0]);
293 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++)
294 assert_se(write(sfd
[1], &i
, sizeof(i
)) == sizeof(i
));
296 sfd
[1] = safe_close(sfd
[1]);
301 sfd
[1] = safe_close(sfd
[1]);
303 fd2
= fd_duplicate_data_fd(sfd
[0]);
306 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++) {
307 assert_se(read(fd2
, &j
, sizeof(j
)) == sizeof(j
));
311 assert_se(read(fd2
, &j
, sizeof(j
)) == 0);
314 static void test_read_nr_open(void) {
315 log_info("nr-open: %i", read_nr_open());
318 int main(int argc
, char *argv
[]) {
320 test_setup_logging(LOG_DEBUG
);
325 test_open_serialization_fd();
326 test_acquire_data_fd();
327 test_fd_move_above_stdio();
328 test_rearrange_stdio();
329 test_fd_duplicate_data_fd();