1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: run various openat(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
13 #include "helpers.h"
14 #include "liburing.h"
15
test_close(struct io_uring * ring,int fd,int is_ring_fd)16 static int test_close(struct io_uring *ring, int fd, int is_ring_fd)
17 {
18 struct io_uring_cqe *cqe;
19 struct io_uring_sqe *sqe;
20 int ret;
21
22 sqe = io_uring_get_sqe(ring);
23 if (!sqe) {
24 fprintf(stderr, "get sqe failed\n");
25 goto err;
26 }
27 io_uring_prep_close(sqe, fd);
28
29 ret = io_uring_submit(ring);
30 if (ret <= 0) {
31 fprintf(stderr, "sqe submit failed: %d\n", ret);
32 goto err;
33 }
34
35 ret = io_uring_wait_cqe(ring, &cqe);
36 if (ret < 0) {
37 if (!(is_ring_fd && ret == -EBADF)) {
38 fprintf(stderr, "wait completion %d\n", ret);
39 goto err;
40 }
41 return ret;
42 }
43 ret = cqe->res;
44 io_uring_cqe_seen(ring, cqe);
45 return ret;
46 err:
47 return -1;
48 }
49
test_openat(struct io_uring * ring,const char * path,int dfd)50 static int test_openat(struct io_uring *ring, const char *path, int dfd)
51 {
52 struct io_uring_cqe *cqe;
53 struct io_uring_sqe *sqe;
54 int ret;
55
56 sqe = io_uring_get_sqe(ring);
57 if (!sqe) {
58 fprintf(stderr, "get sqe failed\n");
59 goto err;
60 }
61 io_uring_prep_openat(sqe, dfd, path, O_RDONLY, 0);
62
63 ret = io_uring_submit(ring);
64 if (ret <= 0) {
65 fprintf(stderr, "sqe submit failed: %d\n", ret);
66 goto err;
67 }
68
69 ret = io_uring_wait_cqe(ring, &cqe);
70 if (ret < 0) {
71 fprintf(stderr, "wait completion %d\n", ret);
72 goto err;
73 }
74 ret = cqe->res;
75 io_uring_cqe_seen(ring, cqe);
76 return ret;
77 err:
78 return -1;
79 }
80
main(int argc,char * argv[])81 int main(int argc, char *argv[])
82 {
83 struct io_uring ring;
84 const char *path, *path_rel;
85 int ret, do_unlink;
86
87 ret = io_uring_queue_init(8, &ring, 0);
88 if (ret) {
89 fprintf(stderr, "ring setup failed\n");
90 return 1;
91 }
92
93 if (argc > 1) {
94 path = "/tmp/.open.close";
95 path_rel = argv[1];
96 do_unlink = 0;
97 } else {
98 path = "/tmp/.open.close";
99 path_rel = ".open.close";
100 do_unlink = 1;
101 }
102
103 t_create_file(path, 4096);
104
105 if (do_unlink)
106 t_create_file(path_rel, 4096);
107
108 ret = test_openat(&ring, path, -1);
109 if (ret < 0) {
110 if (ret == -EINVAL) {
111 fprintf(stdout, "Open not supported, skipping\n");
112 goto done;
113 }
114 fprintf(stderr, "test_openat absolute failed: %d\n", ret);
115 goto err;
116 }
117
118 ret = test_openat(&ring, path_rel, AT_FDCWD);
119 if (ret < 0) {
120 fprintf(stderr, "test_openat relative failed: %d\n", ret);
121 goto err;
122 }
123
124 ret = test_close(&ring, ret, 0);
125 if (ret) {
126 fprintf(stderr, "test_close normal failed\n");
127 goto err;
128 }
129
130 ret = test_close(&ring, ring.ring_fd, 1);
131 if (ret != -EBADF) {
132 fprintf(stderr, "test_close ring_fd failed\n");
133 goto err;
134 }
135
136 done:
137 unlink(path);
138 if (do_unlink)
139 unlink(path_rel);
140 return 0;
141 err:
142 unlink(path);
143 if (do_unlink)
144 unlink(path_rel);
145 return 1;
146 }
147