xref: /aosp_15_r20/external/liburing/test/statx.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: run various statx(2) tests
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/syscall.h>
14 #include <sys/stat.h>
15 
16 #include "helpers.h"
17 #include "liburing.h"
18 
19 #ifdef __NR_statx
do_statx(int dfd,const char * path,int flags,unsigned mask,struct statx * statxbuf)20 static int do_statx(int dfd, const char *path, int flags, unsigned mask,
21 		    struct statx *statxbuf)
22 {
23 	return syscall(__NR_statx, dfd, path, flags, mask, statxbuf);
24 }
25 #else
do_statx(int dfd,const char * path,int flags,unsigned mask,struct statx * statxbuf)26 static int do_statx(int dfd, const char *path, int flags, unsigned mask,
27 		    struct statx *statxbuf)
28 {
29 	errno = ENOSYS;
30 	return -1;
31 }
32 #endif
33 
statx_syscall_supported(void)34 static int statx_syscall_supported(void)
35 {
36 	return errno == ENOSYS ? 0 : -1;
37 }
38 
test_statx(struct io_uring * ring,const char * path)39 static int test_statx(struct io_uring *ring, const char *path)
40 {
41 	struct io_uring_cqe *cqe;
42 	struct io_uring_sqe *sqe;
43 	struct statx x1, x2;
44 	int ret;
45 
46 	sqe = io_uring_get_sqe(ring);
47 	if (!sqe) {
48 		fprintf(stderr, "get sqe failed\n");
49 		goto err;
50 	}
51 	io_uring_prep_statx(sqe, -1, path, 0, STATX_ALL, &x1);
52 
53 	ret = io_uring_submit(ring);
54 	if (ret <= 0) {
55 		fprintf(stderr, "sqe submit failed: %d\n", ret);
56 		goto err;
57 	}
58 
59 	ret = io_uring_wait_cqe(ring, &cqe);
60 	if (ret < 0) {
61 		fprintf(stderr, "wait completion %d\n", ret);
62 		goto err;
63 	}
64 	ret = cqe->res;
65 	io_uring_cqe_seen(ring, cqe);
66 	if (ret)
67 		return ret;
68 	ret = do_statx(-1, path, 0, STATX_ALL, &x2);
69 	if (ret < 0)
70 		return statx_syscall_supported();
71 	if (memcmp(&x1, &x2, sizeof(x1))) {
72 		fprintf(stderr, "Miscompare between io_uring and statx\n");
73 		goto err;
74 	}
75 	return 0;
76 err:
77 	return -1;
78 }
79 
test_statx_fd(struct io_uring * ring,const char * path)80 static int test_statx_fd(struct io_uring *ring, const char *path)
81 {
82 	struct io_uring_cqe *cqe;
83 	struct io_uring_sqe *sqe;
84 	struct statx x1, x2;
85 	int ret, fd;
86 
87 	fd = open(path, O_RDONLY);
88 	if (fd < 0) {
89 		perror("open");
90 		return 1;
91 	}
92 
93 	memset(&x1, 0, sizeof(x1));
94 
95 	sqe = io_uring_get_sqe(ring);
96 	if (!sqe) {
97 		fprintf(stderr, "get sqe failed\n");
98 		goto err;
99 	}
100 	io_uring_prep_statx(sqe, fd, "", AT_EMPTY_PATH, STATX_ALL, &x1);
101 
102 	ret = io_uring_submit(ring);
103 	if (ret <= 0) {
104 		fprintf(stderr, "sqe submit failed: %d\n", ret);
105 		goto err;
106 	}
107 
108 	ret = io_uring_wait_cqe(ring, &cqe);
109 	if (ret < 0) {
110 		fprintf(stderr, "wait completion %d\n", ret);
111 		goto err;
112 	}
113 	ret = cqe->res;
114 	io_uring_cqe_seen(ring, cqe);
115 	if (ret)
116 		return ret;
117 	memset(&x2, 0, sizeof(x2));
118 	ret = do_statx(fd, "", AT_EMPTY_PATH, STATX_ALL, &x2);
119 	if (ret < 0)
120 		return statx_syscall_supported();
121 	if (memcmp(&x1, &x2, sizeof(x1))) {
122 		fprintf(stderr, "Miscompare between io_uring and statx\n");
123 		goto err;
124 	}
125 	return 0;
126 err:
127 	return -1;
128 }
129 
main(int argc,char * argv[])130 int main(int argc, char *argv[])
131 {
132 	struct io_uring ring;
133 	const char *fname;
134 	int ret;
135 
136 	ret = io_uring_queue_init(8, &ring, 0);
137 	if (ret) {
138 		fprintf(stderr, "ring setup failed\n");
139 		return 1;
140 	}
141 
142 	if (argc > 1) {
143 		fname = argv[1];
144 	} else {
145 		fname = "/tmp/.statx";
146 		t_create_file(fname, 4096);
147 	}
148 
149 	ret = test_statx(&ring, fname);
150 	if (ret) {
151 		if (ret == -EINVAL) {
152 			fprintf(stdout, "statx not supported, skipping\n");
153 			goto done;
154 		}
155 		fprintf(stderr, "test_statx failed: %d\n", ret);
156 		goto err;
157 	}
158 
159 	ret = test_statx_fd(&ring, fname);
160 	if (ret) {
161 		fprintf(stderr, "test_statx_fd failed: %d\n", ret);
162 		goto err;
163 	}
164 done:
165 	if (fname != argv[1])
166 		unlink(fname);
167 	return 0;
168 err:
169 	if (fname != argv[1])
170 		unlink(fname);
171 	return 1;
172 }
173