• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * NAME
22  *	writev05.c
23  *
24  * DESCRIPTION
25  *	These testcases are written to test writev() on sparse files. This
26  *	is same as writev02.c. But the initial write() with valid data is
27  *	done at the beginning of the file.
28  *
29  * USAGE:  <for command-line>
30  *      writev05 [-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
41  *      04/2002 wjhuie sigset cleanups
42  *
43  * Restrictions
44  *	NONE
45  */
46 
47 #include <sys/types.h>
48 #include <signal.h>
49 #include <sys/uio.h>
50 #include <fcntl.h>
51 #include <memory.h>
52 #include <errno.h>
53 #include "test.h"
54 #include <sys/mman.h>
55 
56 #define	K_1	8192
57 
58 #define	NBUFS		2
59 #define	CHUNK		K_1	/* single chunk */
60 #define	MAX_IOVEC	2
61 #define	DATA_FILE	"writev_data_file"
62 
63 char buf1[K_1];
64 char buf2[K_1];
65 char buf3[K_1];
66 
67 char *bad_addr = 0;
68 
69 struct iovec wr_iovec[MAX_IOVEC] = {
70 	{(caddr_t) - 1, CHUNK},
71 	{NULL, 0}
72 };
73 
74 char name[K_1], f_name[K_1];
75 int fd[2], in_sighandler;
76 char *buf_list[NBUFS];
77 
78 char *TCID = "writev05";
79 int TST_TOTAL = 1;
80 
81 void sighandler(int);
82 long l_seek(int, long, int);
83 void setup(void);
84 void cleanup(void);
85 int fail;
86 
87 #if !defined(UCLINUX)
88 
main(int argc,char ** argv)89 int main(int argc, char **argv)
90 {
91 	int lc;
92 
93 	int nbytes;
94 
95 	tst_parse_opts(argc, argv, NULL, NULL);
96 
97 	setup();		/* set "tstdir", and "testfile" vars */
98 
99 	/* The following loop checks looping state if -i option given */
100 	for (lc = 0; TEST_LOOPING(lc); lc++) {
101 
102 		/* reset tst_count in case we are looping */
103 		tst_count = 0;
104 
105 		buf_list[0] = buf1;
106 		buf_list[1] = buf2;
107 
108 		fd[1] = -1;	/* Invalid file descriptor */
109 
110 		if (signal(SIGTERM, sighandler) == SIG_ERR) {
111 			perror("signal");
112 			tst_resm(TFAIL, "signal() SIGTERM FAILED");
113 			cleanup();
114 		}
115 
116 		if (signal(SIGPIPE, sighandler) == SIG_ERR) {
117 			perror("signal");
118 			tst_resm(TFAIL, "signal() SIGPIPE FAILED");
119 			cleanup();
120 		}
121 
122 		/* Fill the buf_list[0] and buf_list[1] with 0 zeros */
123 		memset(buf_list[0], 0, K_1);
124 		memset(buf_list[1], 0, K_1);
125 
126 		if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
127 			tst_resm(TFAIL, "open(2) failed: fname = %s, "
128 				 "errno = %d", f_name, errno);
129 			cleanup();
130 		} else {
131 			if ((nbytes = write(fd[0], buf_list[1], K_1)) != K_1) {
132 				tst_resm(TFAIL, "write(2) failed: nbytes "
133 					 "= %d, errno = %d", nbytes, errno);
134 				cleanup();
135 			}
136 		}
137 
138 		if (close(fd[0]) < 0) {
139 			tst_resm(TFAIL, "close failed: errno = %d", errno);
140 			cleanup();
141 		}
142 
143 		if ((fd[0] = open(f_name, O_RDWR, 0666)) < 0) {
144 			tst_resm(TFAIL, "open failed: fname = %s, errno = %d",
145 				 f_name, errno);
146 			cleanup();
147 		}
148 
149 		/*
150 		 * In this block we are trying to call writev() with invalid
151 		 * vector to be written in a sparse file. This will return
152 		 * EFAULT. At the same time, check should be made whether
153 		 * the scheduled write() with valid data is done correctly
154 		 * or not.
155 		 */
156 //block1:
157 		tst_resm(TINFO, "Enter block 1");
158 		fail = 0;
159 
160 		l_seek(fd[0], 0, 0);
161 		TEST(writev(fd[0], wr_iovec, 2));
162 		if (TEST_RETURN < 0) {
163 			if (TEST_ERRNO == EFAULT) {
164 				tst_resm(TINFO, "Received EFAULT as expected");
165 			} else {
166 				tst_resm(TFAIL, "Expected EFAULT, got %d",
167 					 TEST_ERRNO);
168 				fail = 1;
169 			}
170 			l_seek(fd[0], K_1, 0);
171 			if ((nbytes = read(fd[0], buf_list[0], CHUNK)) != 0) {
172 				tst_resm(TFAIL, "Expected nbytes = 0, got "
173 					 "%d", nbytes);
174 				fail = 1;
175 			}
176 		} else {
177 			tst_resm(TFAIL, "Error writev returned a positive "
178 				 "value");
179 			fail = 1;
180 		}
181 		if (fail) {
182 			tst_resm(TINFO, "block 1 FAILED");
183 		} else {
184 			tst_resm(TINFO, "block 1 PASSED");
185 		}
186 		tst_resm(TINFO, "Exit block 1");
187 	}
188 	close(fd[0]);
189 	close(fd[1]);
190 	cleanup();
191 	tst_exit();
192 
193 }
194 
195 #else
196 
main(void)197 int main(void)
198 {
199 	tst_resm(TINFO, "test is not available on uClinux");
200 	tst_exit();
201 }
202 
203 #endif /* if !defined(UCLINUX) */
204 
205 /*
206  * setup()
207  *	performs all ONE TIME setup for this test
208  */
setup(void)209 void setup(void)
210 {
211 
212 	tst_sig(FORK, DEF_HANDLER, cleanup);
213 
214 	/* Pause if that option was specified.
215 	 * TEST_PAUSE contains the code to fork the test with the -i option.
216 	 * You want to make sure you do this before you create your temporary
217 	 * directory.
218 	 */
219 	TEST_PAUSE;
220 
221 	/* Create a unique temporary directory and chdir() to it. */
222 	tst_tmpdir();
223 
224 	strcpy(name, DATA_FILE);
225 	sprintf(f_name, "%s.%d", name, getpid());
226 
227 	bad_addr = mmap(0, 1, PROT_NONE,
228 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
229 	if (bad_addr == MAP_FAILED) {
230 		printf("mmap failed\n");
231 	}
232 	wr_iovec[0].iov_base = bad_addr;
233 
234 }
235 
236 /*
237  * cleanup()
238  *	performs all ONE TIME cleanup for this test at
239  *	completion or premature exit
240  */
cleanup(void)241 void cleanup(void)
242 {
243 
244 	if (unlink(f_name) < 0) {
245 		tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
246 			 f_name, errno);
247 	}
248 	tst_rmdir();
249 
250 }
251 
252 /*
253  * sighandler()
254  *	Signal handler for SIGTERM and SIGPIPE
255  */
sighandler(int sig)256 void sighandler(int sig)
257 {
258 	switch (sig) {
259 	case SIGTERM:
260 		break;
261 	case SIGPIPE:
262 		++in_sighandler;
263 		return;
264 	default:
265 		tst_resm(TFAIL, "sighandler() received invalid signal "
266 			 ": %d", sig);
267 		break;
268 	}
269 
270 	if ((unlink(f_name) < 0) && (errno != ENOENT)) {
271 		tst_resm(TFAIL, "unlink Failed--file = %s, errno = %d",
272 			 f_name, errno);
273 		cleanup();
274 	}
275 	exit(sig);
276 }
277 
278 /*
279  * l_seek()
280  *	Wrap around for regular lseek() to give error message on failure
281  */
l_seek(int fdesc,long offset,int whence)282 long l_seek(int fdesc, long offset, int whence)
283 {
284 	if (lseek(fdesc, offset, whence) < 0) {
285 		tst_resm(TFAIL, "lseek Failed : errno = %d", errno);
286 		fail = 1;
287 	}
288 	return 0;
289 }
290