access05.c revision 43088e16aa60d69e3ec5a69cdd8bdd45b8891127
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#include <sys/mman.h> 88#include <pwd.h> 89 90#include "test.h" 91#include "usctest.h" 92 93#define INV_OK -1 94#define TEST_FILE1 "test_file1" 95#define TEST_FILE2 "test_file2" 96#define TEST_FILE3 "test_file3" 97#define TEST_FILE4 "test_file4" 98 99#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 100 101int no_setup(); 102int setup1(); /* setup() to test access() for EACCES */ 103int setup2(); /* setup() to test access() for EACCES */ 104int setup3(); /* setup() to test access() for EACCES */ 105int setup4(); /* setup() to test access() for EINVAL */ 106int longpath_setup(); /* setup function to test access() for ENAMETOOLONG */ 107 108#if !defined(UCLINUX) 109char *get_high_address(); /* function from ltp-lib */ 110char High_address_node[64]; 111#endif 112 113char Longpathname[PATH_MAX + 2]; 114 115struct test_case_t { /* test case structure */ 116 char *pathname; 117 int a_mode; 118 char *desc; 119 int exp_errno; 120 int (*setupfunc) (); 121} Test_cases[] = { 122 { 123 TEST_FILE1, R_OK, "Read Access denied on file", EACCES, setup1}, { 124 TEST_FILE2, W_OK, "Write Access denied on file", EACCES, setup2}, { 125 TEST_FILE3, X_OK, "Execute Access denied on file", EACCES, setup3}, 126 { 127 TEST_FILE4, INV_OK, "Access mode invalid", EINVAL, setup4}, 128#if !defined(UCLINUX) 129 { 130 (char *)-1, R_OK, "Negative address", EFAULT, no_setup}, { 131 High_address_node, R_OK, "Address beyond address space", EFAULT, 132 no_setup}, 133#endif 134 { 135 "", W_OK, "Pathname is empty", ENOENT, no_setup}, { 136 Longpathname, R_OK, "Pathname too long", ENAMETOOLONG, longpath_setup}, 137 { 138 NULL, 0, NULL, 0, no_setup} 139}; 140 141char *TCID = "access05"; /* Test program identifier. */ 142int TST_TOTAL = 8; /* Total number of test cases. */ 143extern int Tst_count; /* Test Case counter for tst_* routines */ 144int exp_enos[] = { EACCES, EFAULT, EINVAL, ENOENT, ENAMETOOLONG, 0 }; 145 146char nobody_uid[] = "nobody"; 147struct passwd *ltpuser; 148 149void setup(); /* Main setup function of test */ 150void cleanup(); /* cleanup function for the test */ 151 152char *bad_addr = 0; 153 154int main(int ac, char **av) 155{ 156 int lc; /* loop counter */ 157 char *msg; /* message returned from parse_opts */ 158 char *file_name; /* name of the testfile */ 159 char *test_desc; /* test specific message */ 160 int access_mode; /* specified access mode for testfile */ 161 int ind; /* counter for testcase looping */ 162 163 /* Parse standard options given to run the test. */ 164 msg = parse_opts(ac, av, (option_t *) NULL, NULL); 165 if (msg != NULL) { 166 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); 167 } 168 169 /* Perform global setup for test */ 170 setup(); 171 172 /* set the expected errnos... */ 173 TEST_EXP_ENOS(exp_enos); 174 175 /* Check looping state if -i option given */ 176 for (lc = 0; TEST_LOOPING(lc); lc++) { 177 /* Reset Tst_count in case we are looping. */ 178 Tst_count = 0; 179 180 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 181 file_name = Test_cases[ind].pathname; 182 access_mode = Test_cases[ind].a_mode; 183 test_desc = Test_cases[ind].desc; 184 185#if !defined(UCLINUX) 186 if (file_name == High_address_node) { 187 file_name = get_high_address(); 188 } 189#endif 190 191 /* 192 * Call access(2) to test different test conditions. 193 * verify that it fails with -1 return value and 194 * sets appropriate errno. 195 */ 196 TEST(access(file_name, access_mode)); 197 198 if (TEST_RETURN != -1) { 199 tst_resm(TFAIL, "access() returned %ld, " 200 "expected -1, errno:%d", TEST_RETURN, 201 Test_cases[ind].exp_errno); 202 continue; 203 } 204 205 TEST_ERROR_LOG(TEST_ERRNO); 206 207 /* 208 * Call a function to verify whether 209 * the specified file has specified 210 * access mode. 211 */ 212 if (TEST_ERRNO == Test_cases[ind].exp_errno) { 213 tst_resm(TPASS|TTERRNO, "access() fails, %s", 214 test_desc); 215 } else { 216 tst_resm(TFAIL|TTERRNO, "access() fails %s (expected errno %d)", 217 test_desc, Test_cases[ind].exp_errno); 218 } 219 } /* Test Case Looping */ 220 } /* End for TEST_LOOPING */ 221 222 /* Call cleanup() to undo setup done for the test. */ 223 cleanup(); 224 225 return 0; 226 /*NOTREACHED*/} 227 228/* 229 * setup() - performs all ONE TIME setup for this test. 230 * 231 * Create a temporary directory and change directory to it. 232 * Call individual test specific setup functions. 233 */ 234void setup() 235{ 236 int ind; /* counter for testsetup functions */ 237 238 /* capture signals */ 239 tst_sig(NOFORK, DEF_HANDLER, cleanup); 240 241 /* Switch to nobody user for correct error code collection */ 242 if (geteuid() != 0) { 243 tst_brkm(TBROK, tst_exit, "Test must be run as root"); 244 } 245 ltpuser = getpwnam(nobody_uid); 246 if (setuid(ltpuser->pw_uid) == -1) 247 tst_resm(TINFO|TERRNO, "setuid(%d) failed", ltpuser->pw_uid); 248 249 /* Pause if that option was specified */ 250 TEST_PAUSE; 251 252 /* make a temp directory and cd to it */ 253 tst_tmpdir(); 254 255#if !defined(UCLINUX) 256 bad_addr = mmap(0, 1, PROT_NONE, 257 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0); 258 if (bad_addr == MAP_FAILED) { 259 tst_brkm(TBROK|TERRNO, cleanup, "mmap failed"); 260 } 261 Test_cases[5].pathname = bad_addr; 262#endif 263 264 /* call individual setup functions */ 265 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 266 Test_cases[ind].setupfunc(); 267 } 268} 269 270/* 271 * no_setup() - some test conditions do not need any setup. 272 * Hence, this function simply returns 0. 273 */ 274int no_setup() 275{ 276 return 0; 277} 278 279int setup_file(const char *file, mode_t perms) 280{ 281 int fd; /* file handle for testfile */ 282 283 /* Creat a test file under above directory created */ 284 fd = open(file, O_RDWR | O_CREAT, FILE_MODE); 285 if (fd == -1) 286 tst_brkm(TBROK|TERRNO, cleanup, 287 "open(%s, O_RDWR|O_CREAT, %#o) failed", 288 file, FILE_MODE); 289 290 /* Close the testfile created above */ 291 if (close(fd) == -1) 292 tst_brkm(TBROK|TERRNO, cleanup, "close(%s) failed", file); 293 294 /* Change mode permissions on testfile */ 295 if (chmod(file, perms) < 0) 296 tst_brkm(TBROK|TERRNO, cleanup, "chmod(%s, %#o) failed", 297 file, perms); 298 299 return 0; 300} 301 302/* 303 * setup1() - Setup function to test access() for return value -1 304 * and errno EACCES when read access denied for specified 305 * testfile. 306 * 307 * Creat/open a testfile and close it. 308 * Deny read access permissions on testfile. 309 * This function returns 0. 310 */ 311int setup1() 312{ 313 return setup_file(TEST_FILE1, 0333); 314} 315 316/* 317 * setup2() - Setup function to test access() for return value -1 and 318 * errno EACCES when write access denied on testfile. 319 * 320 * Creat/open a testfile and close it. 321 * Deny write access permissions on testfile. 322 * This function returns 0. 323 */ 324int setup2() 325{ 326 return setup_file(TEST_FILE2, 0555); 327} 328 329/* 330 * setup3() - Setup function to test access() for return value -1 and 331 * errno EACCES when execute access denied on testfile. 332 * 333 * Creat/open a testfile and close it. 334 * Deny search access permissions on testfile. 335 * This function returns 0. 336 */ 337int setup3() 338{ 339 return setup_file(TEST_FILE3, 0666); 340} 341 342/* 343 * setup4() - Setup function to test access() for return value -1 344 * and errno EINVAL when specified access mode argument is 345 * invalid. 346 * 347 * Creat/open a testfile and close it. 348 * This function returns 0. 349 */ 350int setup4() 351{ 352 return setup_file(TEST_FILE4, FILE_MODE); 353} 354 355/* 356 * longpath_setup() - setup to create a node with a name length exceeding 357 * the MAX. length of PATH_MAX. 358 */ 359int longpath_setup() 360{ 361 int ind; 362 363 for (ind = 0; ind <= (PATH_MAX + 1); ind++) { 364 Longpathname[ind] = 'a'; 365 } 366 367 return 0; 368} 369 370/* 371 * cleanup() - performs all ONE TIME cleanup for this test at 372 * completion or premature exit. 373 * 374 * Remove the test directory and testfile created in the setup. 375 */ 376void cleanup() 377{ 378 /* 379 * print timing stats if that option was specified. 380 * print errno log if that option was specified. 381 */ 382 TEST_CLEANUP; 383 384 /* 385 * Delete the test directory/file and temporary directory 386 * created in the setup. 387 */ 388 tst_rmdir(); 389 390 /* exit with return code appropriate for results */ 391 tst_exit(); 392} 393