xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/splice/splice07.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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