xref: /dragonfly/sys/vfs/fuse/fuse_util.c (revision 7485684f)
1 /*-
2  * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
3  * Copyright (c) 2019 The DragonFly Project
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include "fuse.h"
29 
30 void
31 fuse_hexdump(const char *p, size_t len)
32 {
33 	int i;
34 
35 	if (!fuse_debug)
36 		return;
37 
38 	for (i = 0; i < (int)len; i++) {
39 		kprintf("%02X ", p[i] & 0xff);
40 		if ((i + 1) % 32 == 0)
41 			kprintf("\n");
42 	}
43 	kprintf("\n");
44 }
45 
46 void
47 fuse_fill_in_header(struct fuse_in_header *ihd,
48     uint32_t len, uint32_t opcode, uint64_t unique, uint64_t nodeid,
49     uint32_t uid, uint32_t gid, uint32_t pid)
50 {
51 	ihd->len = len;
52 	ihd->opcode = opcode;
53 	ihd->unique = unique;
54 	ihd->nodeid = nodeid;
55 	ihd->uid = uid;
56 	ihd->gid = gid;
57 	ihd->pid = pid;
58 }
59 
60 int
61 fuse_forget_node(struct fuse_mount *fmp, uint64_t ino, uint64_t nlookup,
62     struct ucred *cred)
63 {
64 	struct fuse_ipc *fip;
65 	struct fuse_forget_in *ffi;
66 	int error;
67 
68 	KKASSERT(nlookup > 0);
69 
70 	fip = fuse_ipc_get(fmp, sizeof(*ffi));
71 	ffi = fuse_ipc_fill(fip, FUSE_FORGET, ino, cred);
72 	ffi->nlookup = nlookup;
73 
74 	error = fuse_ipc_tx_noreply(fip);
75 	if (error)
76 		return error;
77 	fuse_ipc_put(fip);
78 
79 	return 0;
80 }
81 
82 /*
83  * Ignore FUSE_COMPAT_XXX which seem to exist for backward compatibility
84  * for ancient versions of FUSE protocol.
85  */
86 int
87 fuse_audit_length(struct fuse_in_header *ihd, struct fuse_out_header *ohd)
88 {
89 	size_t len = ohd->len - sizeof(struct fuse_out_header);
90 	bool res;
91 
92 	switch (ihd->opcode) {
93 	case FUSE_LOOKUP:
94 		res = (len == sizeof(struct fuse_entry_out));
95 		break;
96 	case FUSE_FORGET:
97 		res = true;
98 		break;
99 	case FUSE_GETATTR:
100 		res = (len == sizeof(struct fuse_attr_out));
101 		break;
102 	case FUSE_SETATTR:
103 		res = (len == sizeof(struct fuse_attr_out));
104 		break;
105 	case FUSE_READLINK:
106 		res = (len <= PAGE_SIZE);
107 		break;
108 	case FUSE_SYMLINK:
109 		res = (len == sizeof(struct fuse_entry_out));
110 		break;
111 	case FUSE_MKNOD:
112 		res = (len == sizeof(struct fuse_entry_out));
113 		break;
114 	case FUSE_MKDIR:
115 		res = (len == sizeof(struct fuse_entry_out));
116 		break;
117 	case FUSE_UNLINK:
118 		res = (len == 0);
119 		break;
120 	case FUSE_RMDIR:
121 		res = (len == 0);
122 		break;
123 	case FUSE_RENAME:
124 		res = (len == 0);
125 		break;
126 	case FUSE_LINK:
127 		res = (len == sizeof(struct fuse_entry_out));
128 		break;
129 	case FUSE_OPEN:
130 		res = (len == sizeof(struct fuse_open_out));
131 		break;
132 	case FUSE_READ:
133 		res = (len <= ((struct fuse_read_in*)(ihd + 1))->size);
134 		break;
135 	case FUSE_WRITE:
136 		res = (len == sizeof(struct fuse_write_out));
137 		break;
138 	case FUSE_STATFS:
139 		res = (len == sizeof(struct fuse_statfs_out));
140 		break;
141 	case FUSE_RELEASE:
142 		res = (len == 0);
143 		break;
144 	case FUSE_FSYNC:
145 		res = (len == 0);
146 		break;
147 	case FUSE_SETXATTR:
148 		res = (len == 0);
149 		break;
150 	case FUSE_GETXATTR:
151 		res = true;
152 		break;
153 	case FUSE_LISTXATTR:
154 		res = true;
155 		break;
156 	case FUSE_REMOVEXATTR:
157 		res = (len == 0);
158 		break;
159 	case FUSE_FLUSH:
160 		res = (len == 0);
161 		break;
162 	case FUSE_INIT:
163 		res = (len == sizeof(struct fuse_init_out));
164 		break;
165 	case FUSE_OPENDIR:
166 		res = (len == sizeof(struct fuse_open_out));
167 		break;
168 	case FUSE_READDIR:
169 		res = (len <= ((struct fuse_read_in*)(ihd + 1))->size);
170 		break;
171 	case FUSE_RELEASEDIR:
172 		res = (len == 0);
173 		break;
174 	case FUSE_FSYNCDIR:
175 		res = (len == 0);
176 		break;
177 	case FUSE_GETLK:
178 		res = false;
179 		break;
180 	case FUSE_SETLK:
181 		res = false;
182 		break;
183 	case FUSE_SETLKW:
184 		res = false;
185 		break;
186 	case FUSE_ACCESS:
187 		res = (len == 0);
188 		break;
189 	case FUSE_CREATE:
190 		res = (len == sizeof(struct fuse_entry_out) +
191 		    sizeof(struct fuse_open_out));
192 		break;
193 	case FUSE_INTERRUPT:
194 		res = false;
195 		break;
196 	case FUSE_BMAP:
197 		res = false;
198 		break;
199 	case FUSE_DESTROY:
200 		res = (len == 0);
201 		break;
202 	case FUSE_IOCTL:
203 		res = false;
204 		break;
205 	case FUSE_POLL:
206 		res = false;
207 		break;
208 	case FUSE_NOTIFY_REPLY:
209 		res = false;
210 		break;
211 	case FUSE_BATCH_FORGET:
212 		res = false;
213 		break;
214 	case FUSE_FALLOCATE:
215 		res = false;
216 		break;
217 	case FUSE_READDIRPLUS:
218 		res = false;
219 		break;
220 	case FUSE_RENAME2:
221 		res = false;
222 		break;
223 	case FUSE_LSEEK:
224 		res = false;
225 		break;
226 	case FUSE_COPY_FILE_RANGE:
227 		res = false;
228 		break;
229 	default:
230 		fuse_panic("Invalid opcode %d", ihd->opcode);
231 		break;
232 	}
233 
234 	if (!res)
235 		return -1;
236 	return 0;
237 }
238 
239 const char*
240 fuse_get_ops(int op)
241 {
242 	switch (op) {
243 	case FUSE_LOOKUP:
244 		return "FUSE_LOOKUP";
245 	case FUSE_FORGET:
246 		return "FUSE_FORGET";
247 	case FUSE_GETATTR:
248 		return "FUSE_GETATTR";
249 	case FUSE_SETATTR:
250 		return "FUSE_SETATTR";
251 	case FUSE_READLINK:
252 		return "FUSE_READLINK";
253 	case FUSE_SYMLINK:
254 		return "FUSE_SYMLINK";
255 	case FUSE_MKNOD:
256 		return "FUSE_MKNOD";
257 	case FUSE_MKDIR:
258 		return "FUSE_MKDIR";
259 	case FUSE_UNLINK:
260 		return "FUSE_UNLINK";
261 	case FUSE_RMDIR:
262 		return "FUSE_RMDIR";
263 	case FUSE_RENAME:
264 		return "FUSE_RENAME";
265 	case FUSE_LINK:
266 		return "FUSE_LINK";
267 	case FUSE_OPEN:
268 		return "FUSE_OPEN";
269 	case FUSE_READ:
270 		return "FUSE_READ";
271 	case FUSE_WRITE:
272 		return "FUSE_WRITE";
273 	case FUSE_STATFS:
274 		return "FUSE_STATFS";
275 	case FUSE_RELEASE:
276 		return "FUSE_RELEASE";
277 	case FUSE_FSYNC:
278 		return "FUSE_FSYNC";
279 	case FUSE_SETXATTR:
280 		return "FUSE_SETXATTR";
281 	case FUSE_GETXATTR:
282 		return "FUSE_GETXATTR";
283 	case FUSE_LISTXATTR:
284 		return "FUSE_LISTXATTR";
285 	case FUSE_REMOVEXATTR:
286 		return "FUSE_REMOVEXATTR";
287 	case FUSE_FLUSH:
288 		return "FUSE_FLUSH";
289 	case FUSE_INIT:
290 		return "FUSE_INIT";
291 	case FUSE_OPENDIR:
292 		return "FUSE_OPENDIR";
293 	case FUSE_READDIR:
294 		return "FUSE_READDIR";
295 	case FUSE_RELEASEDIR:
296 		return "FUSE_RELEASEDIR";
297 	case FUSE_FSYNCDIR:
298 		return "FUSE_FSYNCDIR";
299 	case FUSE_GETLK:
300 		return "FUSE_GETLK";
301 	case FUSE_SETLK:
302 		return "FUSE_SETLK";
303 	case FUSE_SETLKW:
304 		return "FUSE_SETLKW";
305 	case FUSE_ACCESS:
306 		return "FUSE_ACCESS";
307 	case FUSE_CREATE:
308 		return "FUSE_CREATE";
309 	case FUSE_INTERRUPT:
310 		return "FUSE_INTERRUPT";
311 	case FUSE_BMAP:
312 		return "FUSE_BMAP";
313 	case FUSE_DESTROY:
314 		return "FUSE_DESTROY";
315 	case FUSE_IOCTL:
316 		return "FUSE_IOCTL";
317 	case FUSE_POLL:
318 		return "FUSE_POLL";
319 	case FUSE_NOTIFY_REPLY:
320 		return "FUSE_NOTIFY_REPLY";
321 	case FUSE_BATCH_FORGET:
322 		return "FUSE_BATCH_FORGET";
323 	case FUSE_FALLOCATE:
324 		return "FUSE_FALLOCATE";
325 	case FUSE_READDIRPLUS:
326 		return "FUSE_READDIRPLUS";
327 	case FUSE_RENAME2:
328 		return "FUSE_RENAME2";
329 	case FUSE_LSEEK:
330 		return "FUSE_LSEEK";
331 	case FUSE_COPY_FILE_RANGE:
332 		return "FUSE_COPY_FILE_RANGE";
333 	default:
334 		fuse_panic("Invalid opcode %d", op);
335 		break;
336 	}
337 
338 	return NULL;
339 }
340