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 } 340