All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH] syscalls/readv02: Convert to new API and merge readv03 into readv02.
@ 2021-07-30  5:48 Dai Shili
  2021-08-03 13:43 ` Cyril Hrubis
  0 siblings, 1 reply; 5+ messages in thread
From: Dai Shili @ 2021-07-30  5:48 UTC (permalink / raw)
  To: ltp

1) merge readv03 into readv02
2) use tst_get_bad_addr() API
3) use TST_EXP_FAIL2 macro

Signed-off-by: Dai Shili <daisl.fnst@fujitsu.com>
---
 runtest/syscalls                           |   1 -
 testcases/kernel/syscalls/readv/.gitignore |   1 -
 testcases/kernel/syscalls/readv/readv02.c  | 331 ++++++++++-------------------
 testcases/kernel/syscalls/readv/readv03.c  |  53 -----
 4 files changed, 108 insertions(+), 278 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/readv/readv03.c

diff --git a/runtest/syscalls b/runtest/syscalls
index b379b2d..9c3b510 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1085,7 +1085,6 @@ readlinkat02 readlinkat02
 
 readv01 readv01
 readv02 readv02
-readv03 readv03
 
 realpath01 realpath01
 
diff --git a/testcases/kernel/syscalls/readv/.gitignore b/testcases/kernel/syscalls/readv/.gitignore
index c4aa61e..a532741 100644
--- a/testcases/kernel/syscalls/readv/.gitignore
+++ b/testcases/kernel/syscalls/readv/.gitignore
@@ -1,3 +1,2 @@
 /readv01
 /readv02
-/readv03
diff --git a/testcases/kernel/syscalls/readv/readv02.c b/testcases/kernel/syscalls/readv/readv02.c
index aa40e2c..aaadae0 100644
--- a/testcases/kernel/syscalls/readv/readv02.c
+++ b/testcases/kernel/syscalls/readv/readv02.c
@@ -1,198 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) Bull S.A. 2001
+ * Copyright (c) International Business Machines  Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 05/2002 Ported by Jacky Malcles
  */
 
-/*
- * NAME
- * 	readv02.c
- *
+/*\
  * DESCRIPTION
- *	Testcase to check the error conditions of the readv(2) system call.
+ *  test 1:
+ *  The sum of the iov_len values overflows an ssize_t value, expect an EINVAL.
  *
- * CALLS
- * 	readv()
+ *  test 2:
+ *  Buf is outside the accessible address space, expect an EFAULT.
  *
- * ALGORITHM
- *	Create a IO vector, and attempt to readv() various components of it.
+ *  test 3:
+ *  The vector count iovcnt is less than zero, expect an EINVAL.
  *
- * USAGE
- *	readv02
+ *  test 4:
+ *  The parameter passed to read is a directory, check if the errno is
+ *  set to EISDIR.
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * 	None
+ *  test 5:
+ *  Read with an invalid file descriptor, and expect an EBADF.
  */
-#include <sys/types.h>
+
 #include <sys/uio.h>
 #include <fcntl.h>
-#include <sys/mman.h>
 #include <memory.h>
-#include <errno.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-#define	K_1	1024
-#define	M_1	K_1 * K_1
-#define	G_1	M_1 * K_1
-
-#define	NBUFS		4
-#define	CHUNK		64
-#define	MAX_IOVEC	16
-#define DATA_FILE	"readv_data_file"
-
-char buf1[K_1], buf2[K_1], buf3[K_1];
-
-struct iovec rd_iovec[MAX_IOVEC] = {
-	/* iov_base *//* iov_len */
+#include "tst_test.h"
+
+#define K_1     1024
+#define M_1     (K_1 * K_1)
+#define G_1     (M_1 * K_1)
+#define MODES   0700
+
+#define NBUFS           4
+#define CHUNK           64
+#define MAX_IOVEC       16
+
+static int badfd = -1;
+static int fd[4] = {-1, -1, -1, -1};
+static char buf1[K_1], buf2[K_1], buf3[K_1];
+const char *TEST_DIR = "test_dir";
+const char *TEST_FILE[3] = {"file1", "file2", "file3"};
+char *buf_list[NBUFS];
 
-	/* Test case #1 */
+static struct iovec rd_iovec[MAX_IOVEC] = {
 	{buf2, -1},
 	{(buf2 + CHUNK), CHUNK},
 	{(buf2 + CHUNK * 2), CHUNK},
-
-	/* Test case #2 */
 	{(buf2 + CHUNK * 3), G_1},
 	{(buf2 + CHUNK * 4), G_1},
 	{(buf2 + CHUNK * 5), G_1},
-
-	/* Test case #3 */
 	{(caddr_t) - 1, CHUNK},
 	{(buf2 + CHUNK * 6), CHUNK},
 	{(buf2 + CHUNK * 8), CHUNK},
-
-	/* Test case #4 */
-	{(buf2 + CHUNK * 9), CHUNK}
+	{(buf2 + CHUNK * 9), CHUNK},
+	{buf1, K_1}
 };
 
-char f_name[K_1];
-
-int fd[4];
-char *buf_list[NBUFS];
-
-char *TCID = "readv02";
-int TST_TOTAL = 1;
-
-char *bad_addr = 0;
+static struct tcase {
+	int *fd;
+	void *buf;
+	int count;
+	int exp_error;
+} tcases[] = {
+	{&fd[0], rd_iovec, 1, EINVAL},
+	{&fd[1], rd_iovec + 6, 3, EFAULT},
+	{&fd[2], rd_iovec + 10, -1, EINVAL},
+	{&fd[3], rd_iovec + 10, 1, EISDIR},
+	{&badfd, rd_iovec + 9, 3, EBADF},
+};
 
-int init_buffs(char **);
-int fill_mem(char *, int, int);
-long l_seek(int, long, int);
-char *getenv();
-void setup();
-void cleanup();
 
-int main(int ac, char **av)
+void fill_mem(char *c_ptr, int c1, int c2)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
+	int count;
 
-	/* The following loop checks looping state if -i option given */
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+	for (count = 1; count <= K_1 / CHUNK; count++) {
+		if (count & 0x01) /* if odd */
+			memset(c_ptr, c1, CHUNK);
+		else /* if even */
+			memset(c_ptr, c2, CHUNK);
+	}
+	return;
+}
 
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
+void init_buffs(char *pbufs[])
+{
+	int i;
 
-//test1:
-		if (readv(fd[0], rd_iovec, 1) < 0) {
-			if (errno != EINVAL) {
-				tst_resm(TFAIL, "readv() set an illegal errno:"
-					 " expected: EINVAL, got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EINVAL");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
+	for (i = 0; pbufs[i] != NULL; i++) {
+		switch (i) {
+		case 0:
+		case 1:
+			fill_mem(pbufs[i], 0, 1);
+			break;
+		case 2:
+			fill_mem(pbufs[i], 1, 0);
+			break;
+		default:
+			tst_brk(TBROK, "Error in init_buffs function");
 		}
+	}
+	return;
+}
 
-//test2:
-		l_seek(fd[0], CHUNK * 6, 0);
-		if (readv(fd[0], (rd_iovec + 6), 3) < 0) {
-			if (errno != EFAULT) {
-				tst_resm(TFAIL, "expected errno = EFAULT, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EFAULT");
-			}
-			if (memcmp((buf_list[0] + CHUNK * 6),
-				   (buf_list[1] + CHUNK * 6), CHUNK * 3) != 0) {
-				tst_resm(TFAIL, "Error: readv() partially "
-					 "overlaid buf[2]");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
+static void verify_readv(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
 
-//test3:
-		if (readv(fd[1], (rd_iovec + 9), 1) < 0) {
-			if (errno != EBADF) {
-				tst_resm(TFAIL, "expected errno = EBADF, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EBADF");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
+	TST_EXP_FAIL2(readv(*tc->fd, tc->buf, tc->count), tc->exp_error,
+		"readv(%d, %p, %d)", *tc->fd, tc->buf, tc->count);
 
-//test4:
-		l_seek(fd[0], CHUNK * 10, 0);
-		if (readv(fd[0], (rd_iovec + 10), -1) < 0) {
-			if (errno != EINVAL) {
-				tst_resm(TFAIL, "expected errno = EINVAL, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EINVAL");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
+	if (tc->exp_error == EFAULT) {
+		if (memcmp((buf_list[0] + CHUNK * 6),
+			(buf_list[1] + CHUNK * 6), CHUNK * 3)) {
+		    tst_res(TFAIL, "Error: readv() partially overlaid buf[2]");
 		}
-
 	}
-	close(fd[0]);
-	close(fd[1]);
-	cleanup();
-	tst_exit();
-
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
 void setup(void)
 {
-	int nbytes;
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* make a temporary directory and cd to it */
-	tst_tmpdir();
+	int i;
 
 	buf_list[0] = buf1;
 	buf_list[1] = buf2;
@@ -201,84 +133,37 @@ void setup(void)
 
 	init_buffs(buf_list);
 
-	sprintf(f_name, "%s.%d", DATA_FILE, getpid());
+	for (i = 0; i < 3; i++) {
+		fd[i] = SAFE_OPEN(TEST_FILE[i], O_WRONLY | O_CREAT, 0666);
+		SAFE_WRITE(1, fd[i], buf_list[2], K_1);
 
-	if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
-		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
-			 "errno = %d", f_name, errno);
-	} else {
-		if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1) {
-			tst_brkm(TBROK, cleanup, "write failed: nbytes "
-				 "= %d " "errno = %d", nbytes, errno);
-		}
-	}
+		SAFE_CLOSE(fd[i]);
 
-	SAFE_CLOSE(cleanup, fd[0]);
-
-	if ((fd[0] = open(f_name, O_RDONLY, 0666)) < 0) {
-		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
-			 "errno = %d", f_name, errno);
+		fd[i] = SAFE_OPEN(TEST_FILE[i], O_RDONLY, 0666);
 	}
+	SAFE_LSEEK(fd[1], CHUNK * 6, 0);
+	SAFE_LSEEK(fd[2], CHUNK * 10, 0);
 
-	fd[1] = -1;		/* Invalid file descriptor */
+	rd_iovec[6].iov_base = tst_get_bad_addr(NULL);
 
-	bad_addr = mmap(0, 1, PROT_NONE,
-			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
-	if (bad_addr == MAP_FAILED) {
-		tst_brkm(TBROK, cleanup, "mmap failed");
-	}
-	rd_iovec[6].iov_base = bad_addr;
+	SAFE_MKDIR(TEST_DIR, MODES);
+	fd[3] = SAFE_OPEN(TEST_DIR, O_RDONLY);
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *	       completion or premature exit.
- */
-void cleanup(void)
-{
-	SAFE_UNLINK(NULL, f_name);
-	tst_rmdir();
-
-}
-
-int init_buffs(char *pbufs[])
+static void cleanup(void)
 {
 	int i;
 
-	for (i = 0; pbufs[i] != NULL; i++) {
-		switch (i) {
-		case 0:
-		 /*FALLTHROUGH*/ case 1:
-			fill_mem(pbufs[i], 0, 1);
-			break;
-
-		case 2:
-			fill_mem(pbufs[i], 1, 0);
-			break;
-
-		default:
-			tst_brkm(TBROK, cleanup, "Error in init_buffs()");
-		}
-	}
-	return 0;
-}
-
-int fill_mem(char *c_ptr, int c1, int c2)
-{
-	int count;
-
-	for (count = 1; count <= K_1 / CHUNK; count++) {
-		if (count & 0x01) {	/* if odd */
-			memset(c_ptr, c1, CHUNK);
-		} else {	/* if even */
-			memset(c_ptr, c2, CHUNK);
-		}
+	for (i = 0; i < 4; i++) {
+		if (fd[i] > 0)
+			SAFE_CLOSE(fd[i]);
 	}
-	return 0;
 }
 
-long l_seek(int fdesc, long offset, int whence)
-{
-	SAFE_LSEEK(cleanup, fdesc, offset, whence);
-	return 0;
-}
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = verify_readv,
+};
diff --git a/testcases/kernel/syscalls/readv/readv03.c b/testcases/kernel/syscalls/readv/readv03.c
deleted file mode 100644
index 8f5cddf..0000000
--- a/testcases/kernel/syscalls/readv/readv03.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) Bull S.A. 2001
- * Copyright (c) International Business Machines  Corp., 2001
- * 05/2002 Ported by Jacky Malcles
- */
-
-/*\
- * [Description]
- *
- * Testcase to check EISDIR error when fd refers to a directory.
- */
-
-#include <sys/uio.h>
-#include <fcntl.h>
-#include "tst_test.h"
-
-#define K_1     1024
-#define MODES   S_IRWXU
-
-static char buf1[K_1];
-
-static struct iovec rd_iovec[1] = {
-        {buf1, K_1}
-};
-
-const char *TEST_DIR = "alpha";
-static int fd;
-
-static void verify_readv(void)
-{
-        TST_EXP_FAIL2(readv(fd, rd_iovec, 1), EISDIR,
-                     "readv() got EISDIR");
-}
-
-void setup(void)
-{
-        SAFE_MKDIR(TEST_DIR, MODES);
-        fd = SAFE_OPEN(TEST_DIR, O_RDONLY);
-}
-
-static void cleanup(void)
-{
-        if (fd > 0)
-                SAFE_CLOSE(fd);
-}
-
-static struct tst_test test = {
-        .needs_tmpdir = 1,
-        .setup = setup,
-        .cleanup = cleanup,
-        .test_all = verify_readv,
-};
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [LTP] [PATCH] syscalls/readv02: Convert to new API and merge readv03 into readv02.
  2021-07-30  5:48 [LTP] [PATCH] syscalls/readv02: Convert to new API and merge readv03 into readv02 Dai Shili
@ 2021-08-03 13:43 ` Cyril Hrubis
  2021-08-04  9:37   ` [LTP] 回复: " daisl.fnst
  2021-08-15 11:02   ` [LTP] [PATCH v2] " Dai Shili
  0 siblings, 2 replies; 5+ messages in thread
From: Cyril Hrubis @ 2021-08-03 13:43 UTC (permalink / raw)
  To: ltp

Hi!
> -	/* Test case #1 */
> +static struct iovec rd_iovec[MAX_IOVEC] = {
>  	{buf2, -1},
>  	{(buf2 + CHUNK), CHUNK},
>  	{(buf2 + CHUNK * 2), CHUNK},
> -
> -	/* Test case #2 */
>  	{(buf2 + CHUNK * 3), G_1},
>  	{(buf2 + CHUNK * 4), G_1},
>  	{(buf2 + CHUNK * 5), G_1},
> -
> -	/* Test case #3 */
>  	{(caddr_t) - 1, CHUNK},
>  	{(buf2 + CHUNK * 6), CHUNK},
>  	{(buf2 + CHUNK * 8), CHUNK},
> -
> -	/* Test case #4 */
> -	{(buf2 + CHUNK * 9), CHUNK}
> +	{(buf2 + CHUNK * 9), CHUNK},
> +	{buf1, K_1}
>  };

It would be much easier to read the code if we split this iovec so that
each test has it's own structure. There is absolutely no reason to keep
them all together like that.

I.e. we will have it as:

static struct iovec invalid_iovec[] = {
	{buf, -1},
	{buf + CHUNK, CHUNK},
	{buf + 2*CHUNK, CHUNK},
};

static struct iovec large_iovec[] = {
	{buf2, G_1},
	{buf2 + CHUNK, G_1},
	{buf2 + CHUNK*2, G_1},
};

static struct iovec efault_iovec[] = {
	{NULL, CHUNK},
	{buf + CHUNK, CHUNK},
	{buf + 2*CHUNK, CHUNK},
};

static struct iovec valid_iovec[] = {
	{buf, CHUNK},
};

Also we can use the valid iovec for both EISDIR and EBADFD.

static void setup(void)
{
	...
	efault_iovec[0].iov_base = tst_get_bad_addr(NULL);
	...
}

Also I do not think that we need three buffers, the buf3 is completely
unused and there is no point in having special buffer for badfd test
either.

> -char f_name[K_1];
> -
> -int fd[4];
> -char *buf_list[NBUFS];
> -
> -char *TCID = "readv02";
> -int TST_TOTAL = 1;
> -
> -char *bad_addr = 0;
> +static struct tcase {
> +	int *fd;
> +	void *buf;
> +	int count;
> +	int exp_error;
> +} tcases[] = {
> +	{&fd[0], rd_iovec, 1, EINVAL},
> +	{&fd[1], rd_iovec + 6, 3, EFAULT},
> +	{&fd[2], rd_iovec + 10, -1, EINVAL},
> +	{&fd[3], rd_iovec + 10, 1, EISDIR},
> +	{&badfd, rd_iovec + 9, 3, EBADF},
> +};
>  
> -int init_buffs(char **);
> -int fill_mem(char *, int, int);
> -long l_seek(int, long, int);
> -char *getenv();
> -void setup();
> -void cleanup();
>  
> -int main(int ac, char **av)
> +void fill_mem(char *c_ptr, int c1, int c2)
>  {
> -	int lc;
> -
> -	tst_parse_opts(ac, av, NULL, NULL);
> -
> -	setup();
> +	int count;
>  
> -	/* The following loop checks looping state if -i option given */
> -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> +	for (count = 1; count <= K_1 / CHUNK; count++) {
> +		if (count & 0x01) /* if odd */
> +			memset(c_ptr, c1, CHUNK);
> +		else /* if even */
> +			memset(c_ptr, c2, CHUNK);
> +	}
> +	return;
> +}
>  
> -		/* reset tst_count in case we are looping */
> -		tst_count = 0;
> +void init_buffs(char *pbufs[])
> +{
> +	int i;
>  
> -//test1:
> -		if (readv(fd[0], rd_iovec, 1) < 0) {
> -			if (errno != EINVAL) {
> -				tst_resm(TFAIL, "readv() set an illegal errno:"
> -					 " expected: EINVAL, got %d", errno);
> -			} else {
> -				tst_resm(TPASS, "got EINVAL");
> -			}
> -		} else {
> -			tst_resm(TFAIL, "Error: readv returned a positive "
> -				 "value");
> +	for (i = 0; pbufs[i] != NULL; i++) {
> +		switch (i) {
> +		case 0:
> +		case 1:
> +			fill_mem(pbufs[i], 0, 1);
> +			break;
> +		case 2:
> +			fill_mem(pbufs[i], 1, 0);
> +			break;
> +		default:
> +			tst_brk(TBROK, "Error in init_buffs function");
>  		}
> +	}
> +	return;
> +}
>  
> -//test2:
> -		l_seek(fd[0], CHUNK * 6, 0);
> -		if (readv(fd[0], (rd_iovec + 6), 3) < 0) {
> -			if (errno != EFAULT) {
> -				tst_resm(TFAIL, "expected errno = EFAULT, "
> -					 "got %d", errno);
> -			} else {
> -				tst_resm(TPASS, "got EFAULT");
> -			}
> -			if (memcmp((buf_list[0] + CHUNK * 6),
> -				   (buf_list[1] + CHUNK * 6), CHUNK * 3) != 0) {
> -				tst_resm(TFAIL, "Error: readv() partially "
> -					 "overlaid buf[2]");
> -			}
> -		} else {
> -			tst_resm(TFAIL, "Error: readv returned a positive "
> -				 "value");
> -		}
> +static void verify_readv(unsigned int n)
> +{
> +	struct tcase *tc = &tcases[n];
>  
> -//test3:
> -		if (readv(fd[1], (rd_iovec + 9), 1) < 0) {
> -			if (errno != EBADF) {
> -				tst_resm(TFAIL, "expected errno = EBADF, "
> -					 "got %d", errno);
> -			} else {
> -				tst_resm(TPASS, "got EBADF");
> -			}
> -		} else {
> -			tst_resm(TFAIL, "Error: readv returned a positive "
> -				 "value");
> -		}
> +	TST_EXP_FAIL2(readv(*tc->fd, tc->buf, tc->count), tc->exp_error,
> +		"readv(%d, %p, %d)", *tc->fd, tc->buf, tc->count);
>  
> -//test4:
> -		l_seek(fd[0], CHUNK * 10, 0);
> -		if (readv(fd[0], (rd_iovec + 10), -1) < 0) {
> -			if (errno != EINVAL) {
> -				tst_resm(TFAIL, "expected errno = EINVAL, "
> -					 "got %d", errno);
> -			} else {
> -				tst_resm(TPASS, "got EINVAL");
> -			}
> -		} else {
> -			tst_resm(TFAIL, "Error: readv returned a positive "
> -				 "value");
> +	if (tc->exp_error == EFAULT) {
> +		if (memcmp((buf_list[0] + CHUNK * 6),
> +			(buf_list[1] + CHUNK * 6), CHUNK * 3)) {
> +		    tst_res(TFAIL, "Error: readv() partially overlaid buf[2]");
>  		}
> -
>  	}
> -	close(fd[0]);
> -	close(fd[1]);
> -	cleanup();
> -	tst_exit();
> -
>  }
>  
> -/*
> - * setup() - performs all ONE TIME setup for this test.
> - */
>  void setup(void)
>  {
> -	int nbytes;
> -
> -	tst_sig(NOFORK, DEF_HANDLER, cleanup);
> -
> -	TEST_PAUSE;
> -
> -	/* make a temporary directory and cd to it */
> -	tst_tmpdir();
> +	int i;
>  
>  	buf_list[0] = buf1;
>  	buf_list[1] = buf2;
> @@ -201,84 +133,37 @@ void setup(void)
>  
>  	init_buffs(buf_list);
>  
> -	sprintf(f_name, "%s.%d", DATA_FILE, getpid());
> +	for (i = 0; i < 3; i++) {
> +		fd[i] = SAFE_OPEN(TEST_FILE[i], O_WRONLY | O_CREAT, 0666);
> +		SAFE_WRITE(1, fd[i], buf_list[2], K_1);
>  
> -	if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
> -		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
> -			 "errno = %d", f_name, errno);
> -	} else {
> -		if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1) {
> -			tst_brkm(TBROK, cleanup, "write failed: nbytes "
> -				 "= %d " "errno = %d", nbytes, errno);
> -		}
> -	}
> +		SAFE_CLOSE(fd[i]);
>  
> -	SAFE_CLOSE(cleanup, fd[0]);
> -
> -	if ((fd[0] = open(f_name, O_RDONLY, 0666)) < 0) {
> -		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
> -			 "errno = %d", f_name, errno);
> +		fd[i] = SAFE_OPEN(TEST_FILE[i], O_RDONLY, 0666);
>  	}
> +	SAFE_LSEEK(fd[1], CHUNK * 6, 0);
> +	SAFE_LSEEK(fd[2], CHUNK * 10, 0);

Does these readv calls actually read anyting?

Because as far as I can tell they just fail without actually reading
anything, so there is no point in intializing the buffers and also there
is no point in having three different files opened for the test either.

> -	fd[1] = -1;		/* Invalid file descriptor */
> +	rd_iovec[6].iov_base = tst_get_bad_addr(NULL);
>  
> -	bad_addr = mmap(0, 1, PROT_NONE,
> -			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
> -	if (bad_addr == MAP_FAILED) {
> -		tst_brkm(TBROK, cleanup, "mmap failed");
> -	}
> -	rd_iovec[6].iov_base = bad_addr;
> +	SAFE_MKDIR(TEST_DIR, MODES);
> +	fd[3] = SAFE_OPEN(TEST_DIR, O_RDONLY);
>  }
>  
> -/*
> - * cleanup() - performs all ONE TIME cleanup for this test at
> - *	       completion or premature exit.
> - */
> -void cleanup(void)
> -{
> -	SAFE_UNLINK(NULL, f_name);
> -	tst_rmdir();
> -
> -}
> -
> -int init_buffs(char *pbufs[])
> +static void cleanup(void)
>  {
>  	int i;
>  
> -	for (i = 0; pbufs[i] != NULL; i++) {
> -		switch (i) {
> -		case 0:
> -		 /*FALLTHROUGH*/ case 1:
> -			fill_mem(pbufs[i], 0, 1);
> -			break;
> -
> -		case 2:
> -			fill_mem(pbufs[i], 1, 0);
> -			break;
> -
> -		default:
> -			tst_brkm(TBROK, cleanup, "Error in init_buffs()");
> -		}
> -	}
> -	return 0;
> -}
> -
> -int fill_mem(char *c_ptr, int c1, int c2)
> -{
> -	int count;
> -
> -	for (count = 1; count <= K_1 / CHUNK; count++) {
> -		if (count & 0x01) {	/* if odd */
> -			memset(c_ptr, c1, CHUNK);
> -		} else {	/* if even */
> -			memset(c_ptr, c2, CHUNK);
> -		}
> +	for (i = 0; i < 4; i++) {
> +		if (fd[i] > 0)
> +			SAFE_CLOSE(fd[i]);
>  	}
> -	return 0;
>  }
>  
> -long l_seek(int fdesc, long offset, int whence)
> -{
> -	SAFE_LSEEK(cleanup, fdesc, offset, whence);
> -	return 0;
> -}
> +static struct tst_test test = {
> +	.tcnt = ARRAY_SIZE(tcases),
> +	.needs_tmpdir = 1,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test = verify_readv,
> +};

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [LTP] 回复:  [PATCH] syscalls/readv02: Convert to new API and merge readv03 into readv02.
  2021-08-03 13:43 ` Cyril Hrubis
@ 2021-08-04  9:37   ` daisl.fnst
  2021-08-15 11:02   ` [LTP] [PATCH v2] " Dai Shili
  1 sibling, 0 replies; 5+ messages in thread
From: daisl.fnst @ 2021-08-04  9:37 UTC (permalink / raw)
  To: ltp

Hi Cyril,

Thank you very much for your comments. I will send a v2.

> -----????-----
> ???: Cyril Hrubis <chrubis@suse.cz>
> ????: 2021?8?3? 21:44
> ???: Dai, Shili/? ?? <daisl.fnst@fujitsu.com>
> ??: ltp@lists.linux.it
> ??: Re: [LTP] [PATCH] syscalls/readv02: Convert to new API and merge
> readv03 into readv02.
> 
> Hi!
> > -	/* Test case #1 */
> > +static struct iovec rd_iovec[MAX_IOVEC] = {
> >  	{buf2, -1},
> >  	{(buf2 + CHUNK), CHUNK},
> >  	{(buf2 + CHUNK * 2), CHUNK},
> > -
> > -	/* Test case #2 */
> >  	{(buf2 + CHUNK * 3), G_1},
> >  	{(buf2 + CHUNK * 4), G_1},
> >  	{(buf2 + CHUNK * 5), G_1},
> > -
> > -	/* Test case #3 */
> >  	{(caddr_t) - 1, CHUNK},
> >  	{(buf2 + CHUNK * 6), CHUNK},
> >  	{(buf2 + CHUNK * 8), CHUNK},
> > -
> > -	/* Test case #4 */
> > -	{(buf2 + CHUNK * 9), CHUNK}
> > +	{(buf2 + CHUNK * 9), CHUNK},
> > +	{buf1, K_1}
> >  };
> 
> It would be much easier to read the code if we split this iovec so that each test
> has it's own structure. There is absolutely no reason to keep them all together
> like that.
> 
> I.e. we will have it as:
> 
> static struct iovec invalid_iovec[] = {
> 	{buf, -1},
> 	{buf + CHUNK, CHUNK},
> 	{buf + 2*CHUNK, CHUNK},
> };
> 
> static struct iovec large_iovec[] = {
> 	{buf2, G_1},
> 	{buf2 + CHUNK, G_1},
> 	{buf2 + CHUNK*2, G_1},
> };
> 
> static struct iovec efault_iovec[] = {
> 	{NULL, CHUNK},
> 	{buf + CHUNK, CHUNK},
> 	{buf + 2*CHUNK, CHUNK},
> };
> 
> static struct iovec valid_iovec[] = {
> 	{buf, CHUNK},
> };
> 
> Also we can use the valid iovec for both EISDIR and EBADFD.
> 
> static void setup(void)
> {
> 	...
> 	efault_iovec[0].iov_base = tst_get_bad_addr(NULL);
> 	...
> }
> 
> Also I do not think that we need three buffers, the buf3 is completely unused
> and there is no point in having special buffer for badfd test either.
> 
> > -char f_name[K_1];
> > -
> > -int fd[4];
> > -char *buf_list[NBUFS];
> > -
> > -char *TCID = "readv02";
> > -int TST_TOTAL = 1;
> > -
> > -char *bad_addr = 0;
> > +static struct tcase {
> > +	int *fd;
> > +	void *buf;
> > +	int count;
> > +	int exp_error;
> > +} tcases[] = {
> > +	{&fd[0], rd_iovec, 1, EINVAL},
> > +	{&fd[1], rd_iovec + 6, 3, EFAULT},
> > +	{&fd[2], rd_iovec + 10, -1, EINVAL},
> > +	{&fd[3], rd_iovec + 10, 1, EISDIR},
> > +	{&badfd, rd_iovec + 9, 3, EBADF},
> > +};
> >
> > -int init_buffs(char **);
> > -int fill_mem(char *, int, int);
> > -long l_seek(int, long, int);
> > -char *getenv();
> > -void setup();
> > -void cleanup();
> >
> > -int main(int ac, char **av)
> > +void fill_mem(char *c_ptr, int c1, int c2)
> >  {
> > -	int lc;
> > -
> > -	tst_parse_opts(ac, av, NULL, NULL);
> > -
> > -	setup();
> > +	int count;
> >
> > -	/* The following loop checks looping state if -i option given */
> > -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> > +	for (count = 1; count <= K_1 / CHUNK; count++) {
> > +		if (count & 0x01) /* if odd */
> > +			memset(c_ptr, c1, CHUNK);
> > +		else /* if even */
> > +			memset(c_ptr, c2, CHUNK);
> > +	}
> > +	return;
> > +}
> >
> > -		/* reset tst_count in case we are looping */
> > -		tst_count = 0;
> > +void init_buffs(char *pbufs[])
> > +{
> > +	int i;
> >
> > -//test1:
> > -		if (readv(fd[0], rd_iovec, 1) < 0) {
> > -			if (errno != EINVAL) {
> > -				tst_resm(TFAIL, "readv() set an illegal errno:"
> > -					 " expected: EINVAL, got %d", errno);
> > -			} else {
> > -				tst_resm(TPASS, "got EINVAL");
> > -			}
> > -		} else {
> > -			tst_resm(TFAIL, "Error: readv returned a positive "
> > -				 "value");
> > +	for (i = 0; pbufs[i] != NULL; i++) {
> > +		switch (i) {
> > +		case 0:
> > +		case 1:
> > +			fill_mem(pbufs[i], 0, 1);
> > +			break;
> > +		case 2:
> > +			fill_mem(pbufs[i], 1, 0);
> > +			break;
> > +		default:
> > +			tst_brk(TBROK, "Error in init_buffs function");
> >  		}
> > +	}
> > +	return;
> > +}
> >
> > -//test2:
> > -		l_seek(fd[0], CHUNK * 6, 0);
> > -		if (readv(fd[0], (rd_iovec + 6), 3) < 0) {
> > -			if (errno != EFAULT) {
> > -				tst_resm(TFAIL, "expected errno = EFAULT, "
> > -					 "got %d", errno);
> > -			} else {
> > -				tst_resm(TPASS, "got EFAULT");
> > -			}
> > -			if (memcmp((buf_list[0] + CHUNK * 6),
> > -				   (buf_list[1] + CHUNK * 6), CHUNK * 3) != 0) {
> > -				tst_resm(TFAIL, "Error: readv() partially "
> > -					 "overlaid buf[2]");
> > -			}
> > -		} else {
> > -			tst_resm(TFAIL, "Error: readv returned a positive "
> > -				 "value");
> > -		}
> > +static void verify_readv(unsigned int n) {
> > +	struct tcase *tc = &tcases[n];
> >
> > -//test3:
> > -		if (readv(fd[1], (rd_iovec + 9), 1) < 0) {
> > -			if (errno != EBADF) {
> > -				tst_resm(TFAIL, "expected errno = EBADF, "
> > -					 "got %d", errno);
> > -			} else {
> > -				tst_resm(TPASS, "got EBADF");
> > -			}
> > -		} else {
> > -			tst_resm(TFAIL, "Error: readv returned a positive "
> > -				 "value");
> > -		}
> > +	TST_EXP_FAIL2(readv(*tc->fd, tc->buf, tc->count), tc->exp_error,
> > +		"readv(%d, %p, %d)", *tc->fd, tc->buf, tc->count);
> >
> > -//test4:
> > -		l_seek(fd[0], CHUNK * 10, 0);
> > -		if (readv(fd[0], (rd_iovec + 10), -1) < 0) {
> > -			if (errno != EINVAL) {
> > -				tst_resm(TFAIL, "expected errno = EINVAL, "
> > -					 "got %d", errno);
> > -			} else {
> > -				tst_resm(TPASS, "got EINVAL");
> > -			}
> > -		} else {
> > -			tst_resm(TFAIL, "Error: readv returned a positive "
> > -				 "value");
> > +	if (tc->exp_error == EFAULT) {
> > +		if (memcmp((buf_list[0] + CHUNK * 6),
> > +			(buf_list[1] + CHUNK * 6), CHUNK * 3)) {
> > +		    tst_res(TFAIL, "Error: readv() partially overlaid buf[2]");
> >  		}
> > -
> >  	}
> > -	close(fd[0]);
> > -	close(fd[1]);
> > -	cleanup();
> > -	tst_exit();
> > -
> >  }
> >
> > -/*
> > - * setup() - performs all ONE TIME setup for this test.
> > - */
> >  void setup(void)
> >  {
> > -	int nbytes;
> > -
> > -	tst_sig(NOFORK, DEF_HANDLER, cleanup);
> > -
> > -	TEST_PAUSE;
> > -
> > -	/* make a temporary directory and cd to it */
> > -	tst_tmpdir();
> > +	int i;
> >
> >  	buf_list[0] = buf1;
> >  	buf_list[1] = buf2;
> > @@ -201,84 +133,37 @@ void setup(void)
> >
> >  	init_buffs(buf_list);
> >
> > -	sprintf(f_name, "%s.%d", DATA_FILE, getpid());
> > +	for (i = 0; i < 3; i++) {
> > +		fd[i] = SAFE_OPEN(TEST_FILE[i], O_WRONLY | O_CREAT, 0666);
> > +		SAFE_WRITE(1, fd[i], buf_list[2], K_1);
> >
> > -	if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
> > -		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
> > -			 "errno = %d", f_name, errno);
> > -	} else {
> > -		if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1) {
> > -			tst_brkm(TBROK, cleanup, "write failed: nbytes "
> > -				 "= %d " "errno = %d", nbytes, errno);
> > -		}
> > -	}
> > +		SAFE_CLOSE(fd[i]);
> >
> > -	SAFE_CLOSE(cleanup, fd[0]);
> > -
> > -	if ((fd[0] = open(f_name, O_RDONLY, 0666)) < 0) {
> > -		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
> > -			 "errno = %d", f_name, errno);
> > +		fd[i] = SAFE_OPEN(TEST_FILE[i], O_RDONLY, 0666);
> >  	}
> > +	SAFE_LSEEK(fd[1], CHUNK * 6, 0);
> > +	SAFE_LSEEK(fd[2], CHUNK * 10, 0);
> 
> Does these readv calls actually read anyting?
> 
> Because as far as I can tell they just fail without actually reading anything, so
> there is no point in intializing the buffers and also there is no point in having
> three different files opened for the test either.
> 
> > -	fd[1] = -1;		/* Invalid file descriptor */
> > +	rd_iovec[6].iov_base = tst_get_bad_addr(NULL);
> >
> > -	bad_addr = mmap(0, 1, PROT_NONE,
> > -			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
> > -	if (bad_addr == MAP_FAILED) {
> > -		tst_brkm(TBROK, cleanup, "mmap failed");
> > -	}
> > -	rd_iovec[6].iov_base = bad_addr;
> > +	SAFE_MKDIR(TEST_DIR, MODES);
> > +	fd[3] = SAFE_OPEN(TEST_DIR, O_RDONLY);
> >  }
> >
> > -/*
> > - * cleanup() - performs all ONE TIME cleanup for this test at
> > - *	       completion or premature exit.
> > - */
> > -void cleanup(void)
> > -{
> > -	SAFE_UNLINK(NULL, f_name);
> > -	tst_rmdir();
> > -
> > -}
> > -
> > -int init_buffs(char *pbufs[])
> > +static void cleanup(void)
> >  {
> >  	int i;
> >
> > -	for (i = 0; pbufs[i] != NULL; i++) {
> > -		switch (i) {
> > -		case 0:
> > -		 /*FALLTHROUGH*/ case 1:
> > -			fill_mem(pbufs[i], 0, 1);
> > -			break;
> > -
> > -		case 2:
> > -			fill_mem(pbufs[i], 1, 0);
> > -			break;
> > -
> > -		default:
> > -			tst_brkm(TBROK, cleanup, "Error in init_buffs()");
> > -		}
> > -	}
> > -	return 0;
> > -}
> > -
> > -int fill_mem(char *c_ptr, int c1, int c2) -{
> > -	int count;
> > -
> > -	for (count = 1; count <= K_1 / CHUNK; count++) {
> > -		if (count & 0x01) {	/* if odd */
> > -			memset(c_ptr, c1, CHUNK);
> > -		} else {	/* if even */
> > -			memset(c_ptr, c2, CHUNK);
> > -		}
> > +	for (i = 0; i < 4; i++) {
> > +		if (fd[i] > 0)
> > +			SAFE_CLOSE(fd[i]);
> >  	}
> > -	return 0;
> >  }
> >
> > -long l_seek(int fdesc, long offset, int whence) -{
> > -	SAFE_LSEEK(cleanup, fdesc, offset, whence);
> > -	return 0;
> > -}
> > +static struct tst_test test = {
> > +	.tcnt = ARRAY_SIZE(tcases),
> > +	.needs_tmpdir = 1,
> > +	.setup = setup,
> > +	.cleanup = cleanup,
> > +	.test = verify_readv,
> > +};
> 
> --
> Cyril Hrubis
> chrubis@suse.cz

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [LTP] [PATCH v2] syscalls/readv02: Convert to new API and merge readv03 into readv02
  2021-08-03 13:43 ` Cyril Hrubis
  2021-08-04  9:37   ` [LTP] 回复: " daisl.fnst
@ 2021-08-15 11:02   ` Dai Shili
  2021-08-31 15:55     ` Cyril Hrubis
  1 sibling, 1 reply; 5+ messages in thread
From: Dai Shili @ 2021-08-15 11:02 UTC (permalink / raw)
  To: ltp

1) merge readv03 into readv02
2) use tst_get_bad_addr() API
3) use TST_EXP_FAIL2 macro

Signed-off-by: Dai Shili <daisl.fnst@fujitsu.com>
---
 runtest/syscalls                           |   1 -
 testcases/kernel/syscalls/readv/.gitignore |   1 -
 testcases/kernel/syscalls/readv/readv02.c  | 327 +++++++----------------------
 testcases/kernel/syscalls/readv/readv03.c  |  53 -----
 4 files changed, 79 insertions(+), 303 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/readv/readv03.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 9af5aa5..cb04a88 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1085,7 +1085,6 @@ readlinkat02 readlinkat02
 
 readv01 readv01
 readv02 readv02
-readv03 readv03
 
 realpath01 realpath01
 
diff --git a/testcases/kernel/syscalls/readv/.gitignore b/testcases/kernel/syscalls/readv/.gitignore
index c4aa61e..a532741 100644
--- a/testcases/kernel/syscalls/readv/.gitignore
+++ b/testcases/kernel/syscalls/readv/.gitignore
@@ -1,3 +1,2 @@
 /readv01
 /readv02
-/readv03
diff --git a/testcases/kernel/syscalls/readv/readv02.c b/testcases/kernel/syscalls/readv/readv02.c
index aa40e2c..9a26e50 100644
--- a/testcases/kernel/syscalls/readv/readv02.c
+++ b/testcases/kernel/syscalls/readv/readv02.c
@@ -1,284 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) Bull S.A. 2001
+ * Copyright (c) International Business Machines  Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * 05/2002 Ported by Jacky Malcles
  */
 
-/*
- * NAME
- * 	readv02.c
- *
+/*\
  * DESCRIPTION
- *	Testcase to check the error conditions of the readv(2) system call.
+ *  test 1:
+ *  The sum of the iov_len values overflows an ssize_t value, expect an EINVAL.
  *
- * CALLS
- * 	readv()
+ *  test 2:
+ *  Buf is outside the accessible address space, expect an EFAULT.
  *
- * ALGORITHM
- *	Create a IO vector, and attempt to readv() various components of it.
+ *  test 3:
+ *  The vector count iovcnt is less than zero, expect an EINVAL.
  *
- * USAGE
- *	readv02
+ *  test 4:
+ *  The parameter passed to read is a directory, check if the errno is
+ *  set to EISDIR.
  *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * 	None
+ *  test 5:
+ *  Read with an invalid file descriptor, and expect an EBADF.
  */
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <memory.h>
-#include <errno.h>
 
-#include "test.h"
-#include "safe_macros.h"
-
-#define	K_1	1024
-#define	M_1	K_1 * K_1
-#define	G_1	M_1 * K_1
-
-#define	NBUFS		4
-#define	CHUNK		64
-#define	MAX_IOVEC	16
-#define DATA_FILE	"readv_data_file"
-
-char buf1[K_1], buf2[K_1], buf3[K_1];
-
-struct iovec rd_iovec[MAX_IOVEC] = {
-	/* iov_base *//* iov_len */
+#include <sys/uio.h>
+#include "tst_test.h"
 
-	/* Test case #1 */
-	{buf2, -1},
-	{(buf2 + CHUNK), CHUNK},
-	{(buf2 + CHUNK * 2), CHUNK},
+#define K_1     1024
+#define MODES   0700
 
-	/* Test case #2 */
-	{(buf2 + CHUNK * 3), G_1},
-	{(buf2 + CHUNK * 4), G_1},
-	{(buf2 + CHUNK * 5), G_1},
+#define CHUNK           64
 
-	/* Test case #3 */
-	{(caddr_t) - 1, CHUNK},
-	{(buf2 + CHUNK * 6), CHUNK},
-	{(buf2 + CHUNK * 8), CHUNK},
+static int badfd = -1;
+static int fd[2] = {-1, -1};
+static char buf1[K_1];
+const char *TEST_DIR = "test_dir";
+const char *TEST_FILE = "test_file";
 
-	/* Test case #4 */
-	{(buf2 + CHUNK * 9), CHUNK}
+static struct iovec invalid_iovec[] = {
+	{buf1, -1},
+	{buf1 + CHUNK, CHUNK},
+	{buf1 + 2*CHUNK, CHUNK},
 };
 
-char f_name[K_1];
-
-int fd[4];
-char *buf_list[NBUFS];
+static struct iovec large_iovec[] = {
+	{buf1, K_1},
+	{buf1 + CHUNK, K_1},
+	{buf1 + CHUNK*2, K_1},
+};
 
-char *TCID = "readv02";
-int TST_TOTAL = 1;
+static struct iovec efault_iovec[] = {
+	{NULL, CHUNK},
+	{buf1 + CHUNK, CHUNK},
+	{buf1 + 2*CHUNK, CHUNK},
+};
 
-char *bad_addr = 0;
+static struct iovec valid_iovec[] = {
+	{buf1, CHUNK},
+};
 
-int init_buffs(char **);
-int fill_mem(char *, int, int);
-long l_seek(int, long, int);
-char *getenv();
-void setup();
-void cleanup();
+static struct tcase {
+	int *fd;
+	void *buf;
+	int count;
+	int exp_error;
+} tcases[] = {
+	{&fd[0], invalid_iovec, 1, EINVAL},
+	{&fd[0], efault_iovec, 3, EFAULT},
+	{&fd[0], large_iovec, -1, EINVAL},
+	{&fd[1], valid_iovec, 1, EISDIR},
+	{&badfd, valid_iovec, 3, EBADF},
+};
 
-int main(int ac, char **av)
+static void verify_readv(unsigned int n)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
-
-	/* The following loop checks looping state if -i option given */
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
-
-//test1:
-		if (readv(fd[0], rd_iovec, 1) < 0) {
-			if (errno != EINVAL) {
-				tst_resm(TFAIL, "readv() set an illegal errno:"
-					 " expected: EINVAL, got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EINVAL");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
-
-//test2:
-		l_seek(fd[0], CHUNK * 6, 0);
-		if (readv(fd[0], (rd_iovec + 6), 3) < 0) {
-			if (errno != EFAULT) {
-				tst_resm(TFAIL, "expected errno = EFAULT, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EFAULT");
-			}
-			if (memcmp((buf_list[0] + CHUNK * 6),
-				   (buf_list[1] + CHUNK * 6), CHUNK * 3) != 0) {
-				tst_resm(TFAIL, "Error: readv() partially "
-					 "overlaid buf[2]");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
-
-//test3:
-		if (readv(fd[1], (rd_iovec + 9), 1) < 0) {
-			if (errno != EBADF) {
-				tst_resm(TFAIL, "expected errno = EBADF, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EBADF");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
-
-//test4:
-		l_seek(fd[0], CHUNK * 10, 0);
-		if (readv(fd[0], (rd_iovec + 10), -1) < 0) {
-			if (errno != EINVAL) {
-				tst_resm(TFAIL, "expected errno = EINVAL, "
-					 "got %d", errno);
-			} else {
-				tst_resm(TPASS, "got EINVAL");
-			}
-		} else {
-			tst_resm(TFAIL, "Error: readv returned a positive "
-				 "value");
-		}
-
-	}
-	close(fd[0]);
-	close(fd[1]);
-	cleanup();
-	tst_exit();
+	struct tcase *tc = &tcases[n];
 
+	TST_EXP_FAIL2(readv(*tc->fd, tc->buf, tc->count), tc->exp_error,
+		"readv(%d, %p, %d)", *tc->fd, tc->buf, tc->count);
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void setup(void)
 {
-	int nbytes;
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	/* make a temporary directory and cd to it */
-	tst_tmpdir();
+	fd[0] = SAFE_OPEN(TEST_FILE, O_WRONLY | O_CREAT, 0666);
+	SAFE_WRITE(1, fd[0], buf1, CHUNK);
+	SAFE_CLOSE(fd[0]);
 
-	buf_list[0] = buf1;
-	buf_list[1] = buf2;
-	buf_list[2] = buf3;
-	buf_list[3] = NULL;
-
-	init_buffs(buf_list);
-
-	sprintf(f_name, "%s.%d", DATA_FILE, getpid());
-
-	if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) < 0) {
-		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
-			 "errno = %d", f_name, errno);
-	} else {
-		if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1) {
-			tst_brkm(TBROK, cleanup, "write failed: nbytes "
-				 "= %d " "errno = %d", nbytes, errno);
-		}
-	}
+	fd[0] = SAFE_OPEN(TEST_FILE, O_RDONLY, 0666);
 
-	SAFE_CLOSE(cleanup, fd[0]);
+	efault_iovec[0].iov_base = tst_get_bad_addr(NULL);
 
-	if ((fd[0] = open(f_name, O_RDONLY, 0666)) < 0) {
-		tst_brkm(TBROK, cleanup, "open failed: fname = %s, "
-			 "errno = %d", f_name, errno);
-	}
-
-	fd[1] = -1;		/* Invalid file descriptor */
-
-	bad_addr = mmap(0, 1, PROT_NONE,
-			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
-	if (bad_addr == MAP_FAILED) {
-		tst_brkm(TBROK, cleanup, "mmap failed");
-	}
-	rd_iovec[6].iov_base = bad_addr;
+	SAFE_MKDIR(TEST_DIR, MODES);
+	fd[1] = SAFE_OPEN(TEST_DIR, O_RDONLY);
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *	       completion or premature exit.
- */
-void cleanup(void)
-{
-	SAFE_UNLINK(NULL, f_name);
-	tst_rmdir();
-
-}
-
-int init_buffs(char *pbufs[])
+static void cleanup(void)
 {
 	int i;
 
-	for (i = 0; pbufs[i] != NULL; i++) {
-		switch (i) {
-		case 0:
-		 /*FALLTHROUGH*/ case 1:
-			fill_mem(pbufs[i], 0, 1);
-			break;
-
-		case 2:
-			fill_mem(pbufs[i], 1, 0);
-			break;
-
-		default:
-			tst_brkm(TBROK, cleanup, "Error in init_buffs()");
-		}
-	}
-	return 0;
-}
-
-int fill_mem(char *c_ptr, int c1, int c2)
-{
-	int count;
-
-	for (count = 1; count <= K_1 / CHUNK; count++) {
-		if (count & 0x01) {	/* if odd */
-			memset(c_ptr, c1, CHUNK);
-		} else {	/* if even */
-			memset(c_ptr, c2, CHUNK);
-		}
+	for (i = 0; i < 2; i++) {
+		if (fd[i] > 0)
+			SAFE_CLOSE(fd[i]);
 	}
-	return 0;
 }
 
-long l_seek(int fdesc, long offset, int whence)
-{
-	SAFE_LSEEK(cleanup, fdesc, offset, whence);
-	return 0;
-}
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = verify_readv,
+};
diff --git a/testcases/kernel/syscalls/readv/readv03.c b/testcases/kernel/syscalls/readv/readv03.c
deleted file mode 100644
index 8f5cddf..0000000
--- a/testcases/kernel/syscalls/readv/readv03.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) Bull S.A. 2001
- * Copyright (c) International Business Machines  Corp., 2001
- * 05/2002 Ported by Jacky Malcles
- */
-
-/*\
- * [Description]
- *
- * Testcase to check EISDIR error when fd refers to a directory.
- */
-
-#include <sys/uio.h>
-#include <fcntl.h>
-#include "tst_test.h"
-
-#define K_1     1024
-#define MODES   S_IRWXU
-
-static char buf1[K_1];
-
-static struct iovec rd_iovec[1] = {
-        {buf1, K_1}
-};
-
-const char *TEST_DIR = "alpha";
-static int fd;
-
-static void verify_readv(void)
-{
-        TST_EXP_FAIL2(readv(fd, rd_iovec, 1), EISDIR,
-                     "readv() got EISDIR");
-}
-
-void setup(void)
-{
-        SAFE_MKDIR(TEST_DIR, MODES);
-        fd = SAFE_OPEN(TEST_DIR, O_RDONLY);
-}
-
-static void cleanup(void)
-{
-        if (fd > 0)
-                SAFE_CLOSE(fd);
-}
-
-static struct tst_test test = {
-        .needs_tmpdir = 1,
-        .setup = setup,
-        .cleanup = cleanup,
-        .test_all = verify_readv,
-};
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [LTP] [PATCH v2] syscalls/readv02: Convert to new API and merge readv03 into readv02
  2021-08-15 11:02   ` [LTP] [PATCH v2] " Dai Shili
@ 2021-08-31 15:55     ` Cyril Hrubis
  0 siblings, 0 replies; 5+ messages in thread
From: Cyril Hrubis @ 2021-08-31 15:55 UTC (permalink / raw)
  To: ltp

Hi!
Pushed with minor changes, thanks.

- reformatted the documentation comment so that it renders nicely in
  asccidoc

- got rid of the fd array, it's a bit more readable with fd_file and
  fd_dir instead

- simplified setup a bit

Full diff:

diff --git a/testcases/kernel/syscalls/readv/readv02.c b/testcases/kernel/syscalls/readv/readv02.c
index 9a26e50a8..c09e69bc8 100644
--- a/testcases/kernel/syscalls/readv/readv02.c
+++ b/testcases/kernel/syscalls/readv/readv02.c
@@ -7,22 +7,15 @@
  */
 
 /*\
- * DESCRIPTION
- *  test 1:
- *  The sum of the iov_len values overflows an ssize_t value, expect an EINVAL.
+ * [Description]
  *
- *  test 2:
- *  Buf is outside the accessible address space, expect an EFAULT.
+ * Tests readv() failures:
  *
- *  test 3:
- *  The vector count iovcnt is less than zero, expect an EINVAL.
- *
- *  test 4:
- *  The parameter passed to read is a directory, check if the errno is
- *  set to EISDIR.
- *
- *  test 5:
- *  Read with an invalid file descriptor, and expect an EBADF.
+ * - EINVAL the sum of the iov_len values overflows an ssize_t value
+ * - EFAULT buffer is outside the accessible address space
+ * - EINVAL the vector count iovcnt is less than zero
+ * - EISDIR the file descriptor is a directory
+ * - EBADF  the file descriptor is not valid
  */
 
 #include <sys/uio.h>
@@ -34,7 +27,7 @@
 #define CHUNK           64
 
 static int badfd = -1;
-static int fd[2] = {-1, -1};
+static int fd_dir, fd_file;
 static char buf1[K_1];
 const char *TEST_DIR = "test_dir";
 const char *TEST_FILE = "test_file";
@@ -67,10 +60,10 @@ static struct tcase {
 	int count;
 	int exp_error;
 } tcases[] = {
-	{&fd[0], invalid_iovec, 1, EINVAL},
-	{&fd[0], efault_iovec, 3, EFAULT},
-	{&fd[0], large_iovec, -1, EINVAL},
-	{&fd[1], valid_iovec, 1, EISDIR},
+	{&fd_file, invalid_iovec, 1, EINVAL},
+	{&fd_file, efault_iovec, 3, EFAULT},
+	{&fd_file, large_iovec, -1, EINVAL},
+	{&fd_dir, valid_iovec, 1, EISDIR},
 	{&badfd, valid_iovec, 3, EBADF},
 };
 
@@ -84,26 +77,23 @@ static void verify_readv(unsigned int n)
 
 static void setup(void)
 {
-	fd[0] = SAFE_OPEN(TEST_FILE, O_WRONLY | O_CREAT, 0666);
-	SAFE_WRITE(1, fd[0], buf1, CHUNK);
-	SAFE_CLOSE(fd[0]);
+	SAFE_FILE_PRINTF(TEST_FILE, "test");
 
-	fd[0] = SAFE_OPEN(TEST_FILE, O_RDONLY, 0666);
+	fd_file = SAFE_OPEN(TEST_FILE, O_RDONLY);
 
 	efault_iovec[0].iov_base = tst_get_bad_addr(NULL);
 
 	SAFE_MKDIR(TEST_DIR, MODES);
-	fd[1] = SAFE_OPEN(TEST_DIR, O_RDONLY);
+	fd_dir = SAFE_OPEN(TEST_DIR, O_RDONLY);
 }
 
 static void cleanup(void)
 {
-	int i;
+	if (fd_file > 0)
+		SAFE_CLOSE(fd_file);
 
-	for (i = 0; i < 2; i++) {
-		if (fd[i] > 0)
-			SAFE_CLOSE(fd[i]);
-	}
+	if (fd_dir > 0)
+		SAFE_CLOSE(fd_dir);
 }
 
 static struct tst_test test = {

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-31 15:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-30  5:48 [LTP] [PATCH] syscalls/readv02: Convert to new API and merge readv03 into readv02 Dai Shili
2021-08-03 13:43 ` Cyril Hrubis
2021-08-04  9:37   ` [LTP] 回复: " daisl.fnst
2021-08-15 11:02   ` [LTP] [PATCH v2] " Dai Shili
2021-08-31 15:55     ` Cyril Hrubis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.