• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (c) International Business Machines Corp., 2001
4  *                 Linux Test Project, 2016
5  */
6 
7 /*
8  * DESCRIPTION
9  *	Testcase to check the basic functionality of writev(2) system call.
10  *	Create IO vectors and attempt to writev various components of it.
11  */
12 
13 #include <errno.h>
14 #include <signal.h>
15 #include <sys/uio.h>
16 #include "tst_test.h"
17 
18 #define	CHUNK		64
19 #define	TESTFILE	"writev_data_file"
20 
21 static int valid_fd;
22 static int invalid_fd = -1;
23 static int pipe_fd[2];
24 
25 static char buf[CHUNK * 4];
26 
27 struct iovec iovec_badlen[] = {
28 	{ buf, -1 },
29 	{ buf + CHUNK, CHUNK },
30 	{ buf + CHUNK * 2, CHUNK },
31 };
32 
33 struct iovec iovec_simple[] = {
34 	{ buf, CHUNK },
35 };
36 
37 struct iovec iovec_zero_null[] = {
38 	{ buf, CHUNK },
39 	{ buf + CHUNK, 0 },
40 	{ NULL, 0 },
41 	{ NULL, 0 }
42 };
43 
44 struct testcase_t {
45 	const char *desc;
46 	int *pfd;
47 	struct iovec (*piovec)[];
48 	int iovcnt;
49 	int exp_ret;
50 	int exp_errno;
51 } testcases[] = {
52 	{
53 		.desc = "invalid iov_len",
54 		.pfd = &valid_fd,
55 		.piovec = &iovec_badlen,
56 		.iovcnt = ARRAY_SIZE(iovec_badlen),
57 		.exp_ret = -1,
58 		.exp_errno = EINVAL
59 	},
60 	{
61 		.desc = "invalid fd",
62 		.pfd = &invalid_fd,
63 		.piovec = &iovec_simple,
64 		.iovcnt = ARRAY_SIZE(iovec_simple),
65 		.exp_ret = -1,
66 		.exp_errno = EBADF
67 	},
68 	{
69 		.desc = "invalid iovcnt",
70 		.pfd = &valid_fd,
71 		.piovec = &iovec_simple,
72 		.iovcnt = -1,
73 		.exp_ret = -1,
74 		.exp_errno = EINVAL
75 	},
76 	{
77 		.desc = "zero iovcnt",
78 		.pfd = &valid_fd,
79 		.piovec = &iovec_simple,
80 		.iovcnt = 0,
81 		.exp_ret = 0,
82 	},
83 	{
84 		.desc = "NULL and zero length iovec",
85 		.pfd = &valid_fd,
86 		.piovec = &iovec_zero_null,
87 		.iovcnt = ARRAY_SIZE(iovec_zero_null),
88 		.exp_ret = CHUNK,
89 	},
90 	{
91 		.desc = "write to closed pipe",
92 		.pfd = &(pipe_fd[1]),
93 		.piovec = &iovec_simple,
94 		.iovcnt = ARRAY_SIZE(iovec_simple),
95 		.exp_ret = -1,
96 		.exp_errno = EPIPE,
97 	},
98 };
99 
setup(void)100 void setup(void)
101 {
102 	sigset_t block_mask;
103 
104 	sigemptyset(&block_mask);
105 	sigaddset(&block_mask, SIGPIPE);
106 	sigprocmask(SIG_BLOCK, &block_mask, NULL);
107 
108 	valid_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0644);
109 
110 	SAFE_PIPE(pipe_fd);
111 	SAFE_CLOSE(pipe_fd[0]);
112 }
113 
test_writev(unsigned int i)114 static void test_writev(unsigned int i)
115 {
116 	struct testcase_t *tcase = &testcases[i];
117 	int ret;
118 
119 	TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));
120 
121 	ret = (TST_RET == tcase->exp_ret);
122 	if (TST_RET < 0 || tcase->exp_ret < 0) {
123 		ret &= (TST_ERR == tcase->exp_errno);
124 		tst_res((ret ? TPASS : TFAIL),
125 			"%s, expected: %d (%s), got: %ld (%s)", tcase->desc,
126 			tcase->exp_ret, tst_strerrno(tcase->exp_errno),
127 			TST_RET, tst_strerrno(TST_ERR));
128 	} else {
129 		tst_res((ret ? TPASS : TFAIL),
130 			"%s, expected: %d, got: %ld", tcase->desc,
131 			tcase->exp_ret, TST_RET);
132 	}
133 }
134 
135 static struct tst_test test = {
136 	.needs_tmpdir = 1,
137 	.setup = setup,
138 	.test = test_writev,
139 	.tcnt = ARRAY_SIZE(testcases),
140 };
141