1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: run various rename 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
16 /* test using a bad address for either old or new path */
test_rename_badaddr(struct io_uring * ring,bool bad_old)17 static int test_rename_badaddr(struct io_uring *ring, bool bad_old)
18 {
19 struct io_uring_cqe *cqe;
20 struct io_uring_sqe *sqe;
21 const char *path = ".foo.bar";
22 const char *old, *new;
23 int ret;
24
25 if (bad_old) {
26 old = (void *) (uintptr_t) 0x1234;
27 new = path;
28 } else {
29 old = path;
30 new = (void *) (uintptr_t) 0x1234;
31 }
32
33 sqe = io_uring_get_sqe(ring);
34 if (!sqe) {
35 fprintf(stderr, "get sqe failed\n");
36 goto err;
37 }
38
39 memset(sqe, 0, sizeof(*sqe));
40
41 io_uring_prep_rename(sqe, old, new);
42
43 ret = io_uring_submit(ring);
44 if (ret <= 0) {
45 fprintf(stderr, "sqe submit failed: %d\n", ret);
46 goto err;
47 }
48
49 ret = io_uring_wait_cqe(ring, &cqe);
50 if (ret < 0) {
51 fprintf(stderr, "wait completion %d\n", ret);
52 goto err;
53 }
54 ret = cqe->res;
55 io_uring_cqe_seen(ring, cqe);
56 return ret;
57 err:
58 return 1;
59 }
60
test_rename(struct io_uring * ring,const char * old,const char * new)61 static int test_rename(struct io_uring *ring, const char *old, const char *new)
62 {
63 struct io_uring_cqe *cqe;
64 struct io_uring_sqe *sqe;
65 int ret;
66
67 sqe = io_uring_get_sqe(ring);
68 if (!sqe) {
69 fprintf(stderr, "get sqe failed\n");
70 goto err;
71 }
72
73 memset(sqe, 0, sizeof(*sqe));
74
75 io_uring_prep_rename(sqe, old, new);
76
77 ret = io_uring_submit(ring);
78 if (ret <= 0) {
79 fprintf(stderr, "sqe submit failed: %d\n", ret);
80 goto err;
81 }
82
83 ret = io_uring_wait_cqe(ring, &cqe);
84 if (ret < 0) {
85 fprintf(stderr, "wait completion %d\n", ret);
86 goto err;
87 }
88 ret = cqe->res;
89 io_uring_cqe_seen(ring, cqe);
90 return ret;
91 err:
92 return 1;
93 }
94
stat_file(const char * buf)95 static int stat_file(const char *buf)
96 {
97 struct stat sb;
98
99 if (!stat(buf, &sb))
100 return 0;
101
102 return errno;
103 }
104
main(int argc,char * argv[])105 int main(int argc, char *argv[])
106 {
107 struct io_uring ring;
108 char src[32] = "./XXXXXX";
109 char dst[32] = "./XXXXXX";
110 int ret;
111
112 if (argc > 1)
113 return 0;
114
115 ret = io_uring_queue_init(1, &ring, 0);
116 if (ret) {
117 fprintf(stderr, "ring setup failed: %d\n", ret);
118 return 1;
119 }
120
121 ret = mkstemp(src);
122 if (ret < 0) {
123 perror("mkstemp");
124 return 1;
125 }
126 close(ret);
127
128 ret = mkstemp(dst);
129 if (ret < 0) {
130 perror("mkstemp");
131 return 1;
132 }
133 close(ret);
134
135 if (stat_file(src) != 0) {
136 perror("stat");
137 return 1;
138 }
139 if (stat_file(dst) != 0) {
140 perror("stat");
141 return 1;
142 }
143
144 ret = test_rename(&ring, src, dst);
145 if (ret < 0) {
146 if (ret == -EBADF || ret == -EINVAL) {
147 fprintf(stdout, "Rename not supported, skipping\n");
148 goto out;
149 }
150 fprintf(stderr, "rename: %s\n", strerror(-ret));
151 goto err;
152 } else if (ret)
153 goto err;
154
155 if (stat_file(src) != ENOENT) {
156 fprintf(stderr, "stat got %s\n", strerror(ret));
157 return 1;
158 }
159
160 if (stat_file(dst) != 0) {
161 perror("stat");
162 return 1;
163 }
164
165 ret = test_rename(&ring, "/x/y/1/2", "/2/1/y/x");
166 if (ret != -ENOENT) {
167 fprintf(stderr, "test_rename invalid failed: %d\n", ret);
168 return ret;
169 }
170
171 ret = test_rename_badaddr(&ring, 0);
172 if (ret != -EFAULT) {
173 fprintf(stderr, "test_badaddr 0 failed: %d\n", ret);
174 return ret;
175 }
176
177 ret = test_rename_badaddr(&ring, 1);
178 if (ret != -EFAULT) {
179 fprintf(stderr, "test_badaddr 1 failed: %d\n", ret);
180 return ret;
181 }
182
183 out:
184 unlink(dst);
185 return 0;
186 err:
187 unlink(src);
188 unlink(dst);
189 return 1;
190 }
191