blob: 1fd0794afbef17514c59e315baac56836a28359b [file] [log] [blame]
Cyril Hrubis153bdc72014-06-03 11:46:31 +02001/****************************************************************************
vapierc033f492006-08-21 07:44:43 +00002 *
Cyril Hrubis153bdc72014-06-03 11:46:31 +02003 * Copyright (c) International Business Machines Corp., 2006
4 * Author Yi Yang <yyangcdl@cn.ibm.com>
5 * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
vapierc033f492006-08-21 07:44:43 +00006 *
Cyril Hrubis153bdc72014-06-03 11:46:31 +02007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
vapierc033f492006-08-21 07:44:43 +000011 *
Cyril Hrubis153bdc72014-06-03 11:46:31 +020012 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU General Public License for more details.
vapierc033f492006-08-21 07:44:43 +000016 *
Cyril Hrubis153bdc72014-06-03 11:46:31 +020017 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
vapierc033f492006-08-21 07:44:43 +000020 *
21 * DESCRIPTION
22 * This test case will verify basic function of tee(2)
23 * added by kernel 2.6.17 or up.
24 *
Cyril Hrubis153bdc72014-06-03 11:46:31 +020025 ***************************************************************************/
26
27#define _GNU_SOURCE
vapierc033f492006-08-21 07:44:43 +000028
29#include <errno.h>
30#include <string.h>
31#include <signal.h>
32#include <sys/types.h>
33#include <fcntl.h>
34#include <sys/syscall.h>
Cyril Hrubis153bdc72014-06-03 11:46:31 +020035
vapierc033f492006-08-21 07:44:43 +000036#include "test.h"
vapier9cf96d82006-09-10 09:54:16 +000037#include "linux_syscall_numbers.h"
Cyril Hrubis153bdc72014-06-03 11:46:31 +020038#include "safe_macros.h"
Cyril Hrubis0f0e3482014-02-27 16:08:04 +010039#include "tst_fs_type.h"
Cyril Hrubis153bdc72014-06-03 11:46:31 +020040#include "lapi/fcntl.h"
mreed10380d3e62006-09-06 15:38:25 +000041
Cyril Hrubis153bdc72014-06-03 11:46:31 +020042static void tee_test(void);
43static void setup(void);
44static void cleanup(void);
vapierc033f492006-08-21 07:44:43 +000045
Cyril Hrubis153bdc72014-06-03 11:46:31 +020046#define TEST_BLOCK_SIZE 1024
47
48#define TESTFILE1 "tee_test_file_1"
49#define TESTFILE2 "tee_test_file_2"
50
51static int fd_in, fd_out;
52static char buffer[TEST_BLOCK_SIZE];
vapierc033f492006-08-21 07:44:43 +000053
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020054char *TCID = "tee01";
55int TST_TOTAL = 1;
vapierc033f492006-08-21 07:44:43 +000056
57int main(int ac, char **av)
58{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020059 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020060 const char *msg;
vapierc033f492006-08-21 07:44:43 +000061
Garrett Cooper45e285d2010-11-22 12:19:25 -080062 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080063 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
vapierc033f492006-08-21 07:44:43 +000064
vapierc033f492006-08-21 07:44:43 +000065 setup();
subrata_modakbdbaec52009-02-26 12:14:51 +000066
Cyril Hrubis153bdc72014-06-03 11:46:31 +020067 for (lc = 0; TEST_LOOPING(lc); lc++)
68 tee_test();
69
70 cleanup();
71 tst_exit();
72}
73
74static void check_file(void)
75{
76 int i;
77 char teebuffer[TEST_BLOCK_SIZE];
78
79 fd_out = SAFE_OPEN(cleanup, TESTFILE2, O_RDONLY);
80 SAFE_READ(cleanup, 1, fd_out, teebuffer, TEST_BLOCK_SIZE);
81
82 for (i = 0; i < TEST_BLOCK_SIZE; i++) {
83 if (buffer[i] != teebuffer[i])
84 break;
85 }
86
87 if (i < TEST_BLOCK_SIZE)
88 tst_resm(TFAIL, "Wrong data read from the buffer at %i", i);
89 else
90 tst_resm(TPASS, "Written data has been read back correctly");
91
92 close(fd_out);
93 fd_out = 0;
94}
95
96static void tee_test(void)
97{
98 int pipe1[2];
99 int pipe2[2];
100 int ret = 0;
101
102 fd_in = SAFE_OPEN(cleanup, TESTFILE1, O_RDONLY);
103 fd_out = SAFE_OPEN(cleanup, TESTFILE2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
104
105 SAFE_PIPE(cleanup, pipe1);
106 SAFE_PIPE(cleanup, pipe2);
107
108 ret = splice(fd_in, NULL, pipe1[1], NULL, TEST_BLOCK_SIZE, 0);
109 if (ret < 0)
110 tst_brkm(TBROK | TERRNO, cleanup, "splice(fd_in, pipe1) failed");
111
112 ret = tee(pipe1[0], pipe2[1], TEST_BLOCK_SIZE, SPLICE_F_NONBLOCK);
113 if (ret < 0)
114 tst_brkm(TBROK | TERRNO, cleanup, "tee() failed");
115
116 ret = splice(pipe2[0], NULL, fd_out, NULL, TEST_BLOCK_SIZE, 0);
117 if (ret < 0)
118 tst_brkm(TBROK | TERRNO, cleanup, "splice(pipe2, fd_out) failed");
119
120 close(pipe2[0]);
121 close(pipe2[1]);
122 close(pipe1[0]);
123 close(pipe1[1]);
124 close(fd_out);
125 close(fd_in);
126
127 fd_out = 0;
128 fd_in = 0;
129
130 check_file();
131}
132
133static void setup(void)
134{
135 int i;
136
137 if ((tst_kvercmp(2, 6, 17)) < 0) {
138 tst_brkm(TCONF, cleanup, "This test can only run on kernels "
139 "that are 2.6.17 or higher");
140 }
141
142 tst_sig(NOFORK, DEF_HANDLER, cleanup);
143
144 TEST_PAUSE;
145
146 tst_tmpdir();
147
Cyril Hrubis0f0e3482014-02-27 16:08:04 +0100148 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) {
Xiong Zhoud623e2c2014-09-25 03:24:19 -0400149 if ((tst_kvercmp(2, 6, 32)) < 0)
150 tst_brkm(TCONF, cleanup, "Cannot do tee on a file"
151 " on NFS filesystem before 2.6.32");
subrata_modak56207ce2009-03-23 13:35:39 +0000152 }
vapierc033f492006-08-21 07:44:43 +0000153
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200154 for (i = 0; i < TEST_BLOCK_SIZE; i++)
vapierc033f492006-08-21 07:44:43 +0000155 buffer[i] = i & 0xff;
vapierc033f492006-08-21 07:44:43 +0000156
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200157 fd_in = SAFE_OPEN(cleanup, TESTFILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
158 SAFE_WRITE(cleanup, 1, fd_in, buffer, TEST_BLOCK_SIZE);
159 SAFE_CLOSE(cleanup, fd_in);
160 fd_in = 0;
vapierc033f492006-08-21 07:44:43 +0000161}
162
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200163static void cleanup(void)
vapierc033f492006-08-21 07:44:43 +0000164{
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200165 if (fd_in > 0 && close(fd_in))
166 tst_resm(TWARN, "Failed to close fd_in");
vapierc033f492006-08-21 07:44:43 +0000167
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200168 if (fd_out > 0 && close(fd_out))
169 tst_resm(TWARN, "Failed to close fd_out");
170
171 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700172}