]>
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"
16 static void test_close_many(void) {
18 char name0
[] = "/tmp/test-close-many.XXXXXX";
19 char name1
[] = "/tmp/test-close-many.XXXXXX";
20 char name2
[] = "/tmp/test-close-many.XXXXXX";
22 fds
[0] = mkostemp_safe(name0
);
23 fds
[1] = mkostemp_safe(name1
);
24 fds
[2] = mkostemp_safe(name2
);
28 assert_se(fcntl(fds
[0], F_GETFD
) == -1);
29 assert_se(fcntl(fds
[1], F_GETFD
) == -1);
30 assert_se(fcntl(fds
[2], F_GETFD
) >= 0);
39 static void test_close_nointr(void) {
40 char name
[] = "/tmp/test-test-close_nointr.XXXXXX";
43 fd
= mkostemp_safe(name
);
45 assert_se(close_nointr(fd
) >= 0);
46 assert_se(close_nointr(fd
) < 0);
51 static void test_same_fd(void) {
52 _cleanup_close_pair_
int p
[2] = { -1, -1 };
53 _cleanup_close_
int a
= -1, b
= -1, c
= -1;
55 assert_se(pipe2(p
, O_CLOEXEC
) >= 0);
56 assert_se((a
= fcntl(p
[0], F_DUPFD
, 3)) >= 0);
57 assert_se((b
= open("/dev/null", O_RDONLY
|O_CLOEXEC
)) >= 0);
58 assert_se((c
= fcntl(a
, F_DUPFD
, 3)) >= 0);
60 assert_se(same_fd(p
[0], p
[0]) > 0);
61 assert_se(same_fd(p
[1], p
[1]) > 0);
62 assert_se(same_fd(a
, a
) > 0);
63 assert_se(same_fd(b
, b
) > 0);
65 assert_se(same_fd(a
, p
[0]) > 0);
66 assert_se(same_fd(p
[0], a
) > 0);
67 assert_se(same_fd(c
, p
[0]) > 0);
68 assert_se(same_fd(p
[0], c
) > 0);
69 assert_se(same_fd(a
, c
) > 0);
70 assert_se(same_fd(c
, a
) > 0);
72 assert_se(same_fd(p
[0], p
[1]) == 0);
73 assert_se(same_fd(p
[1], p
[0]) == 0);
74 assert_se(same_fd(p
[0], b
) == 0);
75 assert_se(same_fd(b
, p
[0]) == 0);
76 assert_se(same_fd(p
[1], a
) == 0);
77 assert_se(same_fd(a
, p
[1]) == 0);
78 assert_se(same_fd(p
[1], b
) == 0);
79 assert_se(same_fd(b
, p
[1]) == 0);
81 assert_se(same_fd(a
, b
) == 0);
82 assert_se(same_fd(b
, a
) == 0);
85 static void test_open_serialization_fd(void) {
86 _cleanup_close_
int fd
= -1;
88 fd
= open_serialization_fd("test");
91 assert_se(write(fd
, "test\n", 5) == 5);
94 static void test_acquire_data_fd_one(unsigned flags
) {
95 char wbuffer
[196*1024 - 7];
96 char rbuffer
[sizeof(wbuffer
)];
99 fd
= acquire_data_fd("foo", 3, flags
);
103 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 3);
104 assert_se(streq(rbuffer
, "foo"));
108 fd
= acquire_data_fd("", 0, flags
);
112 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 0);
113 assert_se(streq(rbuffer
, ""));
117 random_bytes(wbuffer
, sizeof(wbuffer
));
119 fd
= acquire_data_fd(wbuffer
, sizeof(wbuffer
), flags
);
123 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == sizeof(rbuffer
));
124 assert_se(memcmp(rbuffer
, wbuffer
, sizeof(rbuffer
)) == 0);
129 static void test_acquire_data_fd(void) {
131 test_acquire_data_fd_one(0);
132 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
);
133 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
);
134 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
);
135 test_acquire_data_fd_one(ACQUIRE_NO_PIPE
);
136 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_PIPE
);
137 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
138 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
139 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
|ACQUIRE_NO_TMPFILE
);
142 static void test_fd_move_above_stdio(void) {
143 int original_stdin
, new_fd
;
145 original_stdin
= fcntl(0, F_DUPFD
, 3);
146 assert_se(original_stdin
>= 3);
147 assert_se(close_nointr(0) != EBADF
);
149 new_fd
= open("/dev/null", O_RDONLY
);
150 assert_se(new_fd
== 0);
152 new_fd
= fd_move_above_stdio(new_fd
);
153 assert_se(new_fd
>= 3);
155 assert_se(dup(original_stdin
) == 0);
156 assert_se(close_nointr(original_stdin
) != EBADF
);
157 assert_se(close_nointr(new_fd
) != EBADF
);
160 static void test_rearrange_stdio(void) {
164 r
= safe_fork("rearrange", FORK_WAIT
|FORK_LOG
, &pid
);
168 _cleanup_free_
char *path
= NULL
;
173 safe_close(STDERR_FILENO
); /* Let's close an fd < 2, to make it more interesting */
175 assert_se(rearrange_stdio(-1, -1, -1) >= 0);
177 assert_se(fd_get_path(STDIN_FILENO
, &path
) >= 0);
178 assert_se(path_equal(path
, "/dev/null"));
181 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
182 assert_se(path_equal(path
, "/dev/null"));
185 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
186 assert_se(path_equal(path
, "/dev/null"));
189 safe_close(STDIN_FILENO
);
190 safe_close(STDOUT_FILENO
);
191 safe_close(STDERR_FILENO
);
195 assert_se(pipe(pair
) >= 0);
196 assert_se(pair
[0] == 0);
197 assert_se(pair
[1] == 1);
198 assert_se(fd_move_above_stdio(0) == 3);
200 assert_se(open("/dev/full", O_WRONLY
|O_CLOEXEC
) == 0);
201 assert_se(acquire_data_fd("foobar", 6, 0) == 2);
203 assert_se(rearrange_stdio(2, 0, 1) >= 0);
205 assert_se(write(1, "x", 1) < 0 && errno
== ENOSPC
);
206 assert_se(write(2, "z", 1) == 1);
207 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
208 assert_se(buffer
[0] == 'z');
209 assert_se(read(0, buffer
, sizeof(buffer
)) == 6);
210 assert_se(memcmp(buffer
, "foobar", 6) == 0);
212 assert_se(rearrange_stdio(-1, 1, 2) >= 0);
213 assert_se(write(1, "a", 1) < 0 && errno
== ENOSPC
);
214 assert_se(write(2, "y", 1) == 1);
215 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
216 assert_se(buffer
[0] == 'y');
218 assert_se(fd_get_path(0, &path
) >= 0);
219 assert_se(path_equal(path
, "/dev/null"));
226 static void assert_equal_fd(int fd1
, int fd2
) {
229 uint8_t a
[4096], b
[4096];
232 x
= read(fd1
, a
, sizeof(a
));
235 y
= read(fd2
, b
, sizeof(b
));
243 assert(memcmp(a
, b
, x
) == 0);
247 static void test_fd_duplicate_data_fd(void) {
248 _cleanup_close_
int fd1
= -1, fd2
= -1;
249 _cleanup_(close_pairp
) int sfd
[2] = { -1, -1 };
250 _cleanup_(sigkill_waitp
) pid_t pid
= -1;
254 fd1
= open("/etc/fstab", O_RDONLY
|O_CLOEXEC
);
257 fd2
= fd_duplicate_data_fd(fd1
);
260 assert_se(lseek(fd1
, 0, SEEK_SET
) == 0);
261 assert_equal_fd(fd1
, fd2
);
264 fd1
= safe_close(fd1
);
265 fd2
= safe_close(fd2
);
267 fd1
= acquire_data_fd("hallo", 6, 0);
270 fd2
= fd_duplicate_data_fd(fd1
);
274 fd1
= acquire_data_fd("hallo", 6, 0);
277 assert_equal_fd(fd1
, fd2
);
279 fd1
= safe_close(fd1
);
280 fd2
= safe_close(fd2
);
282 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0, sfd
) >= 0);
284 r
= safe_fork("(sd-pipe)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
290 sfd
[0] = safe_close(sfd
[0]);
292 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++)
293 assert_se(write(sfd
[1], &i
, sizeof(i
)) == sizeof(i
));
295 sfd
[1] = safe_close(sfd
[1]);
300 sfd
[1] = safe_close(sfd
[1]);
302 fd2
= fd_duplicate_data_fd(sfd
[0]);
305 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++) {
306 assert_se(read(fd2
, &j
, sizeof(j
)) == sizeof(j
));
310 assert_se(read(fd2
, &j
, sizeof(j
)) == 0);
313 static void test_read_nr_open(void) {
314 log_info("nr-open: %i", read_nr_open());
317 int main(int argc
, char *argv
[]) {
319 log_set_max_level(LOG_DEBUG
);
324 test_open_serialization_fd();
325 test_acquire_data_fd();
326 test_fd_move_above_stdio();
327 test_rearrange_stdio();
328 test_fd_duplicate_data_fd();