xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/read/read02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) International Business Machines Corp., 2001
4*49cdfc7eSAndroid Build Coastguard Worker  * Ported to LTP: Wayne Boyer
5*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2017 Fujitsu Ltd.
6*49cdfc7eSAndroid Build Coastguard Worker  *	04/2017 Modified by Jinhui Huang
7*49cdfc7eSAndroid Build Coastguard Worker  */
8*49cdfc7eSAndroid Build Coastguard Worker /*
9*49cdfc7eSAndroid Build Coastguard Worker  * DESCRIPTION
10*49cdfc7eSAndroid Build Coastguard Worker  *	test 1:
11*49cdfc7eSAndroid Build Coastguard Worker  *	Read with an invalid file descriptor, and expect an EBADF.
12*49cdfc7eSAndroid Build Coastguard Worker  *
13*49cdfc7eSAndroid Build Coastguard Worker  *	test 2:
14*49cdfc7eSAndroid Build Coastguard Worker  *	The parameter passed to read is a directory, check if the errno is
15*49cdfc7eSAndroid Build Coastguard Worker  *	set to EISDIR.
16*49cdfc7eSAndroid Build Coastguard Worker  *
17*49cdfc7eSAndroid Build Coastguard Worker  *	test 3:
18*49cdfc7eSAndroid Build Coastguard Worker  *	Buf is outside the accessible address space, expect an EFAULT.
19*49cdfc7eSAndroid Build Coastguard Worker  *
20*49cdfc7eSAndroid Build Coastguard Worker  *	test 4:
21*49cdfc7eSAndroid Build Coastguard Worker  *	The file was opened with the O_DIRECT flag, and transfer sizes was not
22*49cdfc7eSAndroid Build Coastguard Worker  *	multiples of the logical block size of the file system, expect an
23*49cdfc7eSAndroid Build Coastguard Worker  *	EINVAL.
24*49cdfc7eSAndroid Build Coastguard Worker  *
25*49cdfc7eSAndroid Build Coastguard Worker  *	test 5:
26*49cdfc7eSAndroid Build Coastguard Worker  *	The file was opened with the O_DIRECT flag, and the alignment of the
27*49cdfc7eSAndroid Build Coastguard Worker  *	user buffer was not multiples of the logical block size of the file
28*49cdfc7eSAndroid Build Coastguard Worker  *	system, expect an EINVAL.
29*49cdfc7eSAndroid Build Coastguard Worker  */
30*49cdfc7eSAndroid Build Coastguard Worker 
31*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
34*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
35*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
36*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker static int badfd = -1;
39*49cdfc7eSAndroid Build Coastguard Worker static int fd2, fd3, fd4 = -1;
40*49cdfc7eSAndroid Build Coastguard Worker static char buf[BUFSIZ];
41*49cdfc7eSAndroid Build Coastguard Worker static void *bufaddr = buf;
42*49cdfc7eSAndroid Build Coastguard Worker static void *outside_buf = (void *)-1;
43*49cdfc7eSAndroid Build Coastguard Worker static void *addr4;
44*49cdfc7eSAndroid Build Coastguard Worker static void *addr5;
45*49cdfc7eSAndroid Build Coastguard Worker static long fs_type;
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
48*49cdfc7eSAndroid Build Coastguard Worker 	int *fd;
49*49cdfc7eSAndroid Build Coastguard Worker 	void **buf;
50*49cdfc7eSAndroid Build Coastguard Worker 	size_t count;
51*49cdfc7eSAndroid Build Coastguard Worker 	int exp_error;
52*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
53*49cdfc7eSAndroid Build Coastguard Worker 	{&badfd, &bufaddr, 1, EBADF},
54*49cdfc7eSAndroid Build Coastguard Worker 	{&fd2, &bufaddr, 1, EISDIR},
55*49cdfc7eSAndroid Build Coastguard Worker 	{&fd3, &outside_buf, 1, EFAULT},
56*49cdfc7eSAndroid Build Coastguard Worker 	{&fd4, &addr4, 1, EINVAL},
57*49cdfc7eSAndroid Build Coastguard Worker 	{&fd4, &addr5, 4096, EINVAL},
58*49cdfc7eSAndroid Build Coastguard Worker };
59*49cdfc7eSAndroid Build Coastguard Worker 
verify_read(unsigned int n)60*49cdfc7eSAndroid Build Coastguard Worker static void verify_read(unsigned int n)
61*49cdfc7eSAndroid Build Coastguard Worker {
62*49cdfc7eSAndroid Build Coastguard Worker 	struct tcase *tc = &tcases[n];
63*49cdfc7eSAndroid Build Coastguard Worker 
64*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->fd == &fd4 && *tc->fd == -1) {
65*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF, "O_DIRECT not supported on %s filesystem",
66*49cdfc7eSAndroid Build Coastguard Worker 			tst_fs_type_name(fs_type));
67*49cdfc7eSAndroid Build Coastguard Worker 		return;
68*49cdfc7eSAndroid Build Coastguard Worker 	}
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 	TEST(read(*tc->fd, *tc->buf, tc->count));
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	if (*tc->fd == fd4 && TST_RET >= 0) {
73*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS,
74*49cdfc7eSAndroid Build Coastguard Worker 			"O_DIRECT unaligned reads fallbacks to buffered I/O");
75*49cdfc7eSAndroid Build Coastguard Worker 		return;
76*49cdfc7eSAndroid Build Coastguard Worker 	}
77*49cdfc7eSAndroid Build Coastguard Worker 
78*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != -1) {
79*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "read() succeeded unexpectedly");
80*49cdfc7eSAndroid Build Coastguard Worker 		return;
81*49cdfc7eSAndroid Build Coastguard Worker 	}
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_ERR == tc->exp_error) {
84*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS | TTERRNO, "read() failed as expected");
85*49cdfc7eSAndroid Build Coastguard Worker 	} else {
86*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO, "read() failed unexpectedly, "
87*49cdfc7eSAndroid Build Coastguard Worker 			"expected %s", tst_strerrno(tc->exp_error));
88*49cdfc7eSAndroid Build Coastguard Worker 	}
89*49cdfc7eSAndroid Build Coastguard Worker }
90*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)91*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
92*49cdfc7eSAndroid Build Coastguard Worker {
93*49cdfc7eSAndroid Build Coastguard Worker 	fd2 = SAFE_OPEN(".", O_DIRECTORY);
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_PRINTF("test_file", "A");
96*49cdfc7eSAndroid Build Coastguard Worker 
97*49cdfc7eSAndroid Build Coastguard Worker 	fd3 = SAFE_OPEN("test_file", O_RDWR);
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker 	outside_buf = SAFE_MMAP(0, 1, PROT_NONE,
100*49cdfc7eSAndroid Build Coastguard Worker 				MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	addr4 = SAFE_MEMALIGN(getpagesize(), (4096 * 10));
103*49cdfc7eSAndroid Build Coastguard Worker 	addr5 = addr4 + 1;
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	fs_type = tst_fs_type(".");
106*49cdfc7eSAndroid Build Coastguard Worker 	if (fs_type != TST_TMPFS_MAGIC)
107*49cdfc7eSAndroid Build Coastguard Worker 		fd4 = SAFE_OPEN("test_file", O_RDWR | O_DIRECT);
108*49cdfc7eSAndroid Build Coastguard Worker }
109*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)110*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
111*49cdfc7eSAndroid Build Coastguard Worker {
112*49cdfc7eSAndroid Build Coastguard Worker 	free(addr4);
113*49cdfc7eSAndroid Build Coastguard Worker 
114*49cdfc7eSAndroid Build Coastguard Worker 	if (fd4 > 0)
115*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd4);
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	if (fd3 > 0)
118*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd3);
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	if (fd2 > 0)
121*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd2);
122*49cdfc7eSAndroid Build Coastguard Worker }
123*49cdfc7eSAndroid Build Coastguard Worker 
124*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
125*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(tcases),
126*49cdfc7eSAndroid Build Coastguard Worker 	.test = verify_read,
127*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
128*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
129*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
130*49cdfc7eSAndroid Build Coastguard Worker };
131