1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * 07/2001 Ported by Wayne Boyer
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 * DESCRIPTION
21 * test 1:
22 * Read with an invalid file descriptor, and expect an EBADF.
23 *
24 * test 2:
25 * The parameter passed to read is a directory, check if the errno is
26 * set to EISDIR.
27 *
28 * test 3:
29 * Buf is outside the accessible address space, expect an EFAULT.
30 *
31 * test 4:
32 * The file was opened with the O_DIRECT flag, and transfer sizes was not
33 * multiples of the logical block size of the file system, expect an
34 * EINVAL.
35 *
36 * test 5:
37 * The file was opened with the O_DIRECT flag, and the alignment of the
38 * user buffer was not multiples of the logical block size of the file
39 * system, expect an EINVAL.
40 */
41
42 #define _GNU_SOURCE
43
44 #include <stdio.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <sys/mman.h>
49 #include "test.h"
50 #include "safe_macros.h"
51
52 char *TCID = "read02";
53
54 static int badfd = -1;
55 static int fd2, fd3, fd4 = -1;
56 static char buf[BUFSIZ];
57 static void *outside_buf = (void *)-1;
58 static void *addr4;
59 static void *addr5;
60
61 static long fs_type;
62
63 static struct test_case_t {
64 int *fd;
65 void **buf;
66 size_t count;
67 int exp_error;
68 } TC[] = {
69 {&badfd, (void **)&buf, 1, EBADF},
70 {&fd2, (void **)&buf, 1, EISDIR},
71 #ifndef UCLINUX
72 {&fd3, &outside_buf, 1, EFAULT},
73 #endif
74 {&fd4, &addr4, 1, EINVAL},
75 {&fd4, &addr5, 4096, EINVAL},
76 };
77
78 int TST_TOTAL = ARRAY_SIZE(TC);
79 static void setup(void);
80 static void cleanup(void);
81 static void read_verify(const struct test_case_t *);
82
main(int ac,char ** av)83 int main(int ac, char **av)
84 {
85 int i;
86 int lc;
87
88 tst_parse_opts(ac, av, NULL, NULL);
89
90 setup();
91
92 for (lc = 0; TEST_LOOPING(lc); lc++) {
93 tst_count = 0;
94 for (i = 0; i < TST_TOTAL; i++)
95 read_verify(&TC[i]);
96 }
97 cleanup();
98 tst_exit();
99 }
100
setup(void)101 static void setup(void)
102 {
103 tst_sig(NOFORK, DEF_HANDLER, cleanup);
104
105 TEST_PAUSE;
106
107 tst_tmpdir();
108
109 fd2 = SAFE_OPEN(cleanup, ".", O_DIRECTORY);
110
111 SAFE_FILE_PRINTF(cleanup, "test_file", "A");
112
113 fd3 = SAFE_OPEN(cleanup, "test_file", O_RDWR);
114
115 #if !defined(UCLINUX)
116 outside_buf = SAFE_MMAP(cleanup, 0, 1, PROT_NONE,
117 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
118 #endif
119
120 addr4 = SAFE_MEMALIGN(cleanup, getpagesize(), (4096 * 10));
121 addr5 = addr4 + 1;
122
123 fs_type = tst_fs_type(cleanup, ".");
124 if (fs_type != TST_TMPFS_MAGIC)
125 fd4 = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_DIRECT);
126 }
127
read_verify(const struct test_case_t * test)128 static void read_verify(const struct test_case_t *test)
129 {
130 if (test->fd == &fd4 && *test->fd == -1) {
131 tst_resm(TCONF, "O_DIRECT not supported on %s filesystem",
132 tst_fs_type_name(fs_type));
133 return;
134 }
135
136 TEST(read(*test->fd, *test->buf, test->count));
137
138 if (*test->fd == fd4 && TEST_RETURN >= 0) {
139 tst_resm(TPASS,
140 "O_DIRECT unaligned reads fallbacks to buffered I/O");
141 return;
142 }
143
144 if (TEST_RETURN != -1) {
145 tst_resm(TFAIL, "call succeeded unexpectedly");
146 return;
147 }
148
149 if (TEST_ERRNO == test->exp_error) {
150 tst_resm(TPASS | TTERRNO, "expected failure");
151 } else {
152 tst_resm(TFAIL | TTERRNO, "unexpected error expected %d",
153 test->exp_error);
154 }
155 }
156
cleanup(void)157 static void cleanup(void)
158 {
159 free(addr4);
160
161 if (fd4 > 0)
162 close(fd4);
163
164 if (fd3 > 0)
165 close(fd3);
166
167 if (fd2 > 0)
168 close(fd2);
169
170 tst_rmdir();
171 }
172