1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /*
4 * Copyright (C) 2023-2024 Cyril Hrubis <[email protected]>
5 */
6
7 /*\
8 * [Description]
9 *
10 * Iterate over all kinds of file descriptors and feed splice() with all possible
11 * combinations where at least one file descriptor is invalid. We do expect the
12 * syscall to fail either with EINVAL or EBADF.
13 */
14
15 #define _GNU_SOURCE
16
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19
20 #include "tst_test.h"
21
check_splice(struct tst_fd * fd_in,struct tst_fd * fd_out)22 static void check_splice(struct tst_fd *fd_in, struct tst_fd *fd_out)
23 {
24 /* These combinations just hang since the pipe is empty */
25 if (fd_in->type == TST_FD_PIPE_READ) {
26 switch (fd_out->type) {
27 case TST_FD_FILE:
28 case TST_FD_PIPE_WRITE:
29 case TST_FD_UNIX_SOCK:
30 case TST_FD_INET_SOCK:
31 case TST_FD_MEMFD:
32 return;
33 default:
34 break;
35 }
36 }
37
38 if (fd_out->type == TST_FD_PIPE_WRITE) {
39 switch (fd_in->type) {
40 /* While these combinations succeeed */
41 case TST_FD_DEV_ZERO:
42 case TST_FD_FILE:
43 case TST_FD_PROC_MAPS:
44 case TST_FD_MEMFD:
45 return;
46 /* And this complains about socket not being connected */
47 case TST_FD_INET_SOCK:
48 return;
49 default:
50 break;
51 }
52 }
53
54 const int exp_errnos[] = {EBADF, EINVAL};
55
56 TST_EXP_FAIL2_ARR(splice(fd_in->fd, NULL, fd_out->fd, NULL, 1, 0),
57 exp_errnos, ARRAY_SIZE(exp_errnos), "splice() on %s -> %s",
58 tst_fd_desc(fd_in), tst_fd_desc(fd_out));
59 }
60
verify_splice(void)61 static void verify_splice(void)
62 {
63 TST_FD_FOREACH(fd_in) {
64 tst_res(TINFO, "%s -> ...", tst_fd_desc(&fd_in));
65 TST_FD_FOREACH(fd_out)
66 check_splice(&fd_in, &fd_out);
67 }
68 }
69
70 static struct tst_test test = {
71 .test_all = verify_splice,
72 };
73