mkdir04.c revision 4548c6cf9bcdd96d8303caa4130ab638b61f8a30
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. */
93int fail;
94
95char tstdir1[100];
96char tstdir2[100];
97
98int exp_enos[] = { EACCES, 0 };	/* List must end with 0 */
99
100int main(int ac, char **av)
101{
102	int lc;			/* loop counter */
103	char *msg;		/* message returned from parse_opts */
104	int rval;
105	pid_t pid, pid1;
106	int status;
107	struct passwd *ltpuser1, *ltpuser2;
108
109	/*
110	 * parse standard options
111	 */
112	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
113		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
114	}
115
116	/*
117	 * perform global setup for test
118	 */
119	setup();
120
121	/* set the expected errnos... */
122	TEST_EXP_ENOS(exp_enos);
123
124	/*
125	 * check looping state if -i option given
126	 */
127	for (lc = 0; TEST_LOOPING(lc); lc++) {
128
129		Tst_count = 0;
130
131		/* Initialize the test directories name */
132		sprintf(tstdir1, "tstdir1.%d", getpid());
133		ltpuser1 = my_getpwnam(user1name);
134
135		if ((pid = FORK_OR_VFORK()) < 0) {
136			tst_brkm(TBROK, cleanup, "fork #1 failed");
137		 }
138
139		if (pid == 0) {	/* first child */
140			/* set to ltpuser1 */
141			rval = setreuid(ltpuser1->pw_uid, ltpuser1->pw_uid);
142			if (rval < 0) {
143				tst_resm(TFAIL, "setreuid failed to "
144					 "to set the real uid to %d and "
145					 "effective uid to %d",
146					 ltpuser1->pw_uid, ltpuser1->pw_uid);
147				perror("setreuid");
148				exit(1);
149			 }
150			/* create the parent directory with 0700 permits */
151			if (mkdir(tstdir1, PERMS) == -1) {
152				tst_resm(TFAIL, "mkdir(%s, %#o) Failed",
153					 tstdir1, PERMS);
154				exit(1);
155			 }
156			/* create tstdir1 succeeded */
157			exit(0);
158		}
159		wait(&status);
160		if (WEXITSTATUS(status) != 0) {
161			tst_brkm(TFAIL, cleanup,
162				 "Test to check mkdir EACCES failed"
163				 "in create parent directory");
164		}
165
166		sprintf(tstdir2, "%s/tst", tstdir1);
167		ltpuser2 = my_getpwnam(user2name);
168
169		if ((pid1 = FORK_OR_VFORK()) < 0) {
170			tst_brkm(TBROK, cleanup, "fork #2 failed");
171		 }
172
173		if (pid1 == 0) {	/* second child */
174			/* set to ltpuser2 */
175			rval = setreuid(ltpuser2->pw_uid, ltpuser2->pw_uid);
176			if (rval < 0) {
177				tst_resm(TFAIL, "setreuid failed to "
178					 "to set the real uid to %d and "
179					 "effective uid to %d",
180					 ltpuser2->pw_uid, ltpuser2->pw_uid);
181				perror("setreuid");
182				exit(1);
183			 }
184			if (mkdir(tstdir2, PERMS) != -1) {
185				tst_resm(TFAIL, "mkdir(%s, %#o) unexpected "
186					 "succeeded", tstdir2, PERMS);
187				exit(1);
188			 }
189			if (errno != EACCES) {
190				tst_resm(TFAIL, "Expected EACCES got %d",
191					 errno);
192				exit(1);
193			 }
194			/* PASS */
195			exit(0);
196		}
197		waitpid(pid1, &status, 0);
198		if (WEXITSTATUS(status) == 0) {
199			tst_resm(TPASS, "Test to attempt to creat a directory "
200				 "in a directory having no permissions "
201				 "SUCCEEDED in setting errno to EACCES");
202		} else {
203			tst_resm(TFAIL, "Test to attempt to creat a directory "
204				 "in a directory having no permissions FAILED");
205			cleanup();
206		}
207	}
208
209	/*
210	 * cleanup and exit
211	 */
212	cleanup();
213	tst_exit();
214
215}
216
217/*
218 * setup() - performs all ONE TIME setup for this test.
219 */
220void setup()
221{
222	/* must run as root */
223	if (geteuid() != 0) {
224		tst_brkm(TBROK, NULL, "Must run this as root");
225	 }
226
227	tst_sig(FORK, DEF_HANDLER, cleanup);
228
229	TEST_PAUSE;
230
231	/* Create a temporary directory and make it current. */
232	tst_tmpdir();
233
234	umask(0);
235}
236
237/*
238 * cleanup() - performs all ONE TIME cleanup for this test at
239 *             completion or premature exit.
240 */
241void cleanup()
242{
243	/*
244	 * print timing stats if that option was specified.
245	 * print errno log if that option was specified.
246	 */
247	TEST_CLEANUP;
248
249	/*
250	 * Remove the temporary directory.
251	 */
252	tst_rmdir();
253
254	/*
255	 * Exit with return code appropriate for results.
256	 */
257
258}
259