• 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 #include <fcntl.h>
15 
16 #include "tst_test.h"
17 #include "lapi/fcntl.h"
18 #include "lapi/tee.h"
19 #include "lapi/splice.h"
20 
21 #define TEST_BLOCK_SIZE 1024
22 
23 #define TESTFILE1 "tee_test_file_1"
24 #define TESTFILE2 "tee_test_file_2"
25 
26 static int fd_in, fd_out;
27 static char buffer[TEST_BLOCK_SIZE];
28 
check_file(void)29 static void check_file(void)
30 {
31 	int i;
32 	char teebuffer[TEST_BLOCK_SIZE];
33 
34 	fd_out = SAFE_OPEN(TESTFILE2, O_RDONLY);
35 	SAFE_READ(1, fd_out, teebuffer, TEST_BLOCK_SIZE);
36 
37 	for (i = 0; i < TEST_BLOCK_SIZE; i++) {
38 		if (buffer[i] != teebuffer[i])
39 			break;
40 	}
41 
42 	if (i < TEST_BLOCK_SIZE)
43 		tst_res(TFAIL, "Wrong data read from the buffer at %i", i);
44 	else
45 		tst_res(TPASS, "Written data has been read back correctly");
46 
47 	SAFE_CLOSE(fd_out);
48 }
49 
tee_test(void)50 static void tee_test(void)
51 {
52 	int pipe1[2];
53 	int pipe2[2];
54 	int ret = 0;
55 
56 	fd_in = SAFE_OPEN(TESTFILE1, O_RDONLY);
57 	fd_out = SAFE_OPEN(TESTFILE2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
58 
59 	SAFE_PIPE(pipe1);
60 	SAFE_PIPE(pipe2);
61 
62 	ret = splice(fd_in, NULL, pipe1[1], NULL, TEST_BLOCK_SIZE, 0);
63 	if (ret < 0)
64 		tst_brk(TBROK | TERRNO, "splice(fd_in, pipe1) failed");
65 
66 	ret = tee(pipe1[0], pipe2[1], TEST_BLOCK_SIZE, SPLICE_F_NONBLOCK);
67 	if (ret < 0)
68 		tst_brk(TBROK | TERRNO, "tee() failed");
69 
70 	ret = splice(pipe2[0], NULL, fd_out, NULL, TEST_BLOCK_SIZE, 0);
71 	if (ret < 0)
72 		tst_brk(TBROK | TERRNO, "splice(pipe2, fd_out) failed");
73 
74 	SAFE_CLOSE(pipe2[0]);
75 	SAFE_CLOSE(pipe2[1]);
76 	SAFE_CLOSE(pipe1[0]);
77 	SAFE_CLOSE(pipe1[1]);
78 	SAFE_CLOSE(fd_out);
79 	SAFE_CLOSE(fd_in);
80 
81 	check_file();
82 }
83 
setup(void)84 static void setup(void)
85 {
86 	int i;
87 
88 	if (tst_fs_type(".") == TST_NFS_MAGIC) {
89 		if ((tst_kvercmp(2, 6, 32)) < 0)
90 			tst_brk(TCONF, "Cannot do tee on a file"
91 				" on NFS filesystem before 2.6.32");
92 	}
93 
94 	for (i = 0; i < TEST_BLOCK_SIZE; i++)
95 		buffer[i] = i & 0xff;
96 
97 	fd_in = SAFE_OPEN(TESTFILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
98 	SAFE_WRITE(1, fd_in, buffer, TEST_BLOCK_SIZE);
99 	SAFE_CLOSE(fd_in);
100 }
101 
cleanup(void)102 static void cleanup(void)
103 {
104 	if (fd_in > 0)
105 		SAFE_CLOSE(fd_in);
106 
107 	if (fd_out > 0)
108 		SAFE_CLOSE(fd_out);
109 }
110 
111 static struct tst_test test = {
112 	.setup = setup,
113 	.cleanup = cleanup,
114 	.test_all = tee_test,
115 	.needs_tmpdir = 1,
116 	.min_kver = "2.6.17",
117 };
118