blob: ec6c68fbc546a496dafd1b3e4af805e5119916ca [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"
56#include "usctest.h"
plars865695b2001-08-27 22:15:12 +000057
58#define K_1 1024
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 = "writev03";
84int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000085
86void sighandler(int);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -080087void l_seek(int, off_t, int);
plars865695b2001-08-27 22:15:12 +000088void setup(void);
89void cleanup(void);
vapier6925ca32006-02-27 04:25:25 +000090
robbiew7d5c5172003-03-27 22:54:57 +000091int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000092{
subrata_modak56207ce2009-03-23 13:35:39 +000093 int lc; /* loop counter */
94 char *msg; /* message returned from parse_opts */
plars865695b2001-08-27 22:15:12 +000095
96 int nbytes;
97
Garrett Cooper2aca6fc2010-12-19 03:12:40 -080098 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +000099 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800100
plars865695b2001-08-27 22:15:12 +0000101 setup();
102
plars865695b2001-08-27 22:15:12 +0000103 for (lc = 0; TEST_LOOPING(lc); lc++) {
104
plars865695b2001-08-27 22:15:12 +0000105 Tst_count = 0;
106
107 buf_list[0] = buf1;
108 buf_list[1] = buf2;
109 buf_list[2] = buf3;
Garrett Cooper45e285d2010-11-22 12:19:25 -0800110 buf_list[3] = NULL;
plars865695b2001-08-27 22:15:12 +0000111
subrata_modak56207ce2009-03-23 13:35:39 +0000112 fd[1] = -1; /* Invalid file descriptor */
plars865695b2001-08-27 22:15:12 +0000113
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800114 if (signal(SIGTERM, sighandler) == SIG_ERR)
115 tst_brkm(TBROK|TERRNO, cleanup,
116 "signal(SIGTERM, ..) failed");
plars865695b2001-08-27 22:15:12 +0000117
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800118 if (signal(SIGPIPE, sighandler) == SIG_ERR)
119 tst_brkm(TBROK|TERRNO, cleanup,
120 "signal(SIGPIPE, ..) failed");
plars865695b2001-08-27 22:15:12 +0000121
122 memset(buf_list[0], 0, K_1);
123 memset(buf_list[1], 0, K_1);
124
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800125 if ((fd[0] = open(f_name, O_WRONLY|O_CREAT, 0666)) == -1)
126 tst_brkm(TBROK|TERRNO, cleanup,
127 "open(.., O_WRONLY|O_CREAT, ..) failed");
128 else
129 if ((nbytes = write(fd[0], buf_list[1], K_1)) != K_1)
130 tst_brkm(TFAIL|TERRNO, cleanup, "write failed");
plars865695b2001-08-27 22:15:12 +0000131
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800132 if (close(fd[0]) < 0)
133 tst_brkm(TBROK|TERRNO, cleanup, "close failed");
plars865695b2001-08-27 22:15:12 +0000134
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800135 if ((fd[0] = open(f_name, O_RDWR, 0666)) == -1)
136 tst_brkm(TBROK|TERRNO, cleanup,
137 "open(.., O_RDWR, ..) failed");
robbiew7d5c5172003-03-27 22:54:57 +0000138//block1:
plars865695b2001-08-27 22:15:12 +0000139 tst_resm(TINFO, "Enter block 1");
subrata_modak56207ce2009-03-23 13:35:39 +0000140
plars865695b2001-08-27 22:15:12 +0000141 /*
142 * In this block we are trying to call writev() with
143 * partially valid data. This should return the valid number
144 * of bytes written in the vector. If it returns EFAULT, it
145 * is an error. And after returning the number of valid
146 * bytes written, the check should be made to verify the
147 * contents of the first valid write() scheduled.
148 */
149
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800150 if (writev(fd[0], wr_iovec, 3) == -1) {
151 if (errno == EFAULT)
152 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000153 } else {
154 l_seek(fd[0], 0, 0);
155 read(fd[0], buf_list[0], CHUNK);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800156 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0)
plars865695b2001-08-27 22:15:12 +0000157 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000158 }
159 tst_resm(TINFO, "Exit block 1");
160
robbiew7d5c5172003-03-27 22:54:57 +0000161//block2:
plars865695b2001-08-27 22:15:12 +0000162 tst_resm(TINFO, "Enter block 2");
plars865695b2001-08-27 22:15:12 +0000163
164 /*
165 * In this block we are trying to over write the contents by
166 * calling writev() with partially valid data. It should
167 * return the valid number of bytes written but not EFAULT.
168 * Also the check should be made whether the initial write()
169 * scheduled is done correctly or not.
170 */
171 l_seek(fd[0], 0, 0);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800172 if (writev(fd[0], wr_iovec, 3) == -1) {
173 if (errno == EFAULT)
174 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000175 } else {
176 l_seek(fd[0], 0, 0);
177 read(fd[0], buf_list[0], CHUNK);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800178 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0)
plars865695b2001-08-27 22:15:12 +0000179 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000180 }
181 tst_resm(TINFO, "Exit block 2");
182
robbiew7d5c5172003-03-27 22:54:57 +0000183//block3:
plars865695b2001-08-27 22:15:12 +0000184 tst_resm(TINFO, "Enter block 3");
plars865695b2001-08-27 22:15:12 +0000185
186 /*
187 * In this block, we are trying to call writev() by going to
188 * some end position of the file. Here writev() is called
189 * with partially valid data, and this will return the
190 * number of valid bytes written and not EFAULT. Also, the
191 * check should be made whether the inital write() that is
192 * scheduled with valid data is done correctly done or not.
193 */
194
195 l_seek(fd[0], 8192, 0);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800196 if (writev(fd[0], wr_iovec, 3) == -1) {
plars865695b2001-08-27 22:15:12 +0000197 TEST_ERROR_LOG(errno);
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800198 if (errno == EFAULT)
199 tst_resm(TFAIL, "Got EFAULT");
plars865695b2001-08-27 22:15:12 +0000200 } else {
201 l_seek(fd[0], 0, 0);
202 read(fd[0], buf_list[0], CHUNK);
203 if (memcmp(buf_list[0], buf_list[1], CHUNK) != 0) {
204 tst_resm(TFAIL, "writev overwrote the file");
plars865695b2001-08-27 22:15:12 +0000205 }
206 }
207
plars865695b2001-08-27 22:15:12 +0000208 tst_resm(TINFO, "Exit block 3");
209 }
210 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800211 tst_exit();
vapier6925ca32006-02-27 04:25:25 +0000212}
213
plars865695b2001-08-27 22:15:12 +0000214/*
215 * setup()
216 * performs all ONE TIME setup for this test
217 */
subrata_modak56207ce2009-03-23 13:35:39 +0000218void setup(void)
plars865695b2001-08-27 22:15:12 +0000219{
Garrett Cooper2c282152010-12-16 00:55:50 -0800220
plars865695b2001-08-27 22:15:12 +0000221 tst_sig(FORK, DEF_HANDLER, cleanup);
222
223 /* Set up the expected error numbers for -e option */
subrata_modak56207ce2009-03-23 13:35:39 +0000224 TEST_EXP_ENOS(exp_enos);
plars865695b2001-08-27 22:15:12 +0000225
226 /* Pause if that option was specified.
227 * TEST_PAUSE contains the code to fork the test with the -i option.
228 * You want to make sure you do this before you create your temporary
229 * directory.
230 */
subrata_modak56207ce2009-03-23 13:35:39 +0000231 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000232
233 strcpy(name, DATA_FILE);
234 sprintf(f_name, "%s.%d", name, getpid());
subrata_modakbdbaec52009-02-26 12:14:51 +0000235
subrata_modak56207ce2009-03-23 13:35:39 +0000236 bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
vapier0722a2b2006-05-12 15:44:11 +0000237 if (bad_addr == MAP_FAILED) {
robbiew169e09b2005-08-30 17:24:45 +0000238 tst_brkm(TBROK, cleanup, "mmap failed");
239 }
240 wr_iovec[1].iov_base = bad_addr;
plars865695b2001-08-27 22:15:12 +0000241 tst_tmpdir();
242}
243
244/*
245 * cleanup()
246 * performs all ONE TIME cleanup for this test at
247 * completion or premature exit
248 */
subrata_modak56207ce2009-03-23 13:35:39 +0000249void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000250{
plars865695b2001-08-27 22:15:12 +0000251 TEST_CLEANUP;
252
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800253 close(fd[0]);
254 close(fd[1]);
255
256 if (unlink(f_name) == -1)
257 tst_resm(TFAIL, "unlink failed");
plars865695b2001-08-27 22:15:12 +0000258 tst_rmdir();
259
plars865695b2001-08-27 22:15:12 +0000260}
261
subrata_modak56207ce2009-03-23 13:35:39 +0000262void sighandler(int sig)
plars865695b2001-08-27 22:15:12 +0000263{
subrata_modak56207ce2009-03-23 13:35:39 +0000264 switch (sig) {
265 case SIGTERM:
266 break;
267 case SIGPIPE:
268 ++in_sighandler;
269 return;
plars865695b2001-08-27 22:15:12 +0000270 default:
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800271 tst_resm(TBROK, "sighandler received invalid signal : %d", sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000272 break;
plars865695b2001-08-27 22:15:12 +0000273 }
plars865695b2001-08-27 22:15:12 +0000274}
275
276/*
277 * l_seek()
278 * Wrap around for regular lseek function for giving error message
279 */
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800280void l_seek(int fdesc, off_t offset, int whence)
plars865695b2001-08-27 22:15:12 +0000281{
Garrett Cooper2aca6fc2010-12-19 03:12:40 -0800282 if (lseek(fdesc, offset, whence) == -1)
283 tst_brkm(TBROK|TERRNO, cleanup, "lseek failed");
284}