xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/preadv/preadv02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2015-2016 Fujitsu Ltd.
4  * Author: Xiao Yang <[email protected]>
5  * Copyright (c) Linux Test Project, 2017-2023
6  */
7 
8 /*\
9  * [Description]
10  *
11  * - EINVAL when iov_len is invalid.
12  * - EINVAL when the vector count iovcnt is less than zero.
13  * - EINVAL when offset is negative.
14  * - EFAULT when attempts to read into a invalid address.
15  * - EBADF when file descriptor is invalid.
16  * - EBADF when file descriptor is not open for reading.
17  * - EISDIR when fd refers to a directory.
18  * - ESPIPE when fd is associated with a pipe.
19  */
20 
21 #define _GNU_SOURCE
22 
23 #include <sys/uio.h>
24 #include <unistd.h>
25 #include "tst_test.h"
26 #include "preadv.h"
27 
28 #define CHUNK           64
29 
30 static int fd1;
31 static int fd2;
32 static int fd3 = -1;
33 static int fd4;
34 static int fd5[2];
35 
36 static char buf[CHUNK];
37 
38 static struct iovec rd_iovec1[] = {
39 	{buf, -1},
40 };
41 
42 static struct iovec rd_iovec2[] = {
43 	{buf, CHUNK},
44 };
45 
46 static struct iovec rd_iovec3[] = {
47 	{(char *)-1, CHUNK},
48 };
49 
50 static struct tcase {
51 	int *fd;
52 	struct iovec *name;
53 	int count;
54 	off_t offset;
55 	int exp_err;
56 } tcases[] = {
57 	{&fd1, rd_iovec1, 1, 0, EINVAL},
58 	{&fd1, rd_iovec2, -1, 0, EINVAL},
59 	{&fd1, rd_iovec2, 1, -1, EINVAL},
60 	{&fd1, rd_iovec3, 1, 0, EFAULT},
61 	{&fd3, rd_iovec2, 1, 0, EBADF},
62 	{&fd2, rd_iovec2, 1, 0, EBADF},
63 	{&fd4, rd_iovec2, 1, 0, EISDIR},
64 	{&fd5[0], rd_iovec2, 1, 0, ESPIPE}
65 };
66 
verify_preadv(unsigned int n)67 static void verify_preadv(unsigned int n)
68 {
69 	struct tcase *tc = &tcases[n];
70 
71 	TEST(preadv(*tc->fd, tc->name, tc->count, tc->offset));
72 
73 	if (TST_RET == 0) {
74 		tst_res(TFAIL, "preadv() succeeded unexpectedly");
75 		return;
76 	}
77 
78 	if (TST_ERR == tc->exp_err) {
79 		tst_res(TPASS | TTERRNO, "preadv() failed as expected");
80 		return;
81 	}
82 
83 	tst_res(TFAIL | TTERRNO, "preadv() failed unexpectedly, expected %s",
84 		tst_strerrno(tc->exp_err));
85 }
86 
setup(void)87 static void setup(void)
88 {
89 	fd1 = SAFE_OPEN("file1", O_RDWR | O_CREAT, 0644);
90 	SAFE_FTRUNCATE(fd1, getpagesize());
91 	fd2 = SAFE_OPEN("file2", O_WRONLY | O_CREAT, 0644);
92 	fd4 = SAFE_OPEN(".", O_RDONLY);
93 	SAFE_PIPE(fd5);
94 }
95 
cleanup(void)96 static 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)
105 		SAFE_CLOSE(fd4);
106 
107 	if (fd5[0] > 0)
108 		SAFE_CLOSE(fd5[0]);
109 
110 	if (fd5[1] > 0)
111 		SAFE_CLOSE(fd5[1]);
112 }
113 
114 static struct tst_test test = {
115 	.tcnt = ARRAY_SIZE(tcases),
116 	.setup = setup,
117 	.cleanup = cleanup,
118 	.test = verify_preadv,
119 	.needs_tmpdir = 1,
120 };
121