mkdir04.c revision bdbaec51a423e715c2b03ed9e497e9a1fba6103e
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 * NAME
22 *	mkdir04
23 *
24 * DESCRIPTION
25 *
26 * ALGORITHM
27 *	Setup:
28 *		Setup signal handling.
29 *		Pause for SIGUSR1 if option specified.
30 *		Create temporary directory.
31 *
32 *	Test:
33 *		Loop if the proper options are given.
34 *              fork the first child
35 *                      set to be ltpuser1
36 *                      create a dirctory tstdir1 with 0700 permission
37 *              fork the second child
38 *                      set to ltpuser2
39 *                      try to create a subdirectory tstdir2 under tstdir1
40 *                      check the returnvalue, if succeeded (return=0)
41 *			       Log the errno and Issue a FAIL message.
42 *		        Otherwise,
43 *			       Verify the errno
44 *			       if equals to EACCES,
45 *				       Issue Pass message.
46 *			       Otherwise,
47 *				       Issue Fail message.
48 *	Cleanup:
49 *		Print errno log and/or timing stats if options given
50 *		Delete the temporary directory created.
51 * USAGE
52 *	mkdir04 [-c n] [-e] [-f] [-i n] [-I x] [-P x] [-t]
53 *	where,  -c n : Run n copies concurrently.
54 *		-e   : Turn on errno logging.
55 *		-f   : Turn off functionality Testing.
56 *		-i n : Execute test n times.
57 *		-I x : Execute test for x seconds.
58 *		-P x : Pause for x seconds between iterations.
59 *		-t   : Turn on syscall timing.
60 *
61 * HISTORY
62 *	07/2001 Ported by Wayne Boyer
63 *
64 * RESTRICTIONS
65 *	None.
66 *
67 */
68
69#include <errno.h>
70#include <string.h>
71#include <signal.h>
72#include <sys/stat.h>
73#include <sys/types.h>
74#include <fcntl.h>
75#include <pwd.h>
76#include <sys/wait.h>
77#include <unistd.h>
78#include "test.h"
79#include "usctest.h"
80
81void setup();
82void cleanup();
83extern struct passwd * my_getpwnam(char *);
84int fail;
85
86#define PERMS		0700
87
88char user1name[] = "nobody";
89char user2name[] = "bin";
90
91char *TCID="mkdir04";           /* Test program identifier.    */
92int TST_TOTAL=1;                /* Total number of test cases. */
93extern int Tst_count;           /* Test Case counter for tst_* routines */
94int fail;
95
96char tstdir1 [100];
97char tstdir2 [100];
98
99int exp_enos[]={EACCES, 0};     /* List must end with 0 */
100
101int
102main(int ac, char **av)
103{
104	int lc;             /* loop counter */
105	char *msg;          /* message returned from parse_opts */
106	int rval;
107	pid_t pid, pid1;
108	int status;
109	struct passwd *ltpuser1, *ltpuser2;
110
111	/*
112	 * parse standard options
113	 */
114	if ((msg=parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL) {
115		tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
116	}
117
118	/*
119	 * perform global setup for test
120	 */
121	setup();
122
123	/* set the expected errnos... */
124	TEST_EXP_ENOS(exp_enos);
125
126	/*
127	 * check looping state if -i option given
128	 */
129	for (lc=0; TEST_LOOPING(lc); lc++) {
130
131		/* reset Tst_count in case we are looping. */
132		Tst_count=0;
133
134		/* Initialize the test directories name */
135		sprintf(tstdir1, "tstdir1.%d", getpid());
136		ltpuser1 = my_getpwnam(user1name);
137
138		if ((pid = FORK_OR_VFORK()) < 0) {
139			tst_brkm(TBROK, cleanup, "fork #1 failed");
140			/*NOTREACHED*/
141		}
142
143		if (pid == 0) {		/* first child */
144			/* set to ltpuser1 */
145			rval = setreuid(ltpuser1->pw_uid, ltpuser1->pw_uid);
146			if (rval < 0) {
147				tst_resm(TFAIL, "setreuid failed to "
148					 "to set the real uid to %d and "
149					 "effective uid to %d",
150					 ltpuser1->pw_uid, ltpuser1->pw_uid);
151				perror("setreuid");
152				exit(1);
153				/*NOTREACHED*/
154			}
155			/* create the parent directory with 0700 permits */
156			if ( mkdir(tstdir1, PERMS) == -1 ) {
157				 tst_resm(TFAIL, "mkdir(%s, %#o) Failed",
158					  tstdir1, PERMS);
159				 exit(1);
160				 /*NOTREACHED*/
161			}
162			/* create tstdir1 succeeded */
163			exit(0);
164		}
165		wait(&status);
166		if (WEXITSTATUS(status) != 0) {
167			tst_brkm(TFAIL, cleanup,
168				 "Test to check mkdir EACCES failed"
169				 "in create parent directory");
170		}
171
172		sprintf(tstdir2, "%s/tst",tstdir1);
173		ltpuser2 = my_getpwnam(user2name);
174
175		if ((pid1 = FORK_OR_VFORK()) < 0) {
176			tst_brkm(TBROK, cleanup, "fork #2 failed");
177			/*NOTREACHED*/
178		}
179
180		if (pid1 == 0) {		/* second child */
181		  	/* set to ltpuser2 */
182			rval = setreuid(ltpuser2->pw_uid, ltpuser2->pw_uid);
183			if (rval < 0) {
184				tst_resm(TFAIL, "setreuid failed to "
185					 "to set the real uid to %d and "
186					 "effective uid to %d",
187					 ltpuser2->pw_uid, ltpuser2->pw_uid);
188				perror("setreuid");
189				exit(1);
190				/*NOTREACHED*/
191			}
192			if ( mkdir(tstdir2, PERMS) != -1 ) {
193				 tst_resm(TFAIL, "mkdir(%s, %#o) unexpected "
194					  "succeeded",tstdir2, PERMS);
195				 exit(1);
196				 /*NOTREACHED*/
197			}
198			if (errno != EACCES) {
199				tst_resm(TFAIL, "Expected EACCES got %d",
200					 errno);
201				exit(1);
202				/*NOTREACHED*/
203			}
204			/* PASS */
205			exit(0);
206		}
207		waitpid(pid1, &status, 0);
208		if (WEXITSTATUS(status) == 0) {
209			tst_resm(TPASS, "Test to attempt to creat a directory "
210				 "in a directory having no permissions "
211				 "SUCCEEDED in setting errno to EACCES");
212		} else {
213			tst_resm(TFAIL, "Test to attempt to creat a directory "
214				 "in a directory having no permissions FAILED");
215			cleanup();
216		}
217	}   /* End for TEST_LOOPING */
218
219	/*
220	 * cleanup and exit
221	 */
222	cleanup();
223
224	/*NOTREACHED*/
225	return 0;
226}       /* End main */
227
228/*
229 * setup() - performs all ONE TIME setup for this test.
230 */
231void
232setup()
233{
234	/* must run as root */
235	if (geteuid() != 0) {
236		tst_brkm(TBROK, tst_exit, "Must run this as root");
237		/*NOTREACHED*/
238	}
239
240	/* capture signals */
241	tst_sig(FORK, DEF_HANDLER, cleanup);
242
243	/* Pause if that option was specified */
244	TEST_PAUSE;
245
246	/* Create a temporary directory and make it current. */
247	tst_tmpdir();
248
249	/* give the write rights to all user */
250	chmod(".",0777);
251
252	umask(0);
253}
254
255
256/*
257 * cleanup() - performs all ONE TIME cleanup for this test at
258 *             completion or premature exit.
259 */
260void
261cleanup()
262{
263	/*
264	 * print timing stats if that option was specified.
265	 * print errno log if that option was specified.
266	 */
267	TEST_CLEANUP;
268
269	/*
270	 * Remove the temporary directory.
271	 */
272	tst_rmdir();
273
274	/*
275	 * Exit with return code appropriate for results.
276	 */
277	tst_exit();
278}
279