Home | History | Annotate | Download | only in access
      1 /*
      2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
      3  *   AUTHOR		: William Roske
      4  *
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * Further, this software is distributed without any warranty that it is
     14  * free of the rightful claim of any third person regarding infringement
     15  * or the like.  Any license provided herein, whether implied or
     16  * otherwise, applies only to this software file.  Patent licenses, if
     17  * any, provided herein do not apply to combinations of this program with
     18  * other software, or any other product whatsoever.
     19  *
     20  * You should have received a copy of the GNU General Public License along
     21  * with this program; if not, write the Free Software Foundation, Inc.,
     22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     23  *
     24  */
     25 /*
     26  * Basic test for access(2) using F_OK, R_OK, W_OK and X_OK
     27  */
     28 #include <errno.h>
     29 #include <unistd.h>
     30 #include <sys/types.h>
     31 #include <pwd.h>
     32 #include "tst_test.h"
     33 
     34 #define FNAME_RWX "accessfile_rwx"
     35 #define FNAME_R   "accesfile_r"
     36 #define FNAME_W   "accesfile_w"
     37 #define FNAME_X   "accesfile_x"
     38 
     39 static uid_t uid;
     40 
     41 static struct tcase {
     42 	const char *fname;
     43 	int mode;
     44 	char *name;
     45 	int exp_errno;
     46 	/* 1: nobody expected  2: root expected 3: both */
     47 	int exp_user;
     48 } tcases[] = {
     49 	{FNAME_RWX, F_OK, "F_OK", 0, 3},
     50 	{FNAME_RWX, X_OK, "X_OK", 0, 3},
     51 	{FNAME_RWX, W_OK, "W_OK", 0, 3},
     52 	{FNAME_RWX, R_OK, "R_OK", 0, 3},
     53 
     54 	{FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3},
     55 	{FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3},
     56 	{FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3},
     57 	{FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3},
     58 
     59 	{FNAME_X, X_OK, "X_OK", 0, 3},
     60 	{FNAME_W, W_OK, "W_OK", 0, 3},
     61 	{FNAME_R, R_OK, "R_OK", 0, 3},
     62 
     63 	{FNAME_R, X_OK, "X_OK", EACCES, 3},
     64 	{FNAME_R, W_OK, "W_OK", EACCES, 1},
     65 	{FNAME_W, R_OK, "R_OK", EACCES, 1},
     66 	{FNAME_W, X_OK, "X_OK", EACCES, 3},
     67 	{FNAME_X, R_OK, "R_OK", EACCES, 1},
     68 	{FNAME_X, W_OK, "W_OK", EACCES, 1},
     69 
     70 	{FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
     71 	{FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
     72 	{FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
     73 	{FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
     74 
     75 	{FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
     76 	{FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
     77 	{FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
     78 	{FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
     79 
     80 	{FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1},
     81 	{FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1},
     82 	{FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
     83 	{FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1},
     84 
     85 	{FNAME_R, W_OK, "W_OK", 0, 2},
     86 	{FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2},
     87 
     88 	{FNAME_W, R_OK, "R_OK", 0, 2},
     89 	{FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2},
     90 
     91 	{FNAME_X, R_OK, "R_OK", 0, 2},
     92 	{FNAME_X, W_OK, "W_OK", 0, 2},
     93 	{FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2}
     94 };
     95 
     96 static void verify_success(struct tcase *tc, const char *user)
     97 {
     98 	if (TEST_RETURN == -1) {
     99 		tst_res(TFAIL | TTERRNO,
    100 		        "access(%s, %s) as %s failed unexpectedly",
    101 		        tc->fname, tc->name, user);
    102 		return;
    103 	}
    104 
    105 	tst_res(TPASS, "access(%s, %s) as %s", tc->fname, tc->name, user);
    106 }
    107 
    108 static void verify_failure(struct tcase *tc, const char *user)
    109 {
    110 	if (TEST_RETURN != -1) {
    111 		tst_res(TFAIL, "access(%s, %s) as %s succeded unexpectedly",
    112 		        tc->fname, tc->name, user);
    113 		return;
    114 	}
    115 
    116 	if (TEST_ERRNO != tc->exp_errno) {
    117 		tst_res(TFAIL | TTERRNO,
    118 		        "access(%s, %s) as %s should fail with %s",
    119 		        tc->fname, tc->name, user,
    120 		        tst_strerrno(tc->exp_errno));
    121 		return;
    122 	}
    123 
    124 	tst_res(TPASS | TTERRNO, "access(%s, %s) as %s",
    125 	        tc->fname, tc->name, user);
    126 }
    127 
    128 static void access_test(struct tcase *tc, const char *user)
    129 {
    130 	TEST(access(tc->fname, tc->mode));
    131 
    132 	if (tc->exp_errno)
    133 		verify_failure(tc, user);
    134 	else
    135 		verify_success(tc, user);
    136 }
    137 
    138 static void verify_access(unsigned int n)
    139 {
    140 	struct tcase *tc = tcases + n;
    141 	pid_t pid;
    142 
    143 	if (tc->exp_user & 0x02)
    144 		access_test(tc, "root");
    145 
    146 	if (tc->exp_user & 0x01) {
    147 		pid = SAFE_FORK();
    148 		if (pid) {
    149 			SAFE_WAITPID(pid, NULL, 0);
    150 		} else {
    151 			SAFE_SETUID(uid);
    152 			access_test(tc, "nobody");
    153 		}
    154 	}
    155 }
    156 
    157 static void setup(void)
    158 {
    159 	struct passwd *pw;
    160 
    161 	pw = SAFE_GETPWNAM("nobody");
    162 
    163 	uid = pw->pw_uid;
    164 
    165 	SAFE_TOUCH(FNAME_RWX, 0777, NULL);
    166 	SAFE_TOUCH(FNAME_R, 0444, NULL);
    167 	SAFE_TOUCH(FNAME_W, 0222, NULL);
    168 	SAFE_TOUCH(FNAME_X, 0111, NULL);
    169 }
    170 
    171 static struct tst_test test = {
    172 	.tid = "access01",
    173 	.needs_tmpdir = 1,
    174 	.needs_root = 1,
    175 	.forks_child = 1,
    176 	.setup = setup,
    177 	.test = verify_access,
    178 	.tcnt = ARRAY_SIZE(tcases),
    179 };
    180