• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) International Business Machines Corp., 2006
4  * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
5  * Author: Yi Yang <yyangcdl@cn.ibm.com>
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 	if (tst_fs_type(".") == TST_NFS_MAGIC) {
88 		if ((tst_kvercmp(2, 6, 32)) < 0)
89 			tst_brk(TCONF, "Cannot do tee on a file"
90 				" on NFS filesystem before 2.6.32");
91 	}
92 
93 	for (i = 0; i < TEST_BLOCK_SIZE; i++)
94 		buffer[i] = i & 0xff;
95 
96 	fd_in = SAFE_OPEN(TESTFILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
97 	SAFE_WRITE(1, fd_in, buffer, TEST_BLOCK_SIZE);
98 	SAFE_CLOSE(fd_in);
99 }
100 
cleanup(void)101 static void cleanup(void)
102 {
103 	if (fd_in > 0)
104 		SAFE_CLOSE(fd_in);
105 
106 	if (fd_out > 0)
107 		SAFE_CLOSE(fd_out);
108 }
109 
110 static struct tst_test test = {
111 	.setup = setup,
112 	.cleanup = cleanup,
113 	.test_all = tee_test,
114 	.needs_tmpdir = 1,
115 	.min_kver = "2.6.17",
116 };
117