• 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 
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