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