blob: 8015c0a72bd4cd74abe0738dcea347d326035668 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * writev03.c
23 *
24 * DESCRIPTION
25 * The testcases are written calling writev() with partially valid data
26 * to overwrite the contents, to write in the beginning and to write in
27 * the end of the file.
28 *
29 * USAGE: <for command-line>
30 * writev03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
31 * where, -c n : Run n copies concurrently.
32 * -e : Turn on errno logging.
33 * -i n : Execute test n times.
34 * -I x : Execute test for x seconds.
35 * -P x : Pause for x seconds between iterations.
36 * -t : Turn on syscall timing.
37 *
38 * History
39 * 07/2001 John George
40 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000041 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000042 *
43 * Restrictions
44 * NONE
45 */
46
47#include <sys/types.h>
plars865695b2001-08-27 22:15:12 +000048#include <sys/uio.h>
robbiew169e09b2005-08-30 17:24:45 +000049#include <sys/mman.h>
50#include <unistd.h>
51#include <signal.h>
plars865695b2001-08-27 22:15:12 +000052#include <fcntl.h>
53#include <memory.h>
54#include <errno.h>
Garrett Coopere8530df2010-12-21 11:37:57 -080055#include "test.h"
plars865695b2001-08-27 22:15:12 +000056
57#define K_1 1024
58
59#define NBUFS 4
subrata_modak56207ce2009-03-23 13:35:39 +000060#define CHUNK 64 /* single chunk */
plars865695b2001-08-27 22:15:12 +000061#define MAX_IOVEC 4
62#define DATA_FILE "writev_data_file"
63
subrata_modak56207ce2009-03-23 13:35:39 +000064char buf1[K_1], buf2[K_1], buf3[K_1];
65char *bad_addr = 0;
plars865695b2001-08-27 22:15:12 +000066
67struct iovec wr_iovec[MAX_IOVEC] = {
68 /* testcase #1 */
subrata_modak56207ce2009-03-23 13:35:39 +000069 {buf1 + (CHUNK * 6), CHUNK},
70 {(caddr_t) - 1, CHUNK},
71 {buf1 + (CHUNK * 8), CHUNK},
Cyril Hrubiscf0d6262014-09-23 14:03:31 +020072 {NULL, 0}
plars865695b2001-08-27 22:15:12 +000073};
74
subrata_modak56207ce2009-03-23 13:35:39 +000075char name[K_1], f_name[K_1];
76int fd[2], in_sighandler;
77char *buf_list[NBUFS];
plars865695b2001-08-27 22:15:12 +000078
79char *TCID = "writev03";
80int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000081
82void sighandler(int);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -080083void l_seek(int, off_t, int);
plars865695b2001-08-27 22:15:12 +000084void setup(void);
85void cleanup(void);
vapier6925ca32006-02-27 04:25:25 +000086
robbiew7d5c5172003-03-27 22:54:57 +000087int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000088{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020089 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020090 const char *msg;
plars865695b2001-08-27 22:15:12 +000091
92 int nbytes;
93
Garrett Cooper2aca6fc2010-12-19 03:12:40 -080094 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +000095 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080096
plars865695b2001-08-27 22:15:12 +000097 setup();
98
plars865695b2001-08-27 22:15:12 +000099 for (lc = 0; TEST_LOOPING(lc); lc++) {
100
Caspar Zhangd59a6592013-03-07 14:59:12 +0800101 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000102
103 buf_list[0] = buf1;
104 buf_list[1] = buf2;
105 buf_list[2] = buf3;
Garrett Cooper45e285d2010-11-22 12:19:25 -0800106 buf_list[3] = NULL;
plars865695b2001-08-27 22:15:12 +0000107
subrata_modak56207ce2009-03-23 13:35:39 +0000108 fd[1] = -1; /* Invalid file descriptor */
plars865695b2001-08-27 22:15:12 +0000109
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800110 if (signal(SIGTERM, sighandler) == SIG_ERR)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 tst_brkm(TBROK | TERRNO, cleanup,
112 "signal(SIGTERM, ..) failed");
plars865695b2001-08-27 22:15:12 +0000113
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800114 if (signal(SIGPIPE, sighandler) == SIG_ERR)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115 tst_brkm(TBROK | TERRNO, cleanup,
116 "signal(SIGPIPE, ..) failed");
plars865695b2001-08-27 22:15:12 +0000117
118 memset(buf_list[0], 0, K_1);
119 memset(buf_list[1], 0, K_1);
120
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) == -1)
122 tst_brkm(TBROK | TERRNO, cleanup,
123 "open(.., O_WRONLY|O_CREAT, ..) failed");
124 else if ((nbytes = write(fd[0], buf_list[1], K_1)) != K_1)
125 tst_brkm(TFAIL | TERRNO, cleanup, "write failed");
plars865695b2001-08-27 22:15:12 +0000126
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800127 if (close(fd[0]) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800128 tst_brkm(TBROK | TERRNO, cleanup, "close failed");
plars865695b2001-08-27 22:15:12 +0000129
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800130 if ((fd[0] = open(f_name, O_RDWR, 0666)) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131 tst_brkm(TBROK | TERRNO, cleanup,
132 "open(.., O_RDWR, ..) failed");
robbiew7d5c5172003-03-27 22:54:57 +0000133//block1:
plars865695b2001-08-27 22:15:12 +0000134 tst_resm(TINFO, "Enter block 1");
subrata_modak56207ce2009-03-23 13:35:39 +0000135
plars865695b2001-08-27 22:15:12 +0000136 /*
137 * In this block we are trying to call writev() with
138 * partially valid data. This should return the valid number
139 * of bytes written in the vector. If it returns EFAULT, it
140 * is an error. And after returning the number of valid
141 * bytes written, the check should be made to verify the
142 * contents of the first valid write() scheduled.
143 */
144
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800145 if (writev(fd[0], wr_iovec, 3) == -1) {
146 if (errno == EFAULT)
147 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000148 } else {
149 l_seek(fd[0], 0, 0);
150 read(fd[0], buf_list[0], CHUNK);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800151 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0)
plars865695b2001-08-27 22:15:12 +0000152 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000153 }
154 tst_resm(TINFO, "Exit block 1");
155
robbiew7d5c5172003-03-27 22:54:57 +0000156//block2:
plars865695b2001-08-27 22:15:12 +0000157 tst_resm(TINFO, "Enter block 2");
plars865695b2001-08-27 22:15:12 +0000158
159 /*
160 * In this block we are trying to over write the contents by
161 * calling writev() with partially valid data. It should
162 * return the valid number of bytes written but not EFAULT.
163 * Also the check should be made whether the initial write()
164 * scheduled is done correctly or not.
165 */
166 l_seek(fd[0], 0, 0);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800167 if (writev(fd[0], wr_iovec, 3) == -1) {
168 if (errno == EFAULT)
169 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000170 } else {
171 l_seek(fd[0], 0, 0);
172 read(fd[0], buf_list[0], CHUNK);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800173 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0)
plars865695b2001-08-27 22:15:12 +0000174 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000175 }
176 tst_resm(TINFO, "Exit block 2");
177
robbiew7d5c5172003-03-27 22:54:57 +0000178//block3:
plars865695b2001-08-27 22:15:12 +0000179 tst_resm(TINFO, "Enter block 3");
plars865695b2001-08-27 22:15:12 +0000180
181 /*
182 * In this block, we are trying to call writev() by going to
183 * some end position of the file. Here writev() is called
184 * with partially valid data, and this will return the
185 * number of valid bytes written and not EFAULT. Also, the
186 * check should be made whether the inital write() that is
187 * scheduled with valid data is done correctly done or not.
188 */
189
190 l_seek(fd[0], 8192, 0);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800191 if (writev(fd[0], wr_iovec, 3) == -1) {
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800192 if (errno == EFAULT)
193 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000194 } else {
195 l_seek(fd[0], 0, 0);
196 read(fd[0], buf_list[0], CHUNK);
197 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
198 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000199 }
200 }
201
plars865695b2001-08-27 22:15:12 +0000202 tst_resm(TINFO, "Exit block 3");
203 }
204 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800205 tst_exit();
vapier6925ca32006-02-27 04:25:25 +0000206}
207
plars865695b2001-08-27 22:15:12 +0000208/*
209 * setup()
210 * performs all ONE TIME setup for this test
211 */
subrata_modak56207ce2009-03-23 13:35:39 +0000212void setup(void)
plars865695b2001-08-27 22:15:12 +0000213{
Garrett Cooper2c282152010-12-16 00:55:50 -0800214
plars865695b2001-08-27 22:15:12 +0000215 tst_sig(FORK, DEF_HANDLER, cleanup);
216
plars865695b2001-08-27 22:15:12 +0000217 /* Pause if that option was specified.
218 * TEST_PAUSE contains the code to fork the test with the -i option.
219 * You want to make sure you do this before you create your temporary
220 * directory.
221 */
subrata_modak56207ce2009-03-23 13:35:39 +0000222 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000223
224 strcpy(name, DATA_FILE);
225 sprintf(f_name, "%s.%d", name, getpid());
subrata_modakbdbaec52009-02-26 12:14:51 +0000226
subrata_modak56207ce2009-03-23 13:35:39 +0000227 bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
vapier0722a2b2006-05-12 15:44:11 +0000228 if (bad_addr == MAP_FAILED) {
robbiew169e09b2005-08-30 17:24:45 +0000229 tst_brkm(TBROK, cleanup, "mmap failed");
230 }
231 wr_iovec[1].iov_base = bad_addr;
plars865695b2001-08-27 22:15:12 +0000232 tst_tmpdir();
233}
234
235/*
236 * cleanup()
237 * performs all ONE TIME cleanup for this test at
238 * completion or premature exit
239 */
subrata_modak56207ce2009-03-23 13:35:39 +0000240void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000241{
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800242 close(fd[0]);
243 close(fd[1]);
244
245 if (unlink(f_name) == -1)
246 tst_resm(TFAIL, "unlink failed");
plars865695b2001-08-27 22:15:12 +0000247 tst_rmdir();
248
plars865695b2001-08-27 22:15:12 +0000249}
250
subrata_modak56207ce2009-03-23 13:35:39 +0000251void sighandler(int sig)
plars865695b2001-08-27 22:15:12 +0000252{
subrata_modak56207ce2009-03-23 13:35:39 +0000253 switch (sig) {
254 case SIGTERM:
255 break;
256 case SIGPIPE:
257 ++in_sighandler;
258 return;
plars865695b2001-08-27 22:15:12 +0000259 default:
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800260 tst_resm(TBROK, "sighandler received invalid signal : %d", sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000261 break;
plars865695b2001-08-27 22:15:12 +0000262 }
plars865695b2001-08-27 22:15:12 +0000263}
264
265/*
266 * l_seek()
267 * Wrap around for regular lseek function for giving error message
268 */
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800269void l_seek(int fdesc, off_t offset, int whence)
plars865695b2001-08-27 22:15:12 +0000270{
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800271 if (lseek(fdesc, offset, whence) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800272 tst_brkm(TBROK | TERRNO, cleanup, "lseek failed");
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800273}