1 /*
2 *
3 * Copyright (c) Red Hat Inc., 2007
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 * posix_fadvise03.c
23 *
24 * DESCRIPTION
25 * Check the value that posix_fadvise returns for wrong ADVISE value.
26 *
27 * USAGE
28 * posix_fadvise03
29 *
30 * HISTORY
31 * 11/2007 Initial version by Masatake YAMATO <yamato@redhat.com>
32 *
33 * RESTRICTIONS
34 * None
35 */
36
37 #define _XOPEN_SOURCE 600
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include <limits.h>
43 #include "test.h"
44 #include "safe_macros.h"
45
46 #include "lapi/syscalls.h"
47 #ifndef _FILE_OFFSET_BITS
48 #define _FILE_OFFSET_BITS 32
49 #endif
50
51 #ifndef __NR_fadvise64
52 #define __NR_fadvise64 0
53 #endif
54
55 void setup();
56 void cleanup();
57
58 TCID_DEFINE(posix_fadvise03);
59
60 #ifndef ANDROID
61 char fname[] = "/bin/cat"; /* test executable to open */
62 #else
63 char fname[] = "/system/bin/cat"; /* test executable to open */
64 #endif
65 int fd = -1; /* initialized in open */
66
67 int expected_error = EINVAL;
68
69 int defined_advise[] = {
70 POSIX_FADV_NORMAL,
71 POSIX_FADV_SEQUENTIAL,
72 POSIX_FADV_RANDOM,
73 POSIX_FADV_WILLNEED,
74 #if defined(__s390__) && __WORDSIZE == 32
75 /* POSIX_FADV_DONTNEED and POSIX_FADV_NOREUSE are 6,7 on 31bit s390,
76 * but the kernel accepts 4,5 as well and rewrites them internally,
77 * see Linux kernel commit 068e1b94bbd268f375349f68531829c8b7c210bc
78 *
79 * since header definitions are incomplete - posix fcntl.h doesn't care
80 * and defines them as 4,5 while linux/fadvise.h (which uses 6,7)
81 * matches only 64bit - we need to hardcode the values here for
82 * all 4 cases, unfortunately
83 */
84 4, /* POSIX_FADV_DONTNEED */
85 5, /* POSIX_FADV_NOREUSE */
86 6, /* POSIX_FADV_DONTNEED */
87 7, /* POSIX_FADV_NOREUSE */
88 #else
89 POSIX_FADV_DONTNEED,
90 POSIX_FADV_NOREUSE,
91 #endif
92 };
93
94 #define defined_advise_total ARRAY_SIZE(defined_advise)
95
96 #if 0
97 /* Too many test cases. */
98 int TST_TOTAL = (INT_MAX - defined_advise_total);
99 int advise_limit = INT_MAX;
100 #else
101 int TST_TOTAL = (32 - defined_advise_total);
102 int advise_limit = 32;
103 #endif /* 0 */
104
105 /* is_defined_advise:
106 Return 1 if advise is in defined_advise.
107 Return 0 if not. */
is_defined_advise(int advise)108 static int is_defined_advise(int advise)
109 {
110 int i;
111 for (i = 0; i < defined_advise_total; i++) {
112 if (defined_advise[i] == advise)
113 return 1;
114 }
115
116 return 0;
117 }
118
main(int ac,char ** av)119 int main(int ac, char **av)
120 {
121 int lc;
122 int advise;
123
124 /* Check this system has fadvise64 system which is used
125 in posix_fadvise. */
126 if ((_FILE_OFFSET_BITS != 64) && (__NR_fadvise64 == 0)) {
127 tst_resm(TWARN,
128 "This test can only run on kernels that implements ");
129 tst_resm(TWARN, "fadvise64 which is used from posix_fadvise");
130 exit(0);
131 }
132
133 /*
134 * parse standard options
135 */
136 tst_parse_opts(ac, av, NULL, NULL);
137
138 /*
139 * perform global setup for test
140 */
141 setup();
142
143 /*
144 * check looping state if -i option given on the command line
145 */
146 for (lc = 0; TEST_LOOPING(lc); lc++) {
147
148 tst_count = 0;
149
150 /* loop through the test cases */
151 for (advise = 0; advise < advise_limit; advise++) {
152
153 /* Don't use defiend advise as an argument. */
154 if (is_defined_advise(advise)) {
155 continue;
156 }
157
158 TEST(posix_fadvise(fd, 0, 0, advise));
159
160 if (TEST_RETURN == 0) {
161 tst_resm(TFAIL, "call succeeded unexpectedly");
162 continue;
163 }
164
165 /* Man page says:
166 "On error, an error number is returned." */
167 if (TEST_RETURN == expected_error) {
168 tst_resm(TPASS,
169 "expected failure - "
170 "returned value = %ld, advise = %d : %s",
171 TEST_RETURN,
172 advise, strerror(TEST_RETURN));
173 } else {
174 tst_resm(TFAIL,
175 "unexpected return value - %ld : %s, advise %d - "
176 "expected %d",
177 TEST_RETURN,
178 strerror(TEST_RETURN),
179 advise, expected_error);
180 }
181 }
182 }
183
184 /*
185 * cleanup and exit
186 */
187 cleanup();
188
189 tst_exit();
190 }
191
192 /*
193 * setup() - performs all ONE TIME setup for this test.
194 */
setup(void)195 void setup(void)
196 {
197
198 tst_sig(NOFORK, DEF_HANDLER, cleanup);
199
200 TEST_PAUSE;
201
202 fd = SAFE_OPEN(cleanup, fname, O_RDONLY);
203 }
204
205 /*
206 * cleanup() - performs all ONE TIME cleanup for this test at
207 * completion or premature exit.
208 */
cleanup(void)209 void cleanup(void)
210 {
211
212 if (fd != -1) {
213 close(fd);
214 }
215
216 }
217