1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  *   07/2001 Ported by Wayne Boyer
4  *
5  * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
6  *
7  * This program is free software;  you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15  * the GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program;  if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  * DESCRIPTION
24  *	Testcase to check the basic functionality of the readv(2) system call.
25  *
26  * ALGORITHM
27  *	Create a IO vector, and attempt to readv() various components of it.
28  */
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/uio.h>
32 #include <fcntl.h>
33 #include <memory.h>
34 #include <errno.h>
35 
36 #include "test.h"
37 #include "safe_macros.h"
38 
39 #define	CHUNK		64
40 
41 char *TCID = "readv01";
42 int TST_TOTAL = 1;
43 
44 static char buf[CHUNK];
45 
46 static struct iovec rd_iovec[] = {
47 	{buf, CHUNK},
48 	{NULL, 0},
49 	{NULL, 0},
50 };
51 
52 static int fd;
53 
54 static void setup(void);
55 static void cleanup(void);
56 
57 int main(int ac, char **av)
58 {
59 	int lc, i, fail;
60 	char *vec;
61 
62 	tst_parse_opts(ac, av, NULL, NULL);
63 
64 	setup();
65 
66 	for (lc = 0; TEST_LOOPING(lc); lc++) {
67 		tst_count = 0;
68 
69 		SAFE_LSEEK(cleanup, fd, 0, SEEK_SET);
70 
71 		if (readv(fd, rd_iovec, 0) == -1)
72 			tst_resm(TFAIL | TERRNO, "readv failed unexpectedly");
73 		else
74 			tst_resm(TPASS, "readv read 0 io vectors");
75 
76 		memset(rd_iovec[0].iov_base, 0x00, CHUNK);
77 
78 		if (readv(fd, rd_iovec, 3) != CHUNK) {
79 			tst_resm(TFAIL, "readv failed reading %d bytes, "
80 				 "followed by two NULL vectors", CHUNK);
81 		} else {
82 			fail = 0;
83 			vec = rd_iovec[0].iov_base;
84 
85 			for (i = 0; i < CHUNK; i++) {
86 				if (vec[i] != 0x42)
87 					fail++;
88 			}
89 
90 			if (fail)
91 				tst_resm(TFAIL, "Wrong buffer content");
92 			else
93 				tst_resm(TPASS, "readv passed reading %d bytes "
94 				         "followed by two NULL vectors", CHUNK);
95 		}
96 	}
97 
98 	cleanup();
99 	tst_exit();
100 }
101 
102 static void setup(void)
103 {
104 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
105 
106 	TEST_PAUSE;
107 
108 	tst_tmpdir();
109 
110 	memset(buf, 0x42, sizeof(buf));
111 
112 	fd = SAFE_OPEN(cleanup, "data_file", O_WRONLY | O_CREAT, 0666);
113 	SAFE_WRITE(cleanup, 1, fd, buf, sizeof(buf));
114 	SAFE_CLOSE(cleanup, fd);
115 	fd = SAFE_OPEN(cleanup, "data_file", O_RDONLY);
116 }
117 
118 static void cleanup(void)
119 {
120 	if (fd > 0)
121 		close(fd);
122 
123 	tst_rmdir();
124 }
125