• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: run various unlink 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/stat.h>
13 
14 #include "liburing.h"
15 
test_rmdir(struct io_uring * ring)16 static int test_rmdir(struct io_uring *ring)
17 {
18 	struct io_uring_cqe *cqe;
19 	struct io_uring_sqe *sqe;
20 	char buf[32];
21 	int ret;
22 
23 	sprintf(buf, ".tmp.dir.%d", getpid());
24 	if (mkdir(buf, 0755) < 0) {
25 		perror("mkdir");
26 		return 1;
27 	}
28 
29 	sqe = io_uring_get_sqe(ring);
30 	if (!sqe) {
31 		fprintf(stderr, "get sqe failed\n");
32 		goto err;
33 	}
34 	io_uring_prep_unlink(sqe, buf, AT_REMOVEDIR);
35 
36 	ret = io_uring_submit(ring);
37 	if (ret <= 0) {
38 		fprintf(stderr, "sqe submit failed: %d\n", ret);
39 		goto err;
40 	}
41 
42 	ret = io_uring_wait_cqe(ring, &cqe);
43 	if (ret < 0) {
44 		fprintf(stderr, "wait completion %d\n", ret);
45 		goto err;
46 	}
47 	ret = cqe->res;
48 	io_uring_cqe_seen(ring, cqe);
49 
50 	if (!ret) {
51 		struct stat sb;
52 
53 		if (!stat(buf, &sb)) {
54 			fprintf(stderr, "dir unlinked but still there\n");
55 			goto err;
56 		}
57 	}
58 	unlink(buf);
59 	return ret;
60 err:
61 	unlink(buf);
62 	return 1;
63 }
64 
test_unlink_badaddr(struct io_uring * ring)65 static int test_unlink_badaddr(struct io_uring *ring)
66 {
67 	const char *old = (const char *) (uintptr_t) 0x1234;
68 	struct io_uring_cqe *cqe;
69 	struct io_uring_sqe *sqe;
70 	int ret;
71 
72 	sqe = io_uring_get_sqe(ring);
73 	if (!sqe) {
74 		fprintf(stderr, "get sqe failed\n");
75 		goto err;
76 	}
77 	io_uring_prep_unlink(sqe, old, 0);
78 
79 	ret = io_uring_submit(ring);
80 	if (ret <= 0) {
81 		fprintf(stderr, "sqe submit failed: %d\n", ret);
82 		goto err;
83 	}
84 
85 	ret = io_uring_wait_cqe(ring, &cqe);
86 	if (ret < 0) {
87 		fprintf(stderr, "wait completion %d\n", ret);
88 		goto err;
89 	}
90 	ret = cqe->res;
91 	io_uring_cqe_seen(ring, cqe);
92 	return ret;
93 err:
94 	return 1;
95 }
96 
test_unlink(struct io_uring * ring,const char * old)97 static int test_unlink(struct io_uring *ring, const char *old)
98 {
99 	struct io_uring_cqe *cqe;
100 	struct io_uring_sqe *sqe;
101 	int ret;
102 
103 	sqe = io_uring_get_sqe(ring);
104 	if (!sqe) {
105 		fprintf(stderr, "get sqe failed\n");
106 		goto err;
107 	}
108 	io_uring_prep_unlink(sqe, old, 0);
109 
110 	ret = io_uring_submit(ring);
111 	if (ret <= 0) {
112 		fprintf(stderr, "sqe submit failed: %d\n", ret);
113 		goto err;
114 	}
115 
116 	ret = io_uring_wait_cqe(ring, &cqe);
117 	if (ret < 0) {
118 		fprintf(stderr, "wait completion %d\n", ret);
119 		goto err;
120 	}
121 	ret = cqe->res;
122 	io_uring_cqe_seen(ring, cqe);
123 	return ret;
124 err:
125 	return 1;
126 }
127 
stat_file(const char * buf)128 static int stat_file(const char *buf)
129 {
130 	struct stat sb;
131 
132 	if (!stat(buf, &sb))
133 		return 0;
134 
135 	return errno;
136 }
137 
main(int argc,char * argv[])138 int main(int argc, char *argv[])
139 {
140 	struct io_uring ring;
141 	char buf[32] = "./XXXXXX";
142 	int ret;
143 
144 	if (argc > 1)
145 		return 0;
146 
147 	ret = io_uring_queue_init(1, &ring, 0);
148 	if (ret) {
149 		fprintf(stderr, "ring setup failed: %d\n", ret);
150 		return 1;
151 	}
152 
153 	ret = mkstemp(buf);
154 	if (ret < 0) {
155 		perror("mkstemp");
156 		return 1;
157 	}
158 	close(ret);
159 
160 	if (stat_file(buf) != 0) {
161 		perror("stat");
162 		return 1;
163 	}
164 
165 	ret = test_unlink(&ring, buf);
166 	if (ret < 0) {
167 		if (ret == -EBADF || ret == -EINVAL) {
168 			fprintf(stdout, "Unlink not supported, skipping\n");
169 			unlink(buf);
170 			return 0;
171 		}
172 		fprintf(stderr, "rename: %s\n", strerror(-ret));
173 		goto err;
174 	} else if (ret)
175 		goto err;
176 
177 	ret = stat_file(buf);
178 	if (ret != ENOENT) {
179 		fprintf(stderr, "stat got %s\n", strerror(ret));
180 		return 1;
181 	}
182 
183 	ret = test_unlink(&ring, "/3/2/3/1/z/y");
184 	if (ret != -ENOENT) {
185 		fprintf(stderr, "invalid unlink got %s\n", strerror(-ret));
186 		return 1;
187 	}
188 
189 	ret = test_unlink_badaddr(&ring);
190 	if (ret != -EFAULT) {
191 		fprintf(stderr, "badaddr unlink got %s\n", strerror(-ret));
192 		return 1;
193 	}
194 
195 	ret = test_rmdir(&ring);
196 	if (ret) {
197 		fprintf(stderr, "rmdir failed: %s\n", strerror(-ret));
198 		return 1;
199 	}
200 
201 	return 0;
202 err:
203 	unlink(buf);
204 	return 1;
205 }
206