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