access05.c revision bfc42dad4386b0088e4b5c3bc7fdfc1ad017ac7b
1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2001
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * Test Name: access05
22 *
23 * Test Description:
24 *  Verify that,
25 *   1. access() fails with -1 return value and sets errno to EACCES
26 *      if the permission bits of the file mode do not permit the
27 *	 requested (Read/Write/Execute) access.
28 *   2. access() fails with -1 return value and sets errno to EINVAL
29 *	if the specified access mode argument is invalid.
30 *   3. access() fails with -1 return value and sets errno to EFAULT
31 *	if the pathname points outside allocate address space for the
32 *	process.
33 *   4. access() fails with -1 return value and sets errno to ENOENT
34 *	if the specified file doesn't exist (or pathname is NULL).
35 *   5. access() fails with -1 return value and sets errno to ENAMETOOLONG
36 *      if the pathname size is > PATH_MAX characters.
37 *
38 * Expected Result:
39 *  access() should fail with return value -1 and set expected errno.
40 *
41 * Algorithm:
42 *  Setup:
43 *   Setup signal handling.
44 *   Create temporary directory.
45 *   Pause for SIGUSR1 if option specified.
46 *
47 *  Test:
48 *   Loop if the proper options are given.
49 *   Execute system call
50 *   Check return code, if system call failed (return=-1)
51 *   	if errno set == expected errno
52 *   		Issue sys call fails with expected return value and errno.
53 *   	Otherwise,
54 *		Issue sys call fails with unexpected errno.
55 *   Otherwise,
56 *	Issue sys call returns unexpected value.
57 *
58 *  Cleanup:
59 *   Print errno log and/or timing stats if options given
60 *   Delete the temporary directory(s)/file(s) created.
61 *
62 * Usage:  <for command-line>
63 *  access05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
64 *     where,  -c n : Run n copies concurrently.
65 *             -e   : Turn on errno logging.
66 *	       -i n : Execute test n times.
67 *	       -I x : Execute test for x seconds.
68 *	       -P x : Pause for x seconds between iterations.
69 *	       -t   : Turn on syscall timing.
70 *
71 * HISTORY
72 *	07/2001 Ported by Wayne Boyer
73 *
74 * RESTRICTIONS:
75 *  This test should be run by 'non-super-user' only.
76 *
77 */
78
79#include <stdio.h>
80#include <errno.h>
81#include <unistd.h>
82#include <fcntl.h>
83#include <string.h>
84#include <signal.h>
85#include <sys/types.h>
86#include <sys/stat.h>
87
88#include "test.h"
89#include "usctest.h"
90
91#define INV_OK		-1
92#define TEST_FILE1	"test_file1"
93#define TEST_FILE2	"test_file2"
94#define TEST_FILE3	"test_file3"
95#define TEST_FILE4	"test_file4"
96
97#define FILE_MODE	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
98
99int no_setup();
100int setup1();			/* setup() to test access() for EACCES */
101int setup2();			/* setup() to test access() for EACCES */
102int setup3();			/* setup() to test access() for EACCES */
103int setup4();			/* setup() to test access() for EINVAL */
104int longpath_setup();	/* setup function to test access() for ENAMETOOLONG */
105
106char Longpathname[PATH_MAX+2];
107char High_address_node[64];
108
109struct test_case_t {		/* test case structure */
110	char *pathname;
111	int a_mode;
112	char *desc;
113	int exp_errno;
114	int (*setupfunc)();
115} Test_cases[] = {
116	{ TEST_FILE1, R_OK, "Read Access denied on file", EACCES, setup1 },
117	{ TEST_FILE2, W_OK, "Write Access denied on file", EACCES, setup2 },
118	{ TEST_FILE3, X_OK, "Execute Access denied on file", EACCES, setup3 },
119	{ TEST_FILE4, INV_OK, "Access mode invalid", EINVAL, setup4 },
120	{ High_address_node, R_OK, "Address beyond address space", EFAULT, no_setup },
121	{ (char *)-1, R_OK, "Negative address", EFAULT, no_setup },
122	{ "", W_OK, "Pathname is empty", ENOENT, no_setup },
123	{ Longpathname, R_OK, "Pathname too long", ENAMETOOLONG, longpath_setup },
124	{ NULL, 0, NULL, 0, no_setup }
125};
126
127char *TCID="access05";		/* Test program identifier.    */
128int TST_TOTAL=8;		/* Total number of test cases. */
129extern int Tst_count;		/* Test Case counter for tst_* routines */
130int exp_enos[]={EACCES, EFAULT, EINVAL, ENOENT, ENAMETOOLONG, 0};
131
132void setup();			/* Main setup function of test */
133void cleanup();			/* cleanup function for the test */
134
135int
136main(int ac, char **av)
137{
138	int lc;			/* loop counter */
139	char *msg;		/* message returned from parse_opts */
140	char *file_name;	/* name of the testfile */
141	char *test_desc;	/* test specific message */
142	int access_mode;	/* specified access mode for testfile */
143	int ind;		/* counter for testcase looping */
144
145	/* Parse standard options given to run the test. */
146	msg = parse_opts(ac, av, (option_t *) NULL, NULL);
147	if (msg != (char *) NULL) {
148		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
149	}
150
151	/* Perform global setup for test */
152	setup();
153
154	/* set the expected errnos... */
155	TEST_EXP_ENOS(exp_enos);
156
157	/* Check looping state if -i option given */
158	for (lc = 0; TEST_LOOPING(lc); lc++) {
159		/* Reset Tst_count in case we are looping. */
160		Tst_count = 0;
161
162		for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
163			file_name = Test_cases[ind].pathname;
164			access_mode = Test_cases[ind].a_mode;
165			test_desc = Test_cases[ind].desc;
166
167			if (file_name == High_address_node) {
168				file_name = (char *)get_high_address();
169			}
170
171			/*
172			 * Call access(2) to test different test conditions.
173			 * verify that it fails with -1 return value and
174			 * sets appropriate errno.
175			 */
176			TEST(access(file_name, access_mode));
177
178			if (TEST_RETURN != -1) {
179				tst_resm(TFAIL, "access() returned %d, "
180					 "expected -1, errno:%d", TEST_RETURN,
181					 Test_cases[ind].exp_errno);
182				continue;
183			}
184
185			TEST_ERROR_LOG(TEST_ERRNO);
186
187			/*
188			 * Call a function to verify whether
189			 * the specified file has specified
190			 * access mode.
191			 */
192			if (TEST_ERRNO == Test_cases[ind].exp_errno) {
193				tst_resm(TPASS, "access() fails, %s, errno:%d",
194					 test_desc, TEST_ERRNO);
195			} else {
196				tst_resm(TFAIL, "access() fails, %s, errno:%d, "
197					 "expected errno:%d", test_desc,
198					 TEST_ERRNO, Test_cases[ind].exp_errno);
199			}
200		}	/* Test Case Looping */
201	}	/* End for TEST_LOOPING */
202
203	/* Call cleanup() to undo setup done for the test. */
204	cleanup();
205
206	/*NOTREACHED*/
207}
208
209/*
210 * setup() - performs all ONE TIME setup for this test.
211 *
212 *  Create a temporary directory and change directory to it.
213 *  Call individual test specific setup functions.
214 */
215void
216setup()
217{
218	int ind;			/* counter for testsetup functions */
219
220	/* capture signals */
221	tst_sig(NOFORK, DEF_HANDLER, cleanup);
222
223	/* Check that the test process id is not root/super-user */
224	if (geteuid() == 0) {
225		tst_brkm(TBROK, NULL, "Must be non-root/super for this test!");
226		tst_exit();
227	}
228
229	/* Pause if that option was specified */
230	TEST_PAUSE;
231
232	/* make a temp directory and cd to it */
233	tst_tmpdir();
234
235	/* call individual setup functions */
236	for (ind = 0; Test_cases[ind].desc != NULL; ind++) {
237		Test_cases[ind].setupfunc();
238	}
239}
240
241/*
242 * no_setup() - some test conditions do not need any setup.
243 *		Hence, this function simply returns 0.
244 */
245int
246no_setup()
247{
248	return 0;
249}
250
251/*
252 * setup1() - Setup function to test access() for return value -1
253 *	      and errno EACCES when read access denied for specified
254 *	      testfile.
255 *
256 *   Creat/open a testfile and close it.
257 *   Deny read access permissions on testfile.
258 *   This function returns 0.
259 */
260int
261setup1()
262{
263	int fd1;			/* file handle for testfile */
264
265	/* Creat a test file under above directory created */
266	if ((fd1 = open(TEST_FILE1, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
267		tst_brkm(TBROK, cleanup,
268			 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s",
269			 TEST_FILE1, FILE_MODE, errno, strerror(errno));
270	}
271
272	/* Close the testfile created above */
273	if (close(fd1) == -1) {
274		tst_brkm(TBROK, cleanup, "close(%s) Failed, errno=%d : %s",
275			 TEST_FILE1, errno, strerror(errno));
276	}
277
278	/* Change mode permissions on testfile */
279	if (chmod(TEST_FILE1, 0333) < 0) {
280		tst_brkm(TBROK, cleanup, "chmod() failed on %s, errno=%d",
281			 TEST_FILE1, errno);
282	}
283
284	return 0;
285}
286
287/*
288 * setup2() - Setup function to test access() for return value -1 and
289 *	      errno EACCES when write access denied on testfile.
290 *
291 *   Creat/open a testfile and close it.
292 *   Deny write access permissions on testfile.
293 *   This function returns 0.
294 */
295int
296setup2()
297{
298	int fd2;			/* file handle for testfile */
299
300	/* Creat a test file under above directory created */
301	if ((fd2 = open(TEST_FILE2, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
302		tst_brkm(TBROK, cleanup,
303			 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s",
304			 TEST_FILE2, FILE_MODE, errno, strerror(errno));
305	}
306
307	/* Close the testfile created above */
308	if (close(fd2) == -1) {
309		tst_brkm(TBROK, cleanup, "close(%s) Failed, errno=%d : %s",
310			 TEST_FILE2, errno, strerror(errno));
311	}
312
313	/* Change mode permissions on testfile */
314	if (chmod(TEST_FILE2, 0555) < 0) {
315		tst_brkm(TBROK, cleanup, "chmod() failed on %s, errno=%d",
316			 TEST_FILE2, errno);
317	}
318
319	return 0;
320}
321
322/*
323 * setup3() - Setup function to test access() for return value -1 and
324 *	      errno EACCES when execute access denied on testfile.
325 *
326 *   Creat/open a testfile and close it.
327 *   Deny search access permissions on testfile.
328 *   This function returns 0.
329 */
330int
331setup3()
332{
333	int fd3;			/* file handle for testfile */
334
335	/* Creat a test file under above directory created */
336	if ((fd3 = open(TEST_FILE3, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
337		tst_brkm(TBROK, cleanup,
338			 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s",
339			 TEST_FILE3, FILE_MODE, errno, strerror(errno));
340	}
341
342	/* Close the testfile created above */
343	if (close(fd3) == -1) {
344		tst_brkm(TBROK, cleanup, "close(%s) Failed, errno=%d : %s",
345			 TEST_FILE3, errno, strerror(errno));
346	}
347
348	/* Change mode permissions on testfile */
349	if (chmod(TEST_FILE3, 0666) < 0) {
350		tst_brkm(TBROK, cleanup, "chmod() failed on %s, errno=%d",
351			 TEST_FILE3, errno);
352	}
353
354	return 0;
355}
356
357/*
358 * setup4() - Setup function to test access() for return value -1
359 *	      and errno EINVAL when specified access mode argument is
360 *	      invalid.
361 *
362 *   Creat/open a testfile and close it.
363 *   This function returns 0.
364 */
365int
366setup4()
367{
368	int fd4;			/* file handle for testfile */
369
370	/* Creat a test file under above directory created */
371	if ((fd4 = open(TEST_FILE4, O_RDWR|O_CREAT, FILE_MODE)) == -1) {
372		tst_brkm(TBROK, cleanup,
373			 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s",
374			 TEST_FILE4, FILE_MODE, errno, strerror(errno));
375	}
376
377	/* Close the testfile created above */
378	if (close(fd4) == -1) {
379		tst_brkm(TBROK, cleanup, "close(%s) Failed, errno=%d : %s",
380			 TEST_FILE4, errno, strerror(errno));
381	}
382
383	return 0;
384}
385
386/*
387 * longpath_setup() - setup to create a node with a name length exceeding
388 * 		      the MAX. length of PATH_MAX.
389 */
390int
391longpath_setup()
392{
393	int ind;
394
395	for (ind = 0; ind <= (PATH_MAX + 1); ind++) {
396		Longpathname[ind] = 'a';
397	}
398
399	return 0;
400}
401
402/*
403 * cleanup() - performs all ONE TIME cleanup for this test at
404 *             completion or premature exit.
405 *
406 *  Remove the test directory and testfile created in the setup.
407 */
408void
409cleanup()
410{
411	/*
412	 * print timing stats if that option was specified.
413	 * print errno log if that option was specified.
414	 */
415	TEST_CLEANUP;
416
417	/*
418	 * Delete the test directory/file and temporary directory
419	 * created in the setup.
420	 */
421	tst_rmdir();
422
423	/* exit with return code appropriate for results */
424	tst_exit();
425}
426