[LTP] [PATCH] syscalls/access02: reconstruct and convert to new API

Guangwen Feng fenggw-fnst@cn.fujitsu.com
Fri Jun 24 10:08:03 CEST 2016


* take use of some SAFE Marcos
* add read/execute check for the file referred to by symbolic link
* add test as root and nobody respectively

Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
---
 testcases/kernel/syscalls/access/access02.c | 396 ++++++++++------------------
 1 file changed, 141 insertions(+), 255 deletions(-)

diff --git a/testcases/kernel/syscalls/access/access02.c b/testcases/kernel/syscalls/access/access02.c
index 56241d0..361b2e5 100644
--- a/testcases/kernel/syscalls/access/access02.c
+++ b/testcases/kernel/syscalls/access/access02.c
@@ -25,302 +25,188 @@
  *  Also verify that, access() succeeds to test the accessibility of the file
  *  referred to by symbolic link if the pathname points to a symbolic link.
  *
- *	07/2001 Ported by Wayne Boyer
+ *  As well as verify that, these test files can be read/written/executed
+ *  indeed as root and nobody respectively.
+ *
+ *	07/2001 Ported by Wayne Boyera
+ *	06/2016 modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
  */
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
 #include <pwd.h>
-
-#include "test.h"
-
-#define TEMP_FILE	"temp_file"
-#define SYM_FILE	"sym_file"
-#define TEST_FILE1	"test_file1"
-#define TEST_FILE2	"test_file2"
-#define TEST_FILE3	"test_file3"
-#define FILE_MODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
-#define EXE_MODE	0777
-
-char *TCID = "access02";
-int TST_TOTAL = 4;
-
-static int fd1, fd2, fd4;
-static const char nobody_uid[] = "nobody";
-static struct passwd *ltpuser;
-
-static int setup1(void);
-static int setup2(void);
-static int setup3(void);
-static int setup4(void);
-
-static struct test_case_t {
-	char *pathname;
-	mode_t a_mode;
-	int (*setupfunc) (void);
-} test_cases[] = {
-	{TEST_FILE1, R_OK, setup1},
-	{TEST_FILE2, W_OK, setup2},
-	{TEST_FILE3, X_OK, setup3},
-	{SYM_FILE, W_OK, setup4},
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst_test.h"
+
+#define FNAME_R	"accessfile_r"
+#define FNAME_W	"accessfile_w"
+#define FNAME_X	"accessfile_x"
+#define SYMLINK	"symlink"
+#define MODE_R	0444
+#define MODE_W	0222
+#define MODE_X	0555
+
+static uid_t uid;
+static int fds[3];
+
+static struct tcase {
+	const char *pathname;
+	int mode;
+	char *name;
+	int is_symlink;
+	const char *targetname;
+} tcases[] = {
+	{FNAME_R, R_OK, "R_OK", 0, ""},
+	{FNAME_W, W_OK, "W_OK", 0, ""},
+	{FNAME_X, X_OK, "X_OK", 0, ""},
+	{SYMLINK, R_OK, "R_OK", 1, FNAME_R},
+	{SYMLINK, W_OK, "W_OK", 1, FNAME_W},
+	{SYMLINK, X_OK, "X_OK", 1, FNAME_X}
 };
 
-static void setup(void);
-static void cleanup(void);
-static int access_verify(int);
-
-int main(int ac, char **av)
+static void access_test(struct tcase *tc, const char *user)
 {
-	int lc;
-	int i;
-	mode_t access_mode;
-	char *file_name;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (i = 0; i < TST_TOTAL; i++) {
-			file_name = test_cases[i].pathname;
-			access_mode = test_cases[i].a_mode;
-
-			/*
-			 * Call access(2) to check the test file
-			 * for specified access mode permissions.
-			 */
-			TEST(access(file_name, access_mode));
+	char c, command[64];
+	const char *filename;
+
+	if (tc->is_symlink == 1) {
+		SAFE_SYMLINK(tc->targetname, tc->pathname);
+		filename = tc->targetname;
+	} else {
+		filename = tc->pathname;
+	}
 
-			if (TEST_RETURN == -1) {
-				tst_resm(TFAIL | TTERRNO,
-					 "access(%s, %#o) failed",
-					 file_name, access_mode);
-				continue;
-			}
+	TEST(access(tc->pathname, tc->mode));
 
-			access_verify(i);
-		}
+	if (TEST_RETURN == -1) {
+		tst_res(TFAIL | TTERRNO, "access(%s, %s) as %s failed",
+			tc->pathname, tc->name, user);
+		return;
 	}
 
-	cleanup();
-	tst_exit();
-}
+	switch (tc->mode) {
+	case R_OK:
+		/*
+		 * The specified file(or pointed to by symbolic link)
+		 * has read access, attempt to read data from the file,
+		 * if successful, access() behaviour is correct.
+		 */
+		TEST(read(fds[0], &c, 1));
 
-static void setup(void)
-{
-	int i;
+		if (TEST_RETURN == -1) {
+			tst_res(TFAIL | TTERRNO, "read %s as %s failed",
+				filename, user);
+			return;
+		}
 
-	tst_require_root();
-	tst_sig(FORK, DEF_HANDLER, cleanup);
+		break;
+	case W_OK:
+		/*
+		 * The specified file(or pointed to by symbolic link)
+		 * has write access, attempt to write data to the file,
+		 * if successful, access() behaviour is correct.
+		 */
+		TEST(write(fds[1], "A", 1));
 
-	ltpuser = getpwnam(nobody_uid);
-	if (ltpuser == NULL)
-		tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed");
-	if (setuid(ltpuser->pw_uid) == -1)
-		tst_brkm(TINFO | TERRNO, NULL, "setuid failed");
+		if (TEST_RETURN == -1) {
+			tst_res(TFAIL | TTERRNO, "write %s as %s failed",
+				filename, user);
+			return;
+		}
 
-	TEST_PAUSE;
-	tst_tmpdir();
+		break;
+	case X_OK:
+		/*
+		 * The specified file(or pointed to by symbolic link)
+		 * has execute access, attempt to execute the executable
+		 * file, if successful, access() behaviour is correct.
+		 */
+		sprintf(command, "./%s", filename);
 
-	for (i = 0; i < TST_TOTAL; i++)
-		test_cases[i].setupfunc();
-}
+		TEST(system(command));
 
-/*
- * setup1() - Setup function to test the functionality of access() for
- *	      the access mode argument R_OK.
- *
- *   Creat/open a testfile and write some data into it.
- *   This function returns 0.
- */
-static int setup1(void)
-{
-	char write_buf[] = "abc";
+		if (TEST_RETURN != 0) {
+			tst_res(TFAIL | TTERRNO, "execute %s as %s failed",
+				filename, user);
+			return;
+		}
 
-	fd1 = open(TEST_FILE1, O_RDWR | O_CREAT, FILE_MODE);
-	if (fd1 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "open(%s, O_RDWR|O_CREAT, %#o) failed",
-			 TEST_FILE1, FILE_MODE);
+		break;
+	default:
+		break;
 	}
 
-	/* write some data into testfile */
-	if (write(fd1, write_buf, strlen(write_buf)) != strlen(write_buf)) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "write(%s) failed in setup1", TEST_FILE1);
-	}
+	tst_res(TPASS, "access(%s, %s) as %s behaviour is correct.",
+		tc->pathname, tc->name, user);
 
-	return 0;
+	if (tc->is_symlink == 1)
+		SAFE_UNLINK(tc->pathname);
 }
 
-/*
- * setup2() - Setup function to test the functionality of access() for
- *	      the access mode argument W_OK.
- *
- *   Creat/open a testfile for writing under temporary directory.
- *   This function returns 0.
- */
-static int setup2(void)
+static void verify_access(unsigned int n)
 {
-	fd2 = open(TEST_FILE2, O_RDWR | O_CREAT, FILE_MODE);
-	if (fd1 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "open(%s, O_RDWR|O_CREAT, %#o) failed",
-			 TEST_FILE2, FILE_MODE);
+	struct tcase *tc = &tcases[n];
+	pid_t pid;
+
+	/* test as root */
+	access_test(tc, "root");
+
+	/* test as nobody */
+	pid = SAFE_FORK();
+	if (pid) {
+		SAFE_WAITPID(pid, NULL, 0);
+	} else {
+		SAFE_SETUID(uid);
+		access_test(tc, "nobody");
 	}
-
-	return 0;
 }
 
-/*
- * setup3() - Setup function to test the functionality of access() for
- *	      the access mode argument X_OK.
- *
- *   Creat/open a testfile and provide execute permissions to it.
- *   This function returns 0.
- */
-static int setup3(void)
+static void setup(void)
 {
-	int fd3;
+	struct passwd *pw;
 #ifdef UCLINUX
 	char exechead[] = "#!/bin/sh\n";
 #endif
 
-	fd3 = open(TEST_FILE3, O_RDWR | O_CREAT, FILE_MODE);
-	if (fd3 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "open(%s, O_RDWR|O_CREAT, %#o) failed",
-			 TEST_FILE3, FILE_MODE);
-	}
-#ifdef UCLINUX
-	if (write(fd3, exechead, sizeof(exechead)) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "write(%s) failed",
-			 TEST_FILE3);
-	}
-#endif
-
-	/* Close the test file created above */
-	if (close(fd3) == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup, "close(%s) failed",
-			 TEST_FILE3);
-	}
-
-	/* Set execute permission bits on the test file. */
-	if (chmod(TEST_FILE3, EXE_MODE) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "chmod(%s, %#o) failed",
-			 TEST_FILE3, EXE_MODE);
-	}
+	pw = SAFE_GETPWNAM("nobody");
 
-	return 0;
-}
+	uid = pw->pw_uid;
 
-/*
- * setup4() - Setup function to test the functionality of access() for
- *	      symbolic link file.
- *
- *   Creat/open a temporary file and close it.
- *   Creat a symbolic link of temporary file.
- *   This function returns 0.
- */
-static int setup4(void)
-{
-	fd4 = open(TEMP_FILE, O_RDWR | O_CREAT, FILE_MODE);
-	if (fd4 == -1) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "open(%s, O_RDWR|O_CREAT, %#o) failed",
-			 TEMP_FILE, FILE_MODE);
-	}
-
-	/* Creat a symbolic link for temporary file */
-	if (symlink(TEMP_FILE, SYM_FILE) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup,
-			 "symlink(%s, %s) failed", TEMP_FILE, SYM_FILE);
-	}
-
-	return 0;
-}
-
-/*
- * access_verify(i) -
- *
- *	This function verify the accessibility of the
- *	the testfile with the one verified by access().
- */
-static int access_verify(int i)
-{
-	char write_buf[] = "abc";
-	char read_buf[BUFSIZ];
-	int rval;
+	fds[0] = SAFE_OPEN(FNAME_R, O_RDWR | O_CREAT, 0777);
+	fds[1] = SAFE_OPEN(FNAME_W, O_RDWR | O_CREAT, MODE_W);
+	fds[2] = SAFE_OPEN(FNAME_X, O_RDWR | O_CREAT, 0777);
 
-	rval = 0;
+	SAFE_WRITE(1, fds[0], "A", 1);
+#ifdef UCLINUX
+	SAFE_WRITE(1, fds[2], exechead, sizeof(exechead));
+#endif
 
-	switch (i) {
-	case 0:
-		/*
-		 * The specified file has read access.
-		 * Attempt to read some data from the testfile
-		 * and if successful, access() behaviour is
-		 * correct.
-		 */
-		rval = read(fd1, &read_buf, sizeof(read_buf));
-		if (rval == -1)
-			tst_resm(TFAIL | TERRNO, "read(%s) failed", TEST_FILE1);
-		break;
-	case 1:
-		/*
-		 * The specified file has write access.
-		 * Attempt to write some data to the testfile
-		 * and if successful, access() behaviour is correct.
-		 */
-		rval = write(fd2, write_buf, strlen(write_buf));
-		if (rval == -1)
-			tst_resm(TFAIL | TERRNO, "write(%s) failed",
-				 TEST_FILE2);
-		break;
-	case 2:
-		/*
-		 * The specified file has execute access.
-		 * Attempt to execute the specified executable
-		 * file, if successful, access() behaviour is correct.
-		 */
-		rval = system("./" TEST_FILE3);
-		if (rval != 0)
-			tst_resm(TFAIL, "Fail to execute the %s", TEST_FILE3);
-		break;
-	case 3:
-		/*
-		 * The file pointed to by symbolic link has
-		 * write access.
-		 * Attempt to write some data to this temporary file
-		 * pointed to by symlink. if successful, access() bahaviour
-		 * is correct.
-		 */
-		rval = write(fd4, write_buf, strlen(write_buf));
-		if (rval == -1)
-			tst_resm(TFAIL | TERRNO, "write(%s) failed", TEMP_FILE);
-		break;
-	default:
-		break;
-	}
+	SAFE_CLOSE(fds[2]);
+	fds[2] = 0;
 
-	return rval;
+	SAFE_CHMOD(FNAME_R, MODE_R);
+	SAFE_CHMOD(FNAME_X, MODE_X);
 }
 
 static void cleanup(void)
 {
-	if (close(fd1) == -1)
-		tst_brkm(TFAIL | TERRNO, NULL, "close(%s) failed", TEST_FILE1);
-	if (close(fd2) == -1)
-		tst_brkm(TFAIL | TERRNO, NULL, "close(%s) failed", TEST_FILE2);
-	if (close(fd4) == -1)
-		tst_brkm(TFAIL | TERRNO, NULL, "close(%s) failed", TEMP_FILE);
-
-	tst_rmdir();
+	if (fds[0] > 0 && close(fds[0]))
+		tst_res(TWARN | TERRNO, "failed to close file");
+	if (fds[1] > 0 && close(fds[1]))
+		tst_res(TWARN | TERRNO, "failed to close file");
+	if (fds[2] > 0 && close(fds[2]))
+		tst_res(TWARN | TERRNO, "failed to close file");
 }
+
+static struct tst_test test = {
+	.tid = "access02",
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+	.needs_root = 1,
+	.forks_child = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = verify_access,
+};
-- 
1.8.4.2





More information about the ltp mailing list