• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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