Home | History | Annotate | Download | only in readv
      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 
     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 
    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  */
    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  */
    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 
    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 
    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 
    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