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