141 lines
2.7 KiB
C
141 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) International Business Machines Corp., 2001
|
|
* Linux Test Project, 2016
|
|
*/
|
|
|
|
/*
|
|
* DESCRIPTION
|
|
* Testcase to check the basic functionality of writev(2) system call.
|
|
* Create IO vectors and attempt to writev various components of it.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <sys/uio.h>
|
|
#include "tst_test.h"
|
|
|
|
#define CHUNK 64
|
|
#define TESTFILE "writev_data_file"
|
|
|
|
static int valid_fd;
|
|
static int invalid_fd = -1;
|
|
static int pipe_fd[2];
|
|
|
|
static char buf[CHUNK * 4];
|
|
|
|
struct iovec iovec_badlen[] = {
|
|
{ buf, -1 },
|
|
{ buf + CHUNK, CHUNK },
|
|
{ buf + CHUNK * 2, CHUNK },
|
|
};
|
|
|
|
struct iovec iovec_simple[] = {
|
|
{ buf, CHUNK },
|
|
};
|
|
|
|
struct iovec iovec_zero_null[] = {
|
|
{ buf, CHUNK },
|
|
{ buf + CHUNK, 0 },
|
|
{ NULL, 0 },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
struct testcase_t {
|
|
const char *desc;
|
|
int *pfd;
|
|
struct iovec (*piovec)[];
|
|
int iovcnt;
|
|
int exp_ret;
|
|
int exp_errno;
|
|
} testcases[] = {
|
|
{
|
|
.desc = "invalid iov_len",
|
|
.pfd = &valid_fd,
|
|
.piovec = &iovec_badlen,
|
|
.iovcnt = ARRAY_SIZE(iovec_badlen),
|
|
.exp_ret = -1,
|
|
.exp_errno = EINVAL
|
|
},
|
|
{
|
|
.desc = "invalid fd",
|
|
.pfd = &invalid_fd,
|
|
.piovec = &iovec_simple,
|
|
.iovcnt = ARRAY_SIZE(iovec_simple),
|
|
.exp_ret = -1,
|
|
.exp_errno = EBADF
|
|
},
|
|
{
|
|
.desc = "invalid iovcnt",
|
|
.pfd = &valid_fd,
|
|
.piovec = &iovec_simple,
|
|
.iovcnt = -1,
|
|
.exp_ret = -1,
|
|
.exp_errno = EINVAL
|
|
},
|
|
{
|
|
.desc = "zero iovcnt",
|
|
.pfd = &valid_fd,
|
|
.piovec = &iovec_simple,
|
|
.iovcnt = 0,
|
|
.exp_ret = 0,
|
|
},
|
|
{
|
|
.desc = "NULL and zero length iovec",
|
|
.pfd = &valid_fd,
|
|
.piovec = &iovec_zero_null,
|
|
.iovcnt = ARRAY_SIZE(iovec_zero_null),
|
|
.exp_ret = CHUNK,
|
|
},
|
|
{
|
|
.desc = "write to closed pipe",
|
|
.pfd = &(pipe_fd[1]),
|
|
.piovec = &iovec_simple,
|
|
.iovcnt = ARRAY_SIZE(iovec_simple),
|
|
.exp_ret = -1,
|
|
.exp_errno = EPIPE,
|
|
},
|
|
};
|
|
|
|
void setup(void)
|
|
{
|
|
sigset_t block_mask;
|
|
|
|
sigemptyset(&block_mask);
|
|
sigaddset(&block_mask, SIGPIPE);
|
|
sigprocmask(SIG_BLOCK, &block_mask, NULL);
|
|
|
|
valid_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0644);
|
|
|
|
SAFE_PIPE(pipe_fd);
|
|
SAFE_CLOSE(pipe_fd[0]);
|
|
}
|
|
|
|
static void test_writev(unsigned int i)
|
|
{
|
|
struct testcase_t *tcase = &testcases[i];
|
|
int ret;
|
|
|
|
TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));
|
|
|
|
ret = (TST_RET == tcase->exp_ret);
|
|
if (TST_RET < 0 || tcase->exp_ret < 0) {
|
|
ret &= (TST_ERR == tcase->exp_errno);
|
|
tst_res((ret ? TPASS : TFAIL),
|
|
"%s, expected: %d (%s), got: %ld (%s)", tcase->desc,
|
|
tcase->exp_ret, tst_strerrno(tcase->exp_errno),
|
|
TST_RET, tst_strerrno(TST_ERR));
|
|
} else {
|
|
tst_res((ret ? TPASS : TFAIL),
|
|
"%s, expected: %d, got: %ld", tcase->desc,
|
|
tcase->exp_ret, TST_RET);
|
|
}
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.needs_tmpdir = 1,
|
|
.setup = setup,
|
|
.test = test_writev,
|
|
.tcnt = ARRAY_SIZE(testcases),
|
|
};
|