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