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
125void setup();
126void cleanup();
127
128char *TCID = "stat06";
129
130char *bad_addr = 0;
131
132#if !defined(UCLINUX)
133int high_address_setup();
134char High_address[64];
135#endif
136int longpath_setup();
137int no_setup();
138int filepath_setup();
139char Longpathname[PATH_MAX + 2];
140struct stat statbuf;
141jmp_buf sig11_recover;
142void sig11_handler(int sig);
143
144struct 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
170int TST_TOTAL = ARRAY_SIZE(Test_cases);
171
172/***********************************************************************
173 * Main
174 ***********************************************************************/
175int 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 ***************************************************************/
261void 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 ***************************************************************/
290void cleanup(void)
291{
292
293	tst_rmdir();
294
295}
296
297/******************************************************************
298 * no_setup() - does nothing
299 ******************************************************************/
300int 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 ******************************************************************/
310int 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 ******************************************************************/
329int 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 ******************************************************************/
343int 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 ******************************************************************/
358void sig11_handler(int sig)
359{
360	longjmp(sig11_recover, 1);
361}
362