xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/preadv/preadv01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2015 Fujitsu Ltd.
4  * Author: Xiao Yang <[email protected]>
5  * Copyright (c) Linux Test Project, 2016-2023
6  */
7 
8 /*\
9  * [Description]
10  *
11  * Testcase to check the basic functionality of the preadv(2).
12  *
13  * Preadv(2) should succeed to read the expected content of data
14  * and after reading the file, the file offset is not changed.
15  */
16 
17 #define _GNU_SOURCE
18 
19 #include <string.h>
20 #include <sys/uio.h>
21 
22 #include "tst_test.h"
23 #include "preadv.h"
24 
25 #define CHUNK           64
26 
27 static int fd;
28 
29 static struct iovec *rd_iovec;
30 
31 static struct tcase {
32 	int count;
33 	off_t offset;
34 	ssize_t size;
35 	char content;
36 } tcases[] = {
37 	{1, 0, CHUNK, 'a'},
38 	{2, 0, CHUNK, 'a'},
39 	{1, CHUNK*3/2, CHUNK/2, 'b'}
40 };
41 
verify_preadv(unsigned int n)42 static void verify_preadv(unsigned int n)
43 {
44 	int i;
45 	char *vec;
46 	struct tcase *tc = &tcases[n];
47 
48 	vec = rd_iovec[0].iov_base;
49 	memset(vec, 0x00, CHUNK);
50 
51 	SAFE_LSEEK(fd, 0, SEEK_SET);
52 
53 	TEST(preadv(fd, rd_iovec, tc->count, tc->offset));
54 	if (TST_RET < 0) {
55 		tst_res(TFAIL | TTERRNO, "Preadv(2) failed");
56 		return;
57 	}
58 
59 	if (TST_RET != tc->size) {
60 		tst_res(TFAIL, "Preadv(2) read %li bytes, expected %zi",
61 			 TST_RET, tc->size);
62 		return;
63 	}
64 
65 	for (i = 0; i < tc->size; i++) {
66 		if (vec[i] != tc->content)
67 			break;
68 	}
69 
70 	if (i < tc->size) {
71 		tst_res(TFAIL, "Buffer wrong at %i have %02x expected %02x",
72 			 i, vec[i], tc->content);
73 		return;
74 	}
75 
76 	if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) {
77 		tst_res(TFAIL, "Preadv(2) has changed file offset");
78 		return;
79 	}
80 
81 	tst_res(TPASS, "Preadv(2) read %zi bytes successfully "
82 		 "with content '%c' expectedly", tc->size, tc->content);
83 }
84 
setup(void)85 static void setup(void)
86 {
87 	char buf[CHUNK];
88 
89 	fd = SAFE_OPEN("file", O_RDWR | O_CREAT, 0644);
90 
91 	memset(buf, 'a', sizeof(buf));
92 	SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, sizeof(buf));
93 
94 	memset(buf, 'b', sizeof(buf));
95 	SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, sizeof(buf));
96 }
97 
cleanup(void)98 static void cleanup(void)
99 {
100 	if (fd > 0)
101 		SAFE_CLOSE(fd);
102 }
103 
104 static struct tst_test test = {
105 	.tcnt = ARRAY_SIZE(tcases),
106 	.setup = setup,
107 	.cleanup = cleanup,
108 	.test = verify_preadv,
109 	.needs_tmpdir = 1,
110 	.bufs = (struct tst_buffers []) {
111 		{&rd_iovec, .iov_sizes = (int[]){CHUNK, 0, -1}},
112 		{},
113 	}
114 };
115