]>
git.proxmox.com Git - systemd.git/blob - src/test/test-fd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
10 #include "memory-util.h"
11 #include "path-util.h"
12 #include "process-util.h"
13 #include "random-util.h"
14 #include "serialize.h"
15 #include "string-util.h"
17 #include "tmpfile-util.h"
19 static void test_close_many(void) {
21 char name0
[] = "/tmp/test-close-many.XXXXXX";
22 char name1
[] = "/tmp/test-close-many.XXXXXX";
23 char name2
[] = "/tmp/test-close-many.XXXXXX";
25 fds
[0] = mkostemp_safe(name0
);
26 fds
[1] = mkostemp_safe(name1
);
27 fds
[2] = mkostemp_safe(name2
);
31 assert_se(fcntl(fds
[0], F_GETFD
) == -1);
32 assert_se(fcntl(fds
[1], F_GETFD
) == -1);
33 assert_se(fcntl(fds
[2], F_GETFD
) >= 0);
42 static void test_close_nointr(void) {
43 char name
[] = "/tmp/test-test-close_nointr.XXXXXX";
46 fd
= mkostemp_safe(name
);
48 assert_se(close_nointr(fd
) >= 0);
49 assert_se(close_nointr(fd
) < 0);
54 static void test_same_fd(void) {
55 _cleanup_close_pair_
int p
[2] = { -1, -1 };
56 _cleanup_close_
int a
= -1, b
= -1, c
= -1;
58 assert_se(pipe2(p
, O_CLOEXEC
) >= 0);
59 assert_se((a
= fcntl(p
[0], F_DUPFD
, 3)) >= 0);
60 assert_se((b
= open("/dev/null", O_RDONLY
|O_CLOEXEC
)) >= 0);
61 assert_se((c
= fcntl(a
, F_DUPFD
, 3)) >= 0);
63 assert_se(same_fd(p
[0], p
[0]) > 0);
64 assert_se(same_fd(p
[1], p
[1]) > 0);
65 assert_se(same_fd(a
, a
) > 0);
66 assert_se(same_fd(b
, b
) > 0);
68 assert_se(same_fd(a
, p
[0]) > 0);
69 assert_se(same_fd(p
[0], a
) > 0);
70 assert_se(same_fd(c
, p
[0]) > 0);
71 assert_se(same_fd(p
[0], c
) > 0);
72 assert_se(same_fd(a
, c
) > 0);
73 assert_se(same_fd(c
, a
) > 0);
75 assert_se(same_fd(p
[0], p
[1]) == 0);
76 assert_se(same_fd(p
[1], p
[0]) == 0);
77 assert_se(same_fd(p
[0], b
) == 0);
78 assert_se(same_fd(b
, p
[0]) == 0);
79 assert_se(same_fd(p
[1], a
) == 0);
80 assert_se(same_fd(a
, p
[1]) == 0);
81 assert_se(same_fd(p
[1], b
) == 0);
82 assert_se(same_fd(b
, p
[1]) == 0);
84 assert_se(same_fd(a
, b
) == 0);
85 assert_se(same_fd(b
, a
) == 0);
88 static void test_open_serialization_fd(void) {
89 _cleanup_close_
int fd
= -1;
91 fd
= open_serialization_fd("test");
94 assert_se(write(fd
, "test\n", 5) == 5);
97 static void test_acquire_data_fd_one(unsigned flags
) {
98 char wbuffer
[196*1024 - 7];
99 char rbuffer
[sizeof(wbuffer
)];
102 fd
= acquire_data_fd("foo", 3, flags
);
106 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 3);
107 assert_se(streq(rbuffer
, "foo"));
111 fd
= acquire_data_fd("", 0, flags
);
115 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == 0);
116 assert_se(streq(rbuffer
, ""));
120 random_bytes(wbuffer
, sizeof(wbuffer
));
122 fd
= acquire_data_fd(wbuffer
, sizeof(wbuffer
), flags
);
126 assert_se(read(fd
, rbuffer
, sizeof(rbuffer
)) == sizeof(rbuffer
));
127 assert_se(memcmp(rbuffer
, wbuffer
, sizeof(rbuffer
)) == 0);
132 static void test_acquire_data_fd(void) {
134 test_acquire_data_fd_one(0);
135 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
);
136 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
);
137 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
);
138 test_acquire_data_fd_one(ACQUIRE_NO_PIPE
);
139 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_PIPE
);
140 test_acquire_data_fd_one(ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
141 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
);
142 test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL
|ACQUIRE_NO_MEMFD
|ACQUIRE_NO_PIPE
|ACQUIRE_NO_TMPFILE
);
145 static void test_fd_move_above_stdio(void) {
146 int original_stdin
, new_fd
;
148 original_stdin
= fcntl(0, F_DUPFD
, 3);
149 assert_se(original_stdin
>= 3);
150 assert_se(close_nointr(0) != EBADF
);
152 new_fd
= open("/dev/null", O_RDONLY
);
153 assert_se(new_fd
== 0);
155 new_fd
= fd_move_above_stdio(new_fd
);
156 assert_se(new_fd
>= 3);
158 assert_se(dup(original_stdin
) == 0);
159 assert_se(close_nointr(original_stdin
) != EBADF
);
160 assert_se(close_nointr(new_fd
) != EBADF
);
163 static void test_rearrange_stdio(void) {
167 r
= safe_fork("rearrange", FORK_WAIT
|FORK_LOG
, &pid
);
171 _cleanup_free_
char *path
= NULL
;
176 safe_close(STDERR_FILENO
); /* Let's close an fd < 2, to make it more interesting */
178 assert_se(rearrange_stdio(-1, -1, -1) >= 0);
180 assert_se(fd_get_path(STDIN_FILENO
, &path
) >= 0);
181 assert_se(path_equal(path
, "/dev/null"));
184 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
185 assert_se(path_equal(path
, "/dev/null"));
188 assert_se(fd_get_path(STDOUT_FILENO
, &path
) >= 0);
189 assert_se(path_equal(path
, "/dev/null"));
192 safe_close(STDIN_FILENO
);
193 safe_close(STDOUT_FILENO
);
194 safe_close(STDERR_FILENO
);
198 assert_se(pipe(pair
) >= 0);
199 assert_se(pair
[0] == 0);
200 assert_se(pair
[1] == 1);
201 assert_se(fd_move_above_stdio(0) == 3);
203 assert_se(open("/dev/full", O_WRONLY
|O_CLOEXEC
) == 0);
204 assert_se(acquire_data_fd("foobar", 6, 0) == 2);
206 assert_se(rearrange_stdio(2, 0, 1) >= 0);
208 assert_se(write(1, "x", 1) < 0 && errno
== ENOSPC
);
209 assert_se(write(2, "z", 1) == 1);
210 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
211 assert_se(buffer
[0] == 'z');
212 assert_se(read(0, buffer
, sizeof(buffer
)) == 6);
213 assert_se(memcmp(buffer
, "foobar", 6) == 0);
215 assert_se(rearrange_stdio(-1, 1, 2) >= 0);
216 assert_se(write(1, "a", 1) < 0 && errno
== ENOSPC
);
217 assert_se(write(2, "y", 1) == 1);
218 assert_se(read(3, buffer
, sizeof(buffer
)) == 1);
219 assert_se(buffer
[0] == 'y');
221 assert_se(fd_get_path(0, &path
) >= 0);
222 assert_se(path_equal(path
, "/dev/null"));
229 static void assert_equal_fd(int fd1
, int fd2
) {
232 uint8_t a
[4096], b
[4096];
235 x
= read(fd1
, a
, sizeof(a
));
238 y
= read(fd2
, b
, sizeof(b
));
246 assert(memcmp(a
, b
, x
) == 0);
250 static void test_fd_duplicate_data_fd(void) {
251 _cleanup_close_
int fd1
= -1, fd2
= -1;
252 _cleanup_(close_pairp
) int sfd
[2] = { -1, -1 };
253 _cleanup_(sigkill_waitp
) pid_t pid
= -1;
257 fd1
= open("/etc/fstab", O_RDONLY
|O_CLOEXEC
);
260 fd2
= fd_duplicate_data_fd(fd1
);
263 assert_se(lseek(fd1
, 0, SEEK_SET
) == 0);
264 assert_equal_fd(fd1
, fd2
);
267 fd1
= safe_close(fd1
);
268 fd2
= safe_close(fd2
);
270 fd1
= acquire_data_fd("hallo", 6, 0);
273 fd2
= fd_duplicate_data_fd(fd1
);
277 fd1
= acquire_data_fd("hallo", 6, 0);
280 assert_equal_fd(fd1
, fd2
);
282 fd1
= safe_close(fd1
);
283 fd2
= safe_close(fd2
);
285 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0, sfd
) >= 0);
287 r
= safe_fork("(sd-pipe)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
293 sfd
[0] = safe_close(sfd
[0]);
295 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++)
296 assert_se(write(sfd
[1], &i
, sizeof(i
)) == sizeof(i
));
298 sfd
[1] = safe_close(sfd
[1]);
303 sfd
[1] = safe_close(sfd
[1]);
305 fd2
= fd_duplicate_data_fd(sfd
[0]);
308 for (i
= 0; i
< 1536*1024 / sizeof(uint64_t); i
++) {
309 assert_se(read(fd2
, &j
, sizeof(j
)) == sizeof(j
));
313 assert_se(read(fd2
, &j
, sizeof(j
)) == 0);
316 static void test_read_nr_open(void) {
317 log_info("nr-open: %i", read_nr_open());
320 int main(int argc
, char *argv
[]) {
322 test_setup_logging(LOG_DEBUG
);
327 test_open_serialization_fd();
328 test_acquire_data_fd();
329 test_fd_move_above_stdio();
330 test_rearrange_stdio();
331 test_fd_duplicate_data_fd();