blob: 54db5b48eb910d76827710a3d0c23c05224bc20b [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
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
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>
55#include <test.h>
56#include <usctest.h>
57
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},
73 {(caddr_t) 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;
85extern int Tst_count;
86
87void sighandler(int);
88long l_seek(int, long, int);
89void setup(void);
90void cleanup(void);
91int fail;
92
vapier6925ca32006-02-27 04:25:25 +000093#if !defined(UCLINUX)
94
robbiew7d5c5172003-03-27 22:54:57 +000095int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000096{
subrata_modak56207ce2009-03-23 13:35:39 +000097 int lc; /* loop counter */
98 char *msg; /* message returned from parse_opts */
plars865695b2001-08-27 22:15:12 +000099
100 int nbytes;
101
102 /* parse standard options */
Garrett Cooper45e285d2010-11-22 12:19:25 -0800103 if ((msg = parse_opts(argc, argv, NULL, NULL)) !=
104 NULL) {
plars865695b2001-08-27 22:15:12 +0000105 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800106
Garrett Cooper53740502010-12-16 00:04:01 -0800107 }
plars865695b2001-08-27 22:15:12 +0000108
subrata_modak56207ce2009-03-23 13:35:39 +0000109 setup(); /* set "tstdir", and "testfile" vars */
plars865695b2001-08-27 22:15:12 +0000110
111 /* The following loop checks looping state if -i option given */
112 for (lc = 0; TEST_LOOPING(lc); lc++) {
113
114 /* reset Tst_count in case we are looping */
115 Tst_count = 0;
116
117 buf_list[0] = buf1;
118 buf_list[1] = buf2;
119 buf_list[2] = buf3;
Garrett Cooper45e285d2010-11-22 12:19:25 -0800120 buf_list[3] = NULL;
plars865695b2001-08-27 22:15:12 +0000121
subrata_modak56207ce2009-03-23 13:35:39 +0000122 fd[1] = -1; /* Invalid file descriptor */
plars865695b2001-08-27 22:15:12 +0000123
robbiew4c53b8f2003-04-04 16:46:57 +0000124 if (signal(SIGTERM, sighandler) == SIG_ERR) {
robbiew4644c7e2002-04-26 14:33:32 +0000125 perror("signal");
126 tst_resm(TFAIL, "signal() SIGTERM FAILED");
plars865695b2001-08-27 22:15:12 +0000127 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800128 }
plars865695b2001-08-27 22:15:12 +0000129
robbiew4c53b8f2003-04-04 16:46:57 +0000130 if (signal(SIGPIPE, sighandler) == SIG_ERR) {
robbiew4644c7e2002-04-26 14:33:32 +0000131 perror("signal");
132 tst_resm(TFAIL, "signal() SIGPIPE FAILED");
plars865695b2001-08-27 22:15:12 +0000133 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800134 }
plars865695b2001-08-27 22:15:12 +0000135
136 memset(buf_list[0], 0, K_1);
137 memset(buf_list[1], 0, K_1);
138
139 if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
140 tst_resm(TFAIL, "open(2) failed: fname = %s, "
141 "errno = %d", f_name, errno);
142 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800143 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000144 if ((nbytes = write(fd[0], buf_list[1], K_1)) != K_1) {
plars865695b2001-08-27 22:15:12 +0000145 tst_resm(TFAIL, "write(2) failed: nbytes "
146 "= %d, errno = %d", nbytes, errno);
147 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800148 }
plars865695b2001-08-27 22:15:12 +0000149 }
150
151 if (close(fd[0]) < 0) {
152 tst_resm(TFAIL, "close failed: errno = %d", errno);
153 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800154 }
plars865695b2001-08-27 22:15:12 +0000155
156 if ((fd[0] = open(f_name, O_RDWR, 0666)) < 0) {
157 tst_resm(TFAIL, "open failed: fname = %s, errno = %d",
158 f_name, errno);
159 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800160 return 0;
plars865695b2001-08-27 22:15:12 +0000161 }
robbiew7d5c5172003-03-27 22:54:57 +0000162//block1:
plars865695b2001-08-27 22:15:12 +0000163 tst_resm(TINFO, "Enter block 1");
164 fail = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000165
plars865695b2001-08-27 22:15:12 +0000166 /*
167 * In this block we are trying to call writev() with
168 * partially valid data. This should return the valid number
169 * of bytes written in the vector. If it returns EFAULT, it
170 * is an error. And after returning the number of valid
171 * bytes written, the check should be made to verify the
172 * contents of the first valid write() scheduled.
173 */
174 if (writev(fd[0], wr_iovec, 3) < 0) {
175 TEST_ERROR_LOG(errno);
176 fail = 1;
177 if (errno == EFAULT) {
178 tst_resm(TFAIL, "Got error EFAULT");
179 } else {
180 tst_resm(TFAIL, "Received unexpected error: %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000181 errno);
plars865695b2001-08-27 22:15:12 +0000182 }
183 } else {
184 l_seek(fd[0], 0, 0);
185 read(fd[0], buf_list[0], CHUNK);
186 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
187 tst_resm(TFAIL, "writev overwrote the file");
188 fail = 1;
189 }
190 }
191
192 if (fail) {
193 tst_resm(TINFO, "block 1 FAILED");
194 } else {
195 tst_resm(TINFO, "block 1 PASSED");
196 }
197 tst_resm(TINFO, "Exit block 1");
198
robbiew7d5c5172003-03-27 22:54:57 +0000199//block2:
plars865695b2001-08-27 22:15:12 +0000200 tst_resm(TINFO, "Enter block 2");
201 fail = 0;
202
203 /*
204 * In this block we are trying to over write the contents by
205 * calling writev() with partially valid data. It should
206 * return the valid number of bytes written but not EFAULT.
207 * Also the check should be made whether the initial write()
208 * scheduled is done correctly or not.
209 */
210 l_seek(fd[0], 0, 0);
211 if (writev(fd[0], wr_iovec, 3) < 0) {
212 TEST_ERROR_LOG(errno);
213 fail = 1;
214 if (errno == EFAULT) {
215 tst_resm(TFAIL, "Got error EFAULT");
216 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000217 tst_resm(TFAIL, "Received unexpected error: %d",
218 errno);
plars865695b2001-08-27 22:15:12 +0000219 }
220 } else {
221 l_seek(fd[0], 0, 0);
222 read(fd[0], buf_list[0], CHUNK);
223 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
224 tst_resm(TFAIL, "writev overwrote the file");
225 fail = 1;
226 }
227 }
228
229 if (fail) {
230 tst_resm(TINFO, "block 2 FAILED");
231 } else {
232 tst_resm(TINFO, "block 2 PASSED");
233 }
234 tst_resm(TINFO, "Exit block 2");
235
robbiew7d5c5172003-03-27 22:54:57 +0000236//block3:
plars865695b2001-08-27 22:15:12 +0000237 tst_resm(TINFO, "Enter block 3");
238 fail = 0;
239
240 /*
241 * In this block, we are trying to call writev() by going to
242 * some end position of the file. Here writev() is called
243 * with partially valid data, and this will return the
244 * number of valid bytes written and not EFAULT. Also, the
245 * check should be made whether the inital write() that is
246 * scheduled with valid data is done correctly.
247 */
248
249 l_seek(fd[0], 8192, 0);
250 if (writev(fd[0], wr_iovec, 3) < 0) {
251 TEST_ERROR_LOG(errno);
252 fail = 1;
253 if (errno == EFAULT) {
254 tst_resm(TFAIL, "Got error EFAULT");
255 } else {
256 tst_resm(TFAIL, "Received unexpected error: %d",
subrata_modak56207ce2009-03-23 13:35:39 +0000257 errno);
plars865695b2001-08-27 22:15:12 +0000258 }
259 } else {
260 l_seek(fd[0], 0, 0);
261 read(fd[0], buf_list[0], CHUNK);
262 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
263 tst_resm(TFAIL, "writev overwrote the file");
264 fail = 1;
265 }
266 }
267
268 if (fail) {
269 tst_resm(TINFO, "block 3 FAILED");
270 } else {
271 tst_resm(TINFO, "block 3 PASSED");
272 }
273 tst_resm(TINFO, "Exit block 3");
274 }
subrata_modakdad6e1a2007-10-30 10:46:58 +0000275 close(fd[0]);
276 close(fd[1]);
plars865695b2001-08-27 22:15:12 +0000277 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800278
plars865695b2001-08-27 22:15:12 +0000279}
280
vapier6925ca32006-02-27 04:25:25 +0000281#else
282
283int main()
284{
285 tst_resm(TINFO, "test is not available on uClinux");
Garrett Cooper2c282152010-12-16 00:55:50 -0800286 tst_exit();
vapier6925ca32006-02-27 04:25:25 +0000287}
288
289#endif /* if !defined(UCLINUX) */
290
plars865695b2001-08-27 22:15:12 +0000291/*
292 * setup()
293 * performs all ONE TIME setup for this test
294 */
subrata_modak56207ce2009-03-23 13:35:39 +0000295void setup(void)
plars865695b2001-08-27 22:15:12 +0000296{
Garrett Cooper2c282152010-12-16 00:55:50 -0800297
plars865695b2001-08-27 22:15:12 +0000298 tst_sig(FORK, DEF_HANDLER, cleanup);
299
300 /* Set up the expected error numbers for -e option */
301 TEST_EXP_ENOS(exp_enos);
302
plars865695b2001-08-27 22:15:12 +0000303 TEST_PAUSE;
304
305 /* Create a unique temporary directory and chdir() to it. */
306 tst_tmpdir();
307
308 strcpy(name, DATA_FILE);
309 sprintf(f_name, "%s.%d", name, getpid());
subrata_modakbdbaec52009-02-26 12:14:51 +0000310
subrata_modak56207ce2009-03-23 13:35:39 +0000311 bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
312 if (bad_addr == MAP_FAILED) {
313 tst_brkm(TBROK, cleanup, "mmap failed");
314 }
315 wr_iovec[1].iov_base = bad_addr;
plars865695b2001-08-27 22:15:12 +0000316
317}
318
319/*
320 * cleanup()
321 * performs all ONE TIME cleanup for this test at
322 * completion or premature exit
323 */
subrata_modak56207ce2009-03-23 13:35:39 +0000324void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000325{
326 /*
327 * print timing stats if that option was specified.
328 * print errno log if that option was specified.
329 */
330 TEST_CLEANUP;
331
332 if (unlink(f_name) < 0) {
333 tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
334 f_name, errno);
335 }
336 tst_rmdir();
337
plars865695b2001-08-27 22:15:12 +0000338}
339
340/*
341 * sighandler()
342 * Signal handler function for SIGTERM and SIGPIPE
343 */
subrata_modak56207ce2009-03-23 13:35:39 +0000344void sighandler(int sig)
plars865695b2001-08-27 22:15:12 +0000345{
subrata_modak56207ce2009-03-23 13:35:39 +0000346 switch (sig) {
347 case SIGTERM:
348 break;
349 case SIGPIPE:
350 ++in_sighandler;
351 return;
plars865695b2001-08-27 22:15:12 +0000352 default:
subrata_modak56207ce2009-03-23 13:35:39 +0000353 tst_resm(TFAIL, "sighandler() received invalid signal "
354 ": %d", sig);
355 break;
plars865695b2001-08-27 22:15:12 +0000356 }
357
358 if ((unlink(f_name) < 0) && (errno != ENOENT)) {
359 tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
360 f_name, errno);
361 cleanup();
Garrett Cooper53740502010-12-16 00:04:01 -0800362 }
plars865695b2001-08-27 22:15:12 +0000363 exit(sig);
364}
365
366/*
367 * l_seek()
368 * Wrap around for regular lseek function for giving error message
369 */
subrata_modak56207ce2009-03-23 13:35:39 +0000370long l_seek(int fdesc, long offset, int whence)
plars865695b2001-08-27 22:15:12 +0000371{
372 if (lseek(fdesc, offset, whence) < 0) {
373 tst_resm(TFAIL, "lseek Failed : errno = %d", errno);
374 fail = 1;
375 }
subrata_modak43337a32009-02-26 11:43:51 +0000376 return 0;
Garrett Cooper2c282152010-12-16 00:55:50 -0800377}