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