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