1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved. 4 * Author: Jinhui Huang <huangjh.jy@cn.fujitsu.com> 5 */ 6/* 7 * Description: 8 * Check various errnos for pwritev2(2). 9 * 1) pwritev2() fails and sets errno to EINVAL if iov_len is invalid. 10 * 2) pwritev2() fails and sets errno to EINVAL if the vector count iovcnt is 11 * less than zero. 12 * 3) pwritev2() fails and sets errno to EOPNOTSUPP if flag is invalid. 13 * 4) pwritev2() fails and sets errno to EFAULT when writing data from invalid 14 * address. 15 * 5) pwritev2() fails and sets errno to EBADF if file descriptor is invalid. 16 * 6) pwritev2() fails and sets errno to EBADF if file descriptor is open for 17 * reading. 18 * 7) pwritev2() fails and sets errno to ESPIPE if fd is associated with a pipe. 19 */ 20 21#define _GNU_SOURCE 22#include <sys/uio.h> 23#include <unistd.h> 24 25#include "tst_test.h" 26#include "lapi/pwritev2.h" 27 28#define CHUNK 64 29 30static int fd1; 31static int fd2; 32static int fd3 = -1; 33static int fd4[2]; 34 35static char buf[CHUNK]; 36 37static struct iovec wr_iovec1[] = { 38 {buf, -1}, 39}; 40 41static struct iovec wr_iovec2[] = { 42 {buf, CHUNK}, 43}; 44 45static struct iovec wr_iovec3[] = { 46 {NULL, CHUNK}, 47}; 48 49static struct tcase { 50 int *fd; 51 struct iovec *name; 52 int count; 53 off_t offset; 54 int flag; 55 int exp_err; 56} tcases[] = { 57 {&fd1, wr_iovec1, 1, 0, 0, EINVAL}, 58 {&fd1, wr_iovec2, -1, 0, 0, EINVAL}, 59 {&fd1, wr_iovec2, 1, 1, -1, EOPNOTSUPP}, 60 {&fd1, wr_iovec3, 1, 0, 0, EFAULT}, 61 {&fd3, wr_iovec2, 1, 0, 0, EBADF}, 62 {&fd2, wr_iovec2, 1, 0, 0, EBADF}, 63 {&fd4[0], wr_iovec2, 1, 0, 0, ESPIPE}, 64}; 65 66static void verify_pwritev2(unsigned int n) 67{ 68 struct tcase *tc = &tcases[n]; 69 70 TEST(pwritev2(*tc->fd, tc->name, tc->count, tc->offset, tc->flag)); 71 72 if (TST_RET == 0) { 73 tst_res(TFAIL, "pwritev2() succeeded unexpectedly"); 74 return; 75 } 76 77 if (TST_ERR == tc->exp_err) { 78 tst_res(TPASS | TTERRNO, "pwritev2() failed as expected"); 79 return; 80 } 81 82 tst_res(TFAIL | TTERRNO, "pwritev2() failed unexpectedly, expected %s", 83 tst_strerrno(tc->exp_err)); 84} 85 86static void setup(void) 87{ 88 fd1 = SAFE_OPEN("file1", O_RDWR | O_CREAT, 0644); 89 SAFE_FTRUNCATE(fd1, getpagesize()); 90 fd2 = SAFE_OPEN("file2", O_RDONLY | O_CREAT, 0644); 91 SAFE_PIPE(fd4); 92 93 wr_iovec3[0].iov_base = tst_get_bad_addr(NULL); 94} 95 96static void cleanup(void) 97{ 98 if (fd1 > 0) 99 SAFE_CLOSE(fd1); 100 101 if (fd2 > 0) 102 SAFE_CLOSE(fd2); 103 104 if (fd4[0] > 0) 105 SAFE_CLOSE(fd4[0]); 106 107 if (fd4[1] > 0) 108 SAFE_CLOSE(fd4[1]); 109} 110 111static struct tst_test test = { 112 .tcnt = ARRAY_SIZE(tcases), 113 .setup = setup, 114 .cleanup = cleanup, 115 .test = verify_pwritev2, 116 .needs_tmpdir = 1, 117}; 118