xref: /dragonfly/sys/vfs/fuse/fuse_util.c (revision 1a8e5e4cf0cfbe16676810f7edca73f98bb9b8f5)
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
fuse_hexdump(const char * p,size_t len)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
fuse_fill_in_header(struct fuse_in_header * ihd,uint32_t len,uint32_t opcode,uint64_t unique,uint64_t nodeid,uint32_t uid,uint32_t gid,uint32_t pid)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
fuse_forget_node(struct fuse_mount * fmp,uint64_t ino,uint64_t nlookup,struct ucred * cred)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
fuse_audit_length(struct fuse_in_header * ihd,struct fuse_out_header * ohd)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*
fuse_get_ops(int op)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