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