Merge branch 'vendor/MDOCML'
[dragonfly.git] / sys / vfs / fuse / fuse_util.c
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(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 }