blob: a1aeff99068ff9cabe219fa45bd28ae11abc4701 [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 * writev04.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. This is same as writev03.c, but the length of
28 * buffer used here is 8192 bytes.
29 *
30 * USAGE: <for command-line>
31 * writev04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
32 * where, -c n : Run n copies concurrently.
33 * -e : Turn on errno logging.
34 * -i n : Execute test n times.
35 * -I x : Execute test for x seconds.
36 * -P x : Pause for x seconds between iterations.
37 * -t : Turn on syscall timing.
38 *
39 * History
40 * 07/2001 John George
41 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000042 * 04/2002 wjhuie sigset cleanups
plars865695b2001-08-27 22:15:12 +000043 *
44 * Restrictions
45 * NONE
46 */
plars865695b2001-08-27 22:15:12 +000047#include <sys/types.h>
plars865695b2001-08-27 22:15:12 +000048#include <sys/uio.h>
robbiew37549972005-08-30 19:32:44 +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"
56#include "usctest.h"
plars865695b2001-08-27 22:15:12 +000057
58#define K_1 8192
59
60#define NBUFS 4
subrata_modak56207ce2009-03-23 13:35:39 +000061#define CHUNK 64 /* single chunk */
plars865695b2001-08-27 22:15:12 +000062#define MAX_IOVEC 4
63#define DATA_FILE "writev_data_file"
64
subrata_modak56207ce2009-03-23 13:35:39 +000065char buf1[K_1], buf2[K_1], buf3[K_1];
66char *bad_addr = 0;
plars865695b2001-08-27 22:15:12 +000067
68struct iovec wr_iovec[MAX_IOVEC] = {
69 /* testcase #1 */
subrata_modak56207ce2009-03-23 13:35:39 +000070 {buf1 + (CHUNK * 6), CHUNK},
71 {(caddr_t) - 1, CHUNK},
72 {buf1 + (CHUNK * 8), CHUNK},
Cyril Hrubiscf0d6262014-09-23 14:03:31 +020073 {NULL, 0}
plars865695b2001-08-27 22:15:12 +000074};
75
76/* 0 terminated list of expected errnos */
subrata_modak56207ce2009-03-23 13:35:39 +000077int exp_enos[] = { 0 };
plars865695b2001-08-27 22:15:12 +000078
subrata_modak56207ce2009-03-23 13:35:39 +000079char name[K_1], f_name[K_1];
80int fd[2], in_sighandler;
81char *buf_list[NBUFS];
plars865695b2001-08-27 22:15:12 +000082
83char *TCID = "writev04";
84int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000085
86void sighandler(int);
87long l_seek(int, long, int);
88void setup(void);
89void cleanup(void);
90int fail;
91
vapier6925ca32006-02-27 04:25:25 +000092#if !defined(UCLINUX)
93
robbiew7d5c5172003-03-27 22:54:57 +000094int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000095{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020096 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020097 const char *msg;
plars865695b2001-08-27 22:15:12 +000098
99 int nbytes;
100
Wanlong Gao354ebb42012-12-07 10:10:04 +0800101 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL) {
plars865695b2001-08-27 22:15:12 +0000102 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800103
Wanlong Gao354ebb42012-12-07 10:10:04 +0800104 }
plars865695b2001-08-27 22:15:12 +0000105
subrata_modak56207ce2009-03-23 13:35:39 +0000106 setup(); /* set "tstdir", and "testfile" vars */
plars865695b2001-08-27 22:15:12 +0000107
108 /* The following loop checks looping state if -i option given */
109 for (lc = 0; TEST_LOOPING(lc); lc++) {
110
Caspar Zhangd59a6592013-03-07 14:59:12 +0800111 /* reset tst_count in case we are looping */
112 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000113
114 buf_list[0] = buf1;
115 buf_list[1] = buf2;
116 buf_list[2] = buf3;
Garrett Cooper45e285d2010-11-22 12:19:25 -0800117 buf_list[3] = NULL;
plars865695b2001-08-27 22:15:12 +0000118
subrata_modak56207ce2009-03-23 13:35:39 +0000119 fd[1] = -1; /* Invalid file descriptor */
plars865695b2001-08-27 22:15:12 +0000120
robbiew4c53b8f2003-04-04 16:46:57 +0000121 if (signal(SIGTERM, sighandler) == SIG_ERR) {
robbiew4644c7e2002-04-26 14:33:32 +0000122 perror("signal");
123 tst_resm(TFAIL, "signal() SIGTERM FAILED");
plars865695b2001-08-27 22:15:12 +0000124 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 }
plars865695b2001-08-27 22:15:12 +0000126
robbiew4c53b8f2003-04-04 16:46:57 +0000127 if (signal(SIGPIPE, sighandler) == SIG_ERR) {
robbiew4644c7e2002-04-26 14:33:32 +0000128 perror("signal");
129 tst_resm(TFAIL, "signal() SIGPIPE FAILED");
plars865695b2001-08-27 22:15:12 +0000130 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131 }
plars865695b2001-08-27 22:15:12 +0000132
133 memset(buf_list[0], 0, K_1);
134 memset(buf_list[1], 0, K_1);
135
136 if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
137 tst_resm(TFAIL, "open(2) failed: fname = %s, "
138 "errno = %d", f_name, errno);
139 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000141 if ((nbytes = write(fd[0], buf_list[1], K_1)) != K_1) {
plars865695b2001-08-27 22:15:12 +0000142 tst_resm(TFAIL, "write(2) failed: nbytes "
143 "= %d, errno = %d", nbytes, errno);
144 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145 }
plars865695b2001-08-27 22:15:12 +0000146 }
147
148 if (close(fd[0]) < 0) {
149 tst_resm(TFAIL, "close failed: errno = %d", errno);
150 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 }
plars865695b2001-08-27 22:15:12 +0000152
153 if ((fd[0] = open(f_name, O_RDWR, 0666)) < 0) {
Cyril Hrubis9fa8ad02014-12-16 13:20:49 +0100154 tst_brkm(TFAIL, cleanup, "open failed: fname = %s, errno = %d",
plars865695b2001-08-27 22:15:12 +0000155 f_name, errno);
plars865695b2001-08-27 22:15:12 +0000156 }
robbiew7d5c5172003-03-27 22:54:57 +0000157//block1:
plars865695b2001-08-27 22:15:12 +0000158 tst_resm(TINFO, "Enter block 1");
159 fail = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000160
plars865695b2001-08-27 22:15:12 +0000161 /*
162 * In this block we are trying to call writev() with
163 * partially valid data. This should return the valid number
164 * of bytes written in the vector. If it returns EFAULT, it
165 * is an error. And after returning the number of valid
166 * bytes written, the check should be made to verify the
167 * contents of the first valid write() scheduled.
168 */
169 if (writev(fd[0], wr_iovec, 3) < 0) {
170 TEST_ERROR_LOG(errno);
171 fail = 1;
172 if (errno == EFAULT) {
173 tst_resm(TFAIL, "Got error EFAULT");
174 } else {
175 tst_resm(TFAIL, "Received unexpected error: %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000176 errno);
plars865695b2001-08-27 22:15:12 +0000177 }
178 } else {
179 l_seek(fd[0], 0, 0);
180 read(fd[0], buf_list[0], CHUNK);
181 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
182 tst_resm(TFAIL, "writev overwrote the file");
183 fail = 1;
184 }
185 }
186
187 if (fail) {
188 tst_resm(TINFO, "block 1 FAILED");
189 } else {
190 tst_resm(TINFO, "block 1 PASSED");
191 }
192 tst_resm(TINFO, "Exit block 1");
193
robbiew7d5c5172003-03-27 22:54:57 +0000194//block2:
plars865695b2001-08-27 22:15:12 +0000195 tst_resm(TINFO, "Enter block 2");
196 fail = 0;
197
198 /*
199 * In this block we are trying to over write the contents by
200 * calling writev() with partially valid data. It should
201 * return the valid number of bytes written but not EFAULT.
202 * Also the check should be made whether the initial write()
203 * scheduled is done correctly or not.
204 */
205 l_seek(fd[0], 0, 0);
206 if (writev(fd[0], wr_iovec, 3) < 0) {
207 TEST_ERROR_LOG(errno);
208 fail = 1;
209 if (errno == EFAULT) {
210 tst_resm(TFAIL, "Got error EFAULT");
211 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000212 tst_resm(TFAIL, "Received unexpected error: %d",
213 errno);
plars865695b2001-08-27 22:15:12 +0000214 }
215 } else {
216 l_seek(fd[0], 0, 0);
217 read(fd[0], buf_list[0], CHUNK);
218 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
219 tst_resm(TFAIL, "writev overwrote the file");
220 fail = 1;
221 }
222 }
223
224 if (fail) {
225 tst_resm(TINFO, "block 2 FAILED");
226 } else {
227 tst_resm(TINFO, "block 2 PASSED");
228 }
229 tst_resm(TINFO, "Exit block 2");
230
robbiew7d5c5172003-03-27 22:54:57 +0000231//block3:
plars865695b2001-08-27 22:15:12 +0000232 tst_resm(TINFO, "Enter block 3");
233 fail = 0;
234
235 /*
236 * In this block, we are trying to call writev() by going to
237 * some end position of the file. Here writev() is called
238 * with partially valid data, and this will return the
239 * number of valid bytes written and not EFAULT. Also, the
240 * check should be made whether the inital write() that is
241 * scheduled with valid data is done correctly.
242 */
243
244 l_seek(fd[0], 8192, 0);
245 if (writev(fd[0], wr_iovec, 3) < 0) {
246 TEST_ERROR_LOG(errno);
247 fail = 1;
248 if (errno == EFAULT) {
249 tst_resm(TFAIL, "Got error EFAULT");
250 } else {
251 tst_resm(TFAIL, "Received unexpected error: %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000252 errno);
plars865695b2001-08-27 22:15:12 +0000253 }
254 } else {
255 l_seek(fd[0], 0, 0);
256 read(fd[0], buf_list[0], CHUNK);
257 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
258 tst_resm(TFAIL, "writev overwrote the file");
259 fail = 1;
260 }
261 }
262
263 if (fail) {
264 tst_resm(TINFO, "block 3 FAILED");
265 } else {
266 tst_resm(TINFO, "block 3 PASSED");
267 }
268 tst_resm(TINFO, "Exit block 3");
269 }
subrata_modakdad6e1a2007-10-30 10:46:58 +0000270 close(fd[0]);
271 close(fd[1]);
plars865695b2001-08-27 22:15:12 +0000272 cleanup();
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800273 tst_exit();
plars865695b2001-08-27 22:15:12 +0000274}
275
vapier6925ca32006-02-27 04:25:25 +0000276#else
277
Mike Frysingerc57fba52014-04-09 18:56:30 -0400278int main(void)
vapier6925ca32006-02-27 04:25:25 +0000279{
280 tst_resm(TINFO, "test is not available on uClinux");
Garrett Cooper2c282152010-12-16 00:55:50 -0800281 tst_exit();
vapier6925ca32006-02-27 04:25:25 +0000282}
283
284#endif /* if !defined(UCLINUX) */
285
plars865695b2001-08-27 22:15:12 +0000286/*
287 * setup()
288 * performs all ONE TIME setup for this test
289 */
subrata_modak56207ce2009-03-23 13:35:39 +0000290void setup(void)
plars865695b2001-08-27 22:15:12 +0000291{
Garrett Cooper2c282152010-12-16 00:55:50 -0800292
plars865695b2001-08-27 22:15:12 +0000293 tst_sig(FORK, DEF_HANDLER, cleanup);
294
plars865695b2001-08-27 22:15:12 +0000295 TEST_EXP_ENOS(exp_enos);
296
plars865695b2001-08-27 22:15:12 +0000297 TEST_PAUSE;
298
299 /* Create a unique temporary directory and chdir() to it. */
300 tst_tmpdir();
301
302 strcpy(name, DATA_FILE);
303 sprintf(f_name, "%s.%d", name, getpid());
subrata_modakbdbaec52009-02-26 12:14:51 +0000304
subrata_modak56207ce2009-03-23 13:35:39 +0000305 bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
306 if (bad_addr == MAP_FAILED) {
307 tst_brkm(TBROK, cleanup, "mmap failed");
308 }
309 wr_iovec[1].iov_base = bad_addr;
plars865695b2001-08-27 22:15:12 +0000310
311}
312
313/*
314 * cleanup()
315 * performs all ONE TIME cleanup for this test at
316 * completion or premature exit
317 */
subrata_modak56207ce2009-03-23 13:35:39 +0000318void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000319{
320 /*
321 * print timing stats if that option was specified.
322 * print errno log if that option was specified.
323 */
324 TEST_CLEANUP;
325
326 if (unlink(f_name) < 0) {
327 tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
328 f_name, errno);
329 }
330 tst_rmdir();
331
plars865695b2001-08-27 22:15:12 +0000332}
333
334/*
335 * sighandler()
336 * Signal handler function for SIGTERM and SIGPIPE
337 */
subrata_modak56207ce2009-03-23 13:35:39 +0000338void sighandler(int sig)
plars865695b2001-08-27 22:15:12 +0000339{
subrata_modak56207ce2009-03-23 13:35:39 +0000340 switch (sig) {
341 case SIGTERM:
342 break;
343 case SIGPIPE:
344 ++in_sighandler;
345 return;
plars865695b2001-08-27 22:15:12 +0000346 default:
subrata_modak56207ce2009-03-23 13:35:39 +0000347 tst_resm(TFAIL, "sighandler() received invalid signal "
348 ": %d", sig);
349 break;
plars865695b2001-08-27 22:15:12 +0000350 }
351
352 if ((unlink(f_name) < 0) && (errno != ENOENT)) {
353 tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
354 f_name, errno);
355 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800356 }
plars865695b2001-08-27 22:15:12 +0000357 exit(sig);
358}
359
360/*
361 * l_seek()
362 * Wrap around for regular lseek function for giving error message
363 */
subrata_modak56207ce2009-03-23 13:35:39 +0000364long l_seek(int fdesc, long offset, int whence)
plars865695b2001-08-27 22:15:12 +0000365{
366 if (lseek(fdesc, offset, whence) < 0) {
367 tst_resm(TFAIL, "lseek Failed : errno = %d", errno);
368 fail = 1;
369 }
subrata_modak43337a32009-02-26 11:43:51 +0000370 return 0;
Chris Dearmanec6edca2012-10-17 19:54:01 -0700371}