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