1 /*
2 * Copyright (c) 2015-2016 Fujitsu Ltd.
3 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License
14 * alone with this program.
15 */
16
17 /*
18 * Test Name: preadv02
19 *
20 * Description:
21 * 1) preadv(2) fails if iov_len is invalid.
22 * 2) preadv(2) fails if the vector count iovcnt is less than zero.
23 * 3) preadv(2) fails if offset is negative.
24 * 4) preadv(2) fails when attempts to read into a invalid address.
25 * 5) preadv(2) fails if file descriptor is invalid.
26 * 6) preadv(2) fails if file descriptor is not open for reading.
27 * 7) preadv(2) fails when fd refers to a directory.
28 * 8) preadv(2) fails if fd is associated with a pipe.
29 *
30 * Expected Result:
31 * 1) preadv(2) should return -1 and set errno to EINVAL.
32 * 2) preadv(2) should return -1 and set errno to EINVAL.
33 * 3) preadv(2) should return -1 and set errno to EINVAL.
34 * 4) preadv(2) should return -1 and set errno to EFAULT.
35 * 5) preadv(2) should return -1 and set errno to EBADF.
36 * 6) preadv(2) should return -1 and set errno to EBADF.
37 * 7) preadv(2) should return -1 and set errno to EISDIR.
38 * 8) preadv(2) should return -1 and set errno to ESPIPE.
39 */
40
41 #include <sys/uio.h>
42 #include <unistd.h>
43 #include "tst_test.h"
44 #include "preadv.h"
45
46 #define CHUNK 64
47
48 static int fd1;
49 static int fd2;
50 static int fd3 = -1;
51 static int fd4;
52 static int fd5[2];
53
54 static char buf[CHUNK];
55
56 static struct iovec rd_iovec1[] = {
57 {buf, -1},
58 };
59
60 static struct iovec rd_iovec2[] = {
61 {buf, CHUNK},
62 };
63
64 static struct iovec rd_iovec3[] = {
65 {(char *)-1, CHUNK},
66 };
67
68 static struct tcase {
69 int *fd;
70 struct iovec *name;
71 int count;
72 off_t offset;
73 int exp_err;
74 } tcases[] = {
75 {&fd1, rd_iovec1, 1, 0, EINVAL},
76 {&fd1, rd_iovec2, -1, 0, EINVAL},
77 {&fd1, rd_iovec2, 1, -1, EINVAL},
78 {&fd1, rd_iovec3, 1, 0, EFAULT},
79 {&fd3, rd_iovec2, 1, 0, EBADF},
80 {&fd2, rd_iovec2, 1, 0, EBADF},
81 {&fd4, rd_iovec2, 1, 0, EISDIR},
82 {&fd5[0], rd_iovec2, 1, 0, ESPIPE}
83 };
84
verify_preadv(unsigned int n)85 static void verify_preadv(unsigned int n)
86 {
87 struct tcase *tc = &tcases[n];
88
89 TEST(preadv(*tc->fd, tc->name, tc->count, tc->offset));
90
91 if (TEST_RETURN == 0) {
92 tst_res(TFAIL, "preadv() succeeded unexpectedly");
93 return;
94 }
95
96 if (TEST_ERRNO == tc->exp_err) {
97 tst_res(TPASS | TTERRNO, "preadv() failed as expected");
98 return;
99 }
100
101 tst_res(TFAIL | TTERRNO, "preadv() failed unexpectedly, expected %s",
102 tst_strerrno(tc->exp_err));
103 }
104
setup(void)105 static void setup(void)
106 {
107 fd1 = SAFE_OPEN("file1", O_RDWR | O_CREAT, 0644);
108 SAFE_FTRUNCATE(fd1, getpagesize());
109 fd2 = SAFE_OPEN("file2", O_WRONLY | O_CREAT, 0644);
110 fd4 = SAFE_OPEN(".", O_RDONLY);
111 SAFE_PIPE(fd5);
112 }
113
cleanup(void)114 static void cleanup(void)
115 {
116 if (fd1 > 0 && close(fd1))
117 tst_res(TWARN | TERRNO, "failed to close file");
118
119 if (fd2 > 0 && close(fd2))
120 tst_res(TWARN | TERRNO, "failed to close file");
121
122 if (fd4 > 0 && close(fd4))
123 tst_res(TWARN | TERRNO, "failed to close file");
124
125 if (fd5[0] > 0 && close(fd5[0]))
126 tst_res(TWARN | TERRNO, "failed to close file");
127
128 if (fd5[1] > 0 && close(fd5[1]))
129 tst_res(TWARN | TERRNO, "failed to close file");
130 }
131
132 static struct tst_test test = {
133 .tid = "preadv02",
134 .tcnt = ARRAY_SIZE(tcases),
135 .setup = setup,
136 .cleanup = cleanup,
137 .test = verify_preadv,
138 .min_kver = "2.6.30",
139 .needs_tmpdir = 1,
140 };
141