1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
33 /* $Id: stat06.c,v 1.10 2009/11/02 13:57:19 subrata_modak Exp $ */
34 /**********************************************************
35 *
36 * OS Test - Silicon Graphics, Inc.
37 *
38 * TEST IDENTIFIER : stat06
39 *
40 * EXECUTED BY : anyone
41 *
42 * TEST TITLE : stat(2) negative path testcases
43 *
44 * PARENT DOCUMENT : None
45 *
46 * TEST CASE TOTAL : 7
47 *
48 * WALL CLOCK TIME : 1
49 *
50 * CPU TYPES : ALL
51 *
52 * AUTHOR : Richard Logan
53 *
54 * CO-PILOT : William Roske
55 *
56 * DATE STARTED : 03/30/94
57 *
58 * INITIAL RELEASE : UNICOS 7.0
59 *
60 * TEST CASES
61 *
62 * 1-7) See Testcases structure below.
63 *
64 * INPUT SPECIFICATIONS
65 * The standard options for system call tests are accepted.
66 * (See the parse_opts(3) man page).
67 * -h : print help and exit
68 *
69 * OUTPUT SPECIFICATIONS
70 *$
71 * DURATION
72 * Terminates - with frequency and infinite modes.
73 *
74 * SIGNALS
75 * Uses SIGUSR1 to pause before test if option set.
76 * (See the parse_opts(3) man page).
77 *
78 * RESOURCES
79 * None
80 *
81 * ENVIRONMENTAL NEEDS
82 * The libcuts.a and libsys.a libraries must be included in
83 * the compilation of this test.
84 *
85 * SPECIAL PROCEDURAL REQUIREMENTS
86 * None
87 *
88 * INTERCASE DEPENDENCIES
89 * None
90 *
91 * DETAILED DESCRIPTION
92 * This is a Phase I test for the stat(2) system call. It is intended
93 * to provide a limited exposure of the system call, for now. It
94 * should/will be extended when full functional tests are written for
95 * stat(2).
96 *
97 * Setup:
98 * Setup signal handling.
99 * Pause for SIGUSR1 if option specified.
100 *
101 * Test:
102 * Loop if the proper options are given.
103 * Execute system call
104 * Check return code, if system call failed (return=-1)
105 * Log the errno and Issue a FAIL message.
106 * Otherwise, Issue a PASS message.
107 *
108 * Cleanup:
109 * Print errno log and/or timing stats if options given
110 *
111 *
112 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
113
114 #include <sys/types.h>
115 #include <fcntl.h>
116 #include <sys/stat.h>
117 #include <sys/mman.h>
118 #include <errno.h>
119 #include <string.h>
120 #include <signal.h>
121 #include <setjmp.h>
122 #include <unistd.h>
123 #include "test.h"
124
125 void setup();
126 void cleanup();
127
128 char *TCID = "stat06";
129
130 char *bad_addr = 0;
131
132 #if !defined(UCLINUX)
133 int high_address_setup();
134 char High_address[64];
135 #endif
136 int longpath_setup();
137 int no_setup();
138 int filepath_setup();
139 char Longpathname[PATH_MAX + 2];
140 struct stat statbuf;
141 jmp_buf sig11_recover;
142 void sig11_handler(int sig);
143
144 struct test_case_t {
145 char *pathname;
146 struct stat *stbuf;
147 char *desc;
148 int exp_errno;
149 int (*setupfunc) ();
150 } Test_cases[] = {
151 {
152 "nonexistfile", &statbuf, "non-existent file", ENOENT, no_setup}, {
153 "", &statbuf, "path is empty string", ENOENT, no_setup}, {
154 "nefile/file", &statbuf, "path contains a non-existent file",
155 ENOENT, no_setup}, {
156 "file/file", &statbuf, "path contains a regular file",
157 ENOTDIR, filepath_setup}, {
158 Longpathname, &statbuf, "pathname too long", ENAMETOOLONG,
159 longpath_setup},
160 #if !defined(UCLINUX)
161 {
162 High_address, &statbuf, "address beyond address space", EFAULT,
163 high_address_setup}, {
164 (char *)-1, &statbuf, "negative address", EFAULT, no_setup},
165 #endif
166 {
167 NULL, NULL, NULL, 0, no_setup}
168 };
169
170 int TST_TOTAL = ARRAY_SIZE(Test_cases);
171
172 /***********************************************************************
173 * Main
174 ***********************************************************************/
main(int ac,char ** av)175 int main(int ac, char **av)
176 {
177 int lc;
178 char *fname;
179 char *desc;
180 int ind;
181 struct stat *stbuf;
182 struct sigaction sa, osa;
183
184 /***************************************************************
185 * parse standard options
186 ***************************************************************/
187 tst_parse_opts(ac, av, NULL, NULL);
188
189 /***************************************************************
190 * perform global setup for test
191 ***************************************************************/
192 setup();
193
194 /***************************************************************
195 * check looping state if -c option given
196 ***************************************************************/
197 for (lc = 0; TEST_LOOPING(lc); lc++) {
198
199 tst_count = 0;
200
201 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
202
203 fname = Test_cases[ind].pathname;
204 desc = Test_cases[ind].desc;
205 stbuf = Test_cases[ind].stbuf;
206
207 if (stbuf == (struct stat *)-1) {
208 /* special sig11 case */
209 sa.sa_handler = &sig11_handler;
210 sigemptyset(&sa.sa_mask);
211 sa.sa_flags = 0;
212
213 sigaction(SIGSEGV, NULL, &osa);
214 sigaction(SIGSEGV, &sa, NULL);
215
216 if (setjmp(sig11_recover)) {
217 TEST_RETURN = -1;
218 TEST_ERRNO = EFAULT;
219 } else {
220 TEST(stat(fname, stbuf));
221 }
222 sigaction(SIGSEGV, &osa, NULL);
223 } else {
224 /*
225 * Call stat(2)
226 */
227
228 TEST(stat(fname, stbuf));
229 }
230
231 /* check return code */
232 if (TEST_RETURN == -1) {
233 if (TEST_ERRNO ==
234 Test_cases[ind].exp_errno)
235 tst_resm(TPASS,
236 "stat(<%s>, &stbuf) Failed, errno=%d",
237 desc, TEST_ERRNO);
238 else
239 tst_resm(TFAIL,
240 "stat(<%s>, &stbuf) Failed, errno=%d, expected errno:%d",
241 desc, TEST_ERRNO,
242 Test_cases
243 [ind].exp_errno);
244 } else {
245 tst_resm(TFAIL,
246 "stat(<%s>, &stbuf) returned %ld, expected -1, errno:%d",
247 desc, TEST_RETURN,
248 Test_cases[ind].exp_errno);
249 }
250 }
251
252 }
253
254 cleanup();
255 tst_exit();
256 }
257
258 /***************************************************************
259 * setup() - performs all ONE TIME setup for this test.
260 ***************************************************************/
setup(void)261 void setup(void)
262 {
263 int ind;
264
265 tst_sig(NOFORK, DEF_HANDLER, cleanup);
266
267 TEST_PAUSE;
268
269 tst_tmpdir();
270
271 #if !defined(UCLINUX)
272 bad_addr = mmap(0, 1, PROT_NONE,
273 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
274 if (bad_addr == MAP_FAILED) {
275 tst_brkm(TBROK, cleanup, "mmap failed");
276 }
277 Test_cases[6].pathname = bad_addr;
278 #endif
279
280 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
281 Test_cases[ind].setupfunc();
282 }
283
284 }
285
286 /***************************************************************
287 * cleanup() - performs all ONE TIME cleanup for this test at
288 * completion or premature exit.
289 ***************************************************************/
cleanup(void)290 void cleanup(void)
291 {
292
293 tst_rmdir();
294
295 }
296
297 /******************************************************************
298 * no_setup() - does nothing
299 ******************************************************************/
no_setup(void)300 int no_setup(void)
301 {
302 return 0;
303 }
304
305 #if !defined(UCLINUX)
306
307 /******************************************************************
308 * high_address_setup() - generates an address that should cause a segfault
309 ******************************************************************/
high_address_setup(void)310 int high_address_setup(void)
311 {
312 int ind;
313
314 for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
315 if (Test_cases[ind].pathname == High_address) {
316 /*if (strcmp(Test_cases[ind].pathname, HIGH_ADDRESS) == 0) { ** */
317 Test_cases[ind].pathname = (char *)(sbrk(0) + 5);
318 break;
319 }
320 }
321 return 0;
322
323 }
324 #endif
325
326 /******************************************************************
327 * longpath_setup() - creates a filename that is too long
328 ******************************************************************/
longpath_setup(void)329 int longpath_setup(void)
330 {
331 int ind;
332
333 for (ind = 0; ind <= PATH_MAX + 1; ind++) {
334 Longpathname[ind] = 'a';
335 }
336 return 0;
337
338 }
339
340 /******************************************************************
341 * filepath_setup() creates a file the exists that we will treat as a directory
342 ******************************************************************/
filepath_setup(void)343 int filepath_setup(void)
344 {
345 int fd;
346
347 if ((fd = creat("file", 0777)) == -1) {
348 tst_brkm(TBROK, cleanup, "creat(file) failed, errno:%d %s",
349 errno, strerror(errno));
350 }
351 close(fd);
352 return 0;
353 }
354
355 /******************************************************************
356 * sig11_handler() - our segfault recover hack
357 ******************************************************************/
sig11_handler(int sig)358 void sig11_handler(int sig)
359 {
360 longjmp(sig11_recover, 1);
361 }
362