1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2006
4 * Copyright (c) 2014 Cyril Hrubis <[email protected]>
5 * Author: Yi Yang <[email protected]>
6 */
7
8 #define _GNU_SOURCE
9
10 #include <errno.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <sys/types.h>
14
15 #include "tst_test.h"
16 #include "lapi/fcntl.h"
17 #include "lapi/tee.h"
18 #include "lapi/splice.h"
19
20 #define TEST_BLOCK_SIZE 1024
21
22 #define TESTFILE1 "tee_test_file_1"
23 #define TESTFILE2 "tee_test_file_2"
24
25 static int fd_in, fd_out;
26 static char buffer[TEST_BLOCK_SIZE];
27
check_file(void)28 static void check_file(void)
29 {
30 int i;
31 char teebuffer[TEST_BLOCK_SIZE];
32
33 fd_out = SAFE_OPEN(TESTFILE2, O_RDONLY);
34 SAFE_READ(1, fd_out, teebuffer, TEST_BLOCK_SIZE);
35
36 for (i = 0; i < TEST_BLOCK_SIZE; i++) {
37 if (buffer[i] != teebuffer[i])
38 break;
39 }
40
41 if (i < TEST_BLOCK_SIZE)
42 tst_res(TFAIL, "Wrong data read from the buffer at %i", i);
43 else
44 tst_res(TPASS, "Written data has been read back correctly");
45
46 SAFE_CLOSE(fd_out);
47 }
48
tee_test(void)49 static void tee_test(void)
50 {
51 int pipe1[2];
52 int pipe2[2];
53 int ret = 0;
54
55 fd_in = SAFE_OPEN(TESTFILE1, O_RDONLY);
56 fd_out = SAFE_OPEN(TESTFILE2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
57
58 SAFE_PIPE(pipe1);
59 SAFE_PIPE(pipe2);
60
61 ret = splice(fd_in, NULL, pipe1[1], NULL, TEST_BLOCK_SIZE, 0);
62 if (ret < 0)
63 tst_brk(TBROK | TERRNO, "splice(fd_in, pipe1) failed");
64
65 ret = tee(pipe1[0], pipe2[1], TEST_BLOCK_SIZE, SPLICE_F_NONBLOCK);
66 if (ret < 0)
67 tst_brk(TBROK | TERRNO, "tee() failed");
68
69 ret = splice(pipe2[0], NULL, fd_out, NULL, TEST_BLOCK_SIZE, 0);
70 if (ret < 0)
71 tst_brk(TBROK | TERRNO, "splice(pipe2, fd_out) failed");
72
73 SAFE_CLOSE(pipe2[0]);
74 SAFE_CLOSE(pipe2[1]);
75 SAFE_CLOSE(pipe1[0]);
76 SAFE_CLOSE(pipe1[1]);
77 SAFE_CLOSE(fd_out);
78 SAFE_CLOSE(fd_in);
79
80 check_file();
81 }
82
setup(void)83 static void setup(void)
84 {
85 int i;
86
87 for (i = 0; i < TEST_BLOCK_SIZE; i++)
88 buffer[i] = i & 0xff;
89
90 fd_in = SAFE_OPEN(TESTFILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
91 SAFE_WRITE(SAFE_WRITE_ALL, fd_in, buffer, TEST_BLOCK_SIZE);
92 SAFE_CLOSE(fd_in);
93 }
94
cleanup(void)95 static void cleanup(void)
96 {
97 if (fd_in > 0)
98 SAFE_CLOSE(fd_in);
99
100 if (fd_out > 0)
101 SAFE_CLOSE(fd_out);
102 }
103
104 static struct tst_test test = {
105 .setup = setup,
106 .cleanup = cleanup,
107 .test_all = tee_test,
108 .needs_tmpdir = 1,
109 };
110