blob: 6e1f46f477c35804aa64bd416b9165aba992272d [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 Hrubis153bdc72014-06-03 11:46:31 +020039#include "lapi/fcntl.h"
Cyril Hrubisca675382016-04-12 16:46:02 +020040#include "lapi/tee.h"
41#include "lapi/splice.h"
mreed10380d3e62006-09-06 15:38:25 +000042
Cyril Hrubis153bdc72014-06-03 11:46:31 +020043static void tee_test(void);
44static void setup(void);
45static void cleanup(void);
vapierc033f492006-08-21 07:44:43 +000046
Cyril Hrubis153bdc72014-06-03 11:46:31 +020047#define TEST_BLOCK_SIZE 1024
48
49#define TESTFILE1 "tee_test_file_1"
50#define TESTFILE2 "tee_test_file_2"
51
52static int fd_in, fd_out;
53static char buffer[TEST_BLOCK_SIZE];
vapierc033f492006-08-21 07:44:43 +000054
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020055char *TCID = "tee01";
56int TST_TOTAL = 1;
vapierc033f492006-08-21 07:44:43 +000057
58int main(int ac, char **av)
59{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020060 int lc;
vapierc033f492006-08-21 07:44:43 +000061
Cyril Hrubisd6d11d02015-03-09 17:35:43 +010062 tst_parse_opts(ac, av, NULL, NULL);
vapierc033f492006-08-21 07:44:43 +000063
vapierc033f492006-08-21 07:44:43 +000064 setup();
subrata_modakbdbaec52009-02-26 12:14:51 +000065
Cyril Hrubis153bdc72014-06-03 11:46:31 +020066 for (lc = 0; TEST_LOOPING(lc); lc++)
67 tee_test();
68
69 cleanup();
70 tst_exit();
71}
72
73static void check_file(void)
74{
75 int i;
76 char teebuffer[TEST_BLOCK_SIZE];
77
78 fd_out = SAFE_OPEN(cleanup, TESTFILE2, O_RDONLY);
79 SAFE_READ(cleanup, 1, fd_out, teebuffer, TEST_BLOCK_SIZE);
80
81 for (i = 0; i < TEST_BLOCK_SIZE; i++) {
82 if (buffer[i] != teebuffer[i])
83 break;
84 }
85
86 if (i < TEST_BLOCK_SIZE)
87 tst_resm(TFAIL, "Wrong data read from the buffer at %i", i);
88 else
89 tst_resm(TPASS, "Written data has been read back correctly");
90
91 close(fd_out);
92 fd_out = 0;
93}
94
95static void tee_test(void)
96{
97 int pipe1[2];
98 int pipe2[2];
99 int ret = 0;
100
101 fd_in = SAFE_OPEN(cleanup, TESTFILE1, O_RDONLY);
102 fd_out = SAFE_OPEN(cleanup, TESTFILE2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
103
104 SAFE_PIPE(cleanup, pipe1);
105 SAFE_PIPE(cleanup, pipe2);
106
107 ret = splice(fd_in, NULL, pipe1[1], NULL, TEST_BLOCK_SIZE, 0);
108 if (ret < 0)
109 tst_brkm(TBROK | TERRNO, cleanup, "splice(fd_in, pipe1) failed");
110
111 ret = tee(pipe1[0], pipe2[1], TEST_BLOCK_SIZE, SPLICE_F_NONBLOCK);
112 if (ret < 0)
113 tst_brkm(TBROK | TERRNO, cleanup, "tee() failed");
114
115 ret = splice(pipe2[0], NULL, fd_out, NULL, TEST_BLOCK_SIZE, 0);
116 if (ret < 0)
117 tst_brkm(TBROK | TERRNO, cleanup, "splice(pipe2, fd_out) failed");
118
119 close(pipe2[0]);
120 close(pipe2[1]);
121 close(pipe1[0]);
122 close(pipe1[1]);
123 close(fd_out);
124 close(fd_in);
125
126 fd_out = 0;
127 fd_in = 0;
128
129 check_file();
130}
131
132static void setup(void)
133{
134 int i;
135
136 if ((tst_kvercmp(2, 6, 17)) < 0) {
137 tst_brkm(TCONF, cleanup, "This test can only run on kernels "
138 "that are 2.6.17 or higher");
139 }
140
141 tst_sig(NOFORK, DEF_HANDLER, cleanup);
142
143 TEST_PAUSE;
144
145 tst_tmpdir();
146
Cyril Hrubis0f0e3482014-02-27 16:08:04 +0100147 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) {
Xiong Zhoud623e2c2014-09-25 03:24:19 -0400148 if ((tst_kvercmp(2, 6, 32)) < 0)
149 tst_brkm(TCONF, cleanup, "Cannot do tee on a file"
150 " on NFS filesystem before 2.6.32");
subrata_modak56207ce2009-03-23 13:35:39 +0000151 }
vapierc033f492006-08-21 07:44:43 +0000152
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200153 for (i = 0; i < TEST_BLOCK_SIZE; i++)
vapierc033f492006-08-21 07:44:43 +0000154 buffer[i] = i & 0xff;
vapierc033f492006-08-21 07:44:43 +0000155
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200156 fd_in = SAFE_OPEN(cleanup, TESTFILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
157 SAFE_WRITE(cleanup, 1, fd_in, buffer, TEST_BLOCK_SIZE);
158 SAFE_CLOSE(cleanup, fd_in);
159 fd_in = 0;
vapierc033f492006-08-21 07:44:43 +0000160}
161
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200162static void cleanup(void)
vapierc033f492006-08-21 07:44:43 +0000163{
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200164 if (fd_in > 0 && close(fd_in))
165 tst_resm(TWARN, "Failed to close fd_in");
vapierc033f492006-08-21 07:44:43 +0000166
Cyril Hrubis153bdc72014-06-03 11:46:31 +0200167 if (fd_out > 0 && close(fd_out))
168 tst_resm(TWARN, "Failed to close fd_out");
169
170 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700171}