• 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  * 	readv02.c
23  *
24  * DESCRIPTION
25  *	Testcase to check the error conditions of the readv(2) system call.
26  *
27  * CALLS
28  * 	readv()
29  *
30  * ALGORITHM
31  *	Create a IO vector, and attempt to readv() various components of it.
32  *
33  * USAGE
34  *	readv02
35  *
36  * HISTORY
37  *	07/2001 Ported by Wayne Boyer
38  *
39  * RESTRICTIONS
40  * 	None
41  */
42 #include <sys/types.h>
43 #include <sys/uio.h>
44 #include <fcntl.h>
45 #include <sys/mman.h>
46 #include <memory.h>
47 #include <errno.h>
48 
49 #include "test.h"
50 
51 #define	K_1	1024
52 #define	M_1	K_1 * K_1
53 #define	G_1	M_1 * K_1
54 
55 #define	NBUFS		4
56 #define	CHUNK		64
57 #define	MAX_IOVEC	16
58 #define DATA_FILE	"readv_data_file"
59 
60 char buf1[K_1], buf2[K_1], buf3[K_1];
61 
62 struct iovec rd_iovec[MAX_IOVEC] = {
63 	/* iov_base *//* iov_len */
64 
65 	/* Test case #1 */
66 	{buf2, -1},
67 	{(buf2 + CHUNK), CHUNK},
68 	{(buf2 + CHUNK * 2), CHUNK},
69 
70 	/* Test case #2 */
71 	{(buf2 + CHUNK * 3), G_1},
72 	{(buf2 + CHUNK * 4), G_1},
73 	{(buf2 + CHUNK * 5), G_1},
74 
75 	/* Test case #3 */
76 	{(caddr_t) - 1, CHUNK},
77 	{(buf2 + CHUNK * 6), CHUNK},
78 	{(buf2 + CHUNK * 8), CHUNK},
79 
80 	/* Test case #4 */
81 	{(buf2 + CHUNK * 9), CHUNK}
82 };
83 
84 char f_name[K_1];
85 
86 int fd[4];
87 char *buf_list[NBUFS];
88 
89 char *TCID = "readv02";
90 int TST_TOTAL = 1;
91 
92 char *bad_addr = 0;
93 
94 int init_buffs(char **);
95 int fill_mem(char *, int, int);
96 long l_seek(int, long, int);
97 char *getenv();
98 void setup();
99 void cleanup();
100 
main(int ac,char ** av)101 int main(int ac, char **av)
102 {
103 	int lc;
104 
105 	tst_parse_opts(ac, av, NULL, NULL);
106 
107 	setup();
108 
109 	/* The following loop checks looping state if -i option given */
110 	for (lc = 0; TEST_LOOPING(lc); lc++) {
111 
112 		/* reset tst_count in case we are looping */
113 		tst_count = 0;
114 
115 //test1:
116 		if (readv(fd[0], rd_iovec, 1) < 0) {
117 			if (errno != EINVAL) {
118 				tst_resm(TFAIL, "readv() set an illegal errno:"
119 					 " expected: EINVAL, got %d", errno);
120 			} else {
121 				tst_resm(TPASS, "got EINVAL");
122 			}
123 		} else {
124 			tst_resm(TFAIL, "Error: readv returned a positive "
125 				 "value");
126 		}
127 
128 //test2:
129 		l_seek(fd[0], CHUNK * 6, 0);
130 		if (readv(fd[0], (rd_iovec + 6), 3) < 0) {
131 			if (errno != EFAULT) {
132 				tst_resm(TFAIL, "expected errno = EFAULT, "
133 					 "got %d", errno);
134 			} else {
135 				tst_resm(TPASS, "got EFAULT");
136 			}
137 			if (memcmp((buf_list[0] + CHUNK * 6),
138 				   (buf_list[1] + CHUNK * 6), CHUNK * 3) != 0) {
139 				tst_resm(TFAIL, "Error: readv() partially "
140 					 "overlaid buf[2]");
141 			}
142 		} else {
143 			tst_resm(TFAIL, "Error: readv returned a positive "
144 				 "value");
145 		}
146 
147 //test3:
148 		if (readv(fd[1], (rd_iovec + 9), 1) < 0) {
149 			if (errno != EBADF) {
150 				tst_resm(TFAIL, "expected errno = EBADF, "
151 					 "got %d", errno);
152 			} else {
153 				tst_resm(TPASS, "got EBADF");
154 			}
155 		} else {
156 			tst_resm(TFAIL, "Error: readv returned a positive "
157 				 "value");
158 		}
159 
160 //test4:
161 		l_seek(fd[0], CHUNK * 10, 0);
162 		if (readv(fd[0], (rd_iovec + 10), -1) < 0) {
163 			if (errno != EINVAL) {
164 				tst_resm(TFAIL, "expected errno = EINVAL, "
165 					 "got %d", errno);
166 			} else {
167 				tst_resm(TPASS, "got EINVAL");
168 			}
169 		} else {
170 			tst_resm(TFAIL, "Error: readv returned a positive "
171 				 "value");
172 		}
173 
174 	}
175 	close(fd[0]);
176 	close(fd[1]);
177 	cleanup();
178 	tst_exit();
179 
180 }
181 
182 /*
183  * setup() - performs all ONE TIME setup for this test.
184  */
setup(void)185 void setup(void)
186 {
187 	int nbytes;
188 
189 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
190 
191 	TEST_PAUSE;
192 
193 	/* make a temporary directory and cd to it */
194 	tst_tmpdir();
195 
196 	buf_list[0] = buf1;
197 	buf_list[1] = buf2;
198 	buf_list[2] = buf3;
199 	buf_list[3] = NULL;
200 
201 	init_buffs(buf_list);
202 
203 	sprintf(f_name, "%s.%d", DATA_FILE, getpid());
204 
205 	if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
206 		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
207 			 "errno = %d", f_name, errno);
208 	} else {
209 		if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1) {
210 			tst_brkm(TBROK, cleanup, "write failed: nbytes "
211 				 "= %d " "errno = %d", nbytes, errno);
212 		}
213 	}
214 
215 	if (close(fd[0]) < 0) {
216 		tst_brkm(TBROK, cleanup, "close failed: errno = %d", errno);
217 	}
218 
219 	if ((fd[0] = open(f_name, O_RDONLY, 0666)) < 0) {
220 		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
221 			 "errno = %d", f_name, errno);
222 	}
223 
224 	fd[1] = -1;		/* Invalid file descriptor */
225 
226 	bad_addr = mmap(0, 1, PROT_NONE,
227 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
228 	if (bad_addr == MAP_FAILED) {
229 		tst_brkm(TBROK, cleanup, "mmap failed");
230 	}
231 	rd_iovec[6].iov_base = bad_addr;
232 }
233 
234 /*
235  * cleanup() - performs all ONE TIME cleanup for this test at
236  *	       completion or premature exit.
237  */
cleanup(void)238 void cleanup(void)
239 {
240 	if (unlink(f_name) < 0) {
241 		tst_brkm(TBROK, NULL, "unlink FAILED: file %s, errno %d",
242 			 f_name, errno);
243 	}
244 	tst_rmdir();
245 
246 }
247 
init_buffs(char * pbufs[])248 int init_buffs(char *pbufs[])
249 {
250 	int i;
251 
252 	for (i = 0; pbufs[i] != NULL; i++) {
253 		switch (i) {
254 		case 0:
255 		 /*FALLTHROUGH*/ case 1:
256 			fill_mem(pbufs[i], 0, 1);
257 			break;
258 
259 		case 2:
260 			fill_mem(pbufs[i], 1, 0);
261 			break;
262 
263 		default:
264 			tst_brkm(TBROK, cleanup, "Error in init_buffs()");
265 		}
266 	}
267 	return 0;
268 }
269 
fill_mem(char * c_ptr,int c1,int c2)270 int fill_mem(char *c_ptr, int c1, int c2)
271 {
272 	int count;
273 
274 	for (count = 1; count <= K_1 / CHUNK; count++) {
275 		if (count & 0x01) {	/* if odd */
276 			memset(c_ptr, c1, CHUNK);
277 		} else {	/* if even */
278 			memset(c_ptr, c2, CHUNK);
279 		}
280 	}
281 	return 0;
282 }
283 
l_seek(int fdesc,long offset,int whence)284 long l_seek(int fdesc, long offset, int whence)
285 {
286 	if (lseek(fdesc, offset, whence) < 0) {
287 		tst_brkm(TBROK, cleanup, "lseek Failed : errno = %d", errno);
288 	}
289 	return 0;
290 }
291