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 <sys/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 60char buf1[K_1], buf2[K_1], buf3[K_1]; 61 62struct 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 84char f_name[K_1]; 85 86int fd[4]; 87char *buf_list[NBUFS]; 88 89char *TCID = "readv02"; 90int TST_TOTAL = 1; 91 92char *bad_addr = 0; 93 94int init_buffs(char **); 95int fill_mem(char *, int, int); 96long l_seek(int, long, int); 97char *getenv(); 98void setup(); 99void cleanup(); 100 101int 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 */ 185void 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 */ 238void 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 248int 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 270int 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 284long 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