Home | History | Annotate | Download | only in writev
      1 /*
      2  *   Copyright (c) International Business Machines  Corp., 2001
      3  *                 Linux Test Project, 2016
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;
     17  */
     18 
     19 /*
     20  * DESCRIPTION
     21  *	Testcase to check the basic functionality of writev(2) system call.
     22  *	Create IO vectors and attempt to writev various components of it.
     23  */
     24 
     25 #include <errno.h>
     26 #include <signal.h>
     27 #include <sys/uio.h>
     28 #include "tst_test.h"
     29 
     30 #define	CHUNK		64
     31 #define	TESTFILE	"writev_data_file"
     32 
     33 static int valid_fd;
     34 static int invalid_fd = -1;
     35 static int pipe_fd[2];
     36 
     37 static char buf[CHUNK * 4];
     38 
     39 struct iovec iovec_badlen[] = {
     40 	{ buf, -1 },
     41 	{ buf + CHUNK, CHUNK },
     42 	{ buf + CHUNK * 2, CHUNK },
     43 };
     44 
     45 struct iovec iovec_simple[] = {
     46 	{ buf, CHUNK },
     47 };
     48 
     49 struct iovec iovec_zero_null[] = {
     50 	{ buf, CHUNK },
     51 	{ buf + CHUNK, 0 },
     52 	{ NULL, 0 },
     53 	{ NULL, 0 }
     54 };
     55 
     56 struct testcase_t {
     57 	const char *desc;
     58 	int *pfd;
     59 	struct iovec (*piovec)[];
     60 	int iovcnt;
     61 	int exp_ret;
     62 	int exp_errno;
     63 } testcases[] = {
     64 	{
     65 		.desc = "invalid iov_len",
     66 		.pfd = &valid_fd,
     67 		.piovec = &iovec_badlen,
     68 		.iovcnt = ARRAY_SIZE(iovec_badlen),
     69 		.exp_ret = -1,
     70 		.exp_errno = EINVAL
     71 	},
     72 	{
     73 		.desc = "invalid fd",
     74 		.pfd = &invalid_fd,
     75 		.piovec = &iovec_simple,
     76 		.iovcnt = ARRAY_SIZE(iovec_simple),
     77 		.exp_ret = -1,
     78 		.exp_errno = EBADF
     79 	},
     80 	{
     81 		.desc = "invalid iovcnt",
     82 		.pfd = &valid_fd,
     83 		.piovec = &iovec_simple,
     84 		.iovcnt = -1,
     85 		.exp_ret = -1,
     86 		.exp_errno = EINVAL
     87 	},
     88 	{
     89 		.desc = "zero iovcnt",
     90 		.pfd = &valid_fd,
     91 		.piovec = &iovec_simple,
     92 		.iovcnt = 0,
     93 		.exp_ret = 0,
     94 	},
     95 	{
     96 		.desc = "NULL and zero length iovec",
     97 		.pfd = &valid_fd,
     98 		.piovec = &iovec_zero_null,
     99 		.iovcnt = ARRAY_SIZE(iovec_zero_null),
    100 		.exp_ret = CHUNK,
    101 	},
    102 	{
    103 		.desc = "write to closed pipe",
    104 		.pfd = &(pipe_fd[1]),
    105 		.piovec = &iovec_simple,
    106 		.iovcnt = ARRAY_SIZE(iovec_simple),
    107 		.exp_ret = -1,
    108 		.exp_errno = EPIPE,
    109 	},
    110 };
    111 
    112 void setup(void)
    113 {
    114 	sigset_t block_mask;
    115 
    116 	sigemptyset(&block_mask);
    117 	sigaddset(&block_mask, SIGPIPE);
    118 	sigprocmask(SIG_BLOCK, &block_mask, NULL);
    119 
    120 	valid_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0644);
    121 
    122 	SAFE_PIPE(pipe_fd);
    123 	SAFE_CLOSE(pipe_fd[0]);
    124 }
    125 
    126 static void test_writev(unsigned int i)
    127 {
    128 	struct testcase_t *tcase = &testcases[i];
    129 	int ret;
    130 
    131 	TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));
    132 
    133 	ret = (TST_RET == tcase->exp_ret);
    134 	if (TST_RET < 0 || tcase->exp_ret < 0) {
    135 		ret &= (TST_ERR == tcase->exp_errno);
    136 		tst_res((ret ? TPASS : TFAIL),
    137 			"%s, expected: %d (%s), got: %ld (%s)", tcase->desc,
    138 			tcase->exp_ret, tst_strerrno(tcase->exp_errno),
    139 			TST_RET, tst_strerrno(TST_ERR));
    140 	} else {
    141 		tst_res((ret ? TPASS : TFAIL),
    142 			"%s, expected: %d, got: %ld", tcase->desc,
    143 			tcase->exp_ret, TST_RET);
    144 	}
    145 }
    146 
    147 static struct tst_test test = {
    148 	.needs_tmpdir = 1,
    149 	.setup = setup,
    150 	.test = test_writev,
    151 	.tcnt = ARRAY_SIZE(testcases),
    152 };
    153