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