1 1.2 pho /* $NetBSD: fs.c,v 1.2 2023/07/14 02:43:50 pho Exp $ */ 2 1.1 pho 3 1.1 pho /* 4 1.1 pho * Copyright (c) 2021 The NetBSD Foundation, Inc. 5 1.1 pho * All rights reserved. 6 1.1 pho * 7 1.1 pho * Redistribution and use in source and binary forms, with or without 8 1.1 pho * modification, are permitted provided that the following conditions 9 1.1 pho * are met: 10 1.1 pho * 1. Redistributions of source code must retain the above copyright 11 1.1 pho * notice, this list of conditions and the following disclaimer. 12 1.1 pho * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 pho * notice, this list of conditions and the following disclaimer in the 14 1.1 pho * documentation and/or other materials provided with the distribution. 15 1.1 pho * 3. The name of the author may not be used to endorse or promote 16 1.1 pho * products derived from this software without specific prior written 17 1.1 pho * permission. 18 1.1 pho * 19 1.1 pho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20 1.1 pho * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 1.1 pho * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 pho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 1.1 pho * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 pho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 1.1 pho * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 pho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 1.1 pho * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 1.1 pho * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 1.1 pho * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 1.1 pho */ 31 1.1 pho 32 1.1 pho #include <sys/cdefs.h> 33 1.1 pho #if !defined(lint) 34 1.2 pho __RCSID("$NetBSD: fs.c,v 1.2 2023/07/14 02:43:50 pho Exp $"); 35 1.1 pho #endif /* !lint */ 36 1.1 pho 37 1.1 pho /* 38 1.1 pho * Filesystem Stacking API, appeared on FUSE 2.7. 39 1.1 pho * 40 1.1 pho * So many callback functions in struct fuse_operations have different 41 1.1 pho * prototypes between versions. We use the stacking API to abstract 42 1.1 pho * that away to implement puffs operations in a manageable way. 43 1.1 pho */ 44 1.1 pho 45 1.1 pho #include <err.h> 46 1.1 pho #include <fuse_internal.h> 47 1.1 pho #include <stdlib.h> 48 1.1 pho #include <string.h> 49 1.1 pho #include <sys/dirent.h> 50 1.1 pho #include <sys/errno.h> 51 1.1 pho 52 1.1 pho struct fuse_fs { 53 1.1 pho void* op; 54 1.1 pho int op_version; 55 1.1 pho void* user_data; 56 1.1 pho }; 57 1.1 pho 58 1.1 pho #define UNKNOWN_VERSION(op_version) \ 59 1.1 pho errc(EXIT_FAILURE, ENOSYS, "%s: unknown fuse_operations version: %d", \ 60 1.1 pho __func__, op_version) 61 1.1 pho 62 1.1 pho static void* 63 1.1 pho clone_op(const void* op, int op_version) { 64 1.1 pho void* cloned; 65 1.1 pho 66 1.1 pho switch (op_version) { 67 1.1 pho #define CLONE_OP(VER) \ 68 1.1 pho case VER: \ 69 1.1 pho cloned = malloc(sizeof(struct __CONCAT(fuse_operations_v,VER))); \ 70 1.1 pho if (!cloned) \ 71 1.1 pho return NULL; \ 72 1.1 pho memcpy(cloned, op, sizeof(struct __CONCAT(fuse_operations_v,VER))); \ 73 1.1 pho return cloned 74 1.1 pho 75 1.1 pho CLONE_OP(11); 76 1.1 pho CLONE_OP(21); 77 1.1 pho CLONE_OP(22); 78 1.1 pho CLONE_OP(23); 79 1.1 pho CLONE_OP(25); 80 1.1 pho CLONE_OP(26); 81 1.1 pho CLONE_OP(28); 82 1.1 pho CLONE_OP(29); 83 1.1 pho CLONE_OP(30); 84 1.1 pho CLONE_OP(34); 85 1.1 pho CLONE_OP(35); 86 1.1 pho CLONE_OP(38); 87 1.1 pho #undef CLONE_OP 88 1.1 pho default: 89 1.1 pho UNKNOWN_VERSION(op_version); 90 1.1 pho } 91 1.1 pho } 92 1.1 pho 93 1.1 pho struct fuse_fs* 94 1.1 pho __fuse_fs_new(const void* op, int op_version, void* user_data) { 95 1.1 pho struct fuse_fs* fs; 96 1.1 pho 97 1.1 pho fs = malloc(sizeof(struct fuse_fs)); 98 1.1 pho if (!fs) 99 1.1 pho err(EXIT_FAILURE, __func__); 100 1.1 pho 101 1.1 pho /* Callers aren't obliged to keep "op" valid during the lifetime 102 1.1 pho * of struct fuse_fs*. We must clone it now, even though it's 103 1.1 pho * non-trivial. */ 104 1.1 pho fs->op = clone_op(op, op_version); 105 1.1 pho if (!fs->op) 106 1.1 pho err(EXIT_FAILURE, __func__); 107 1.1 pho 108 1.1 pho fs->op_version = op_version; 109 1.1 pho fs->user_data = user_data; 110 1.1 pho 111 1.1 pho return fs; 112 1.1 pho } 113 1.1 pho 114 1.1 pho /* Clobber the context private_data with that of this filesystem 115 1.1 pho * layer. This function needs to be called before invoking any of 116 1.1 pho * operation callbacks. */ 117 1.1 pho static void 118 1.1 pho clobber_context_user_data(struct fuse_fs* fs) { 119 1.1 pho fuse_get_context()->private_data = fs->user_data; 120 1.1 pho } 121 1.1 pho 122 1.1 pho /* Ugly... These are like hand-written vtables... */ 123 1.1 pho int 124 1.1 pho fuse_fs_getattr_v27(struct fuse_fs *fs, const char *path, struct stat *buf) { 125 1.1 pho return fuse_fs_getattr_v30(fs, path, buf, NULL); 126 1.1 pho } 127 1.1 pho 128 1.1 pho int 129 1.1 pho fuse_fs_getattr_v30(struct fuse_fs* fs, const char* path, 130 1.1 pho struct stat* buf, struct fuse_file_info* fi) { 131 1.1 pho clobber_context_user_data(fs); 132 1.1 pho switch (fs->op_version) { 133 1.1 pho #define CALL_OLD_GETATTR(VER) \ 134 1.1 pho case VER: \ 135 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr) \ 136 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr(path, buf); \ 137 1.1 pho else \ 138 1.1 pho return -ENOSYS 139 1.1 pho CALL_OLD_GETATTR(11); 140 1.1 pho CALL_OLD_GETATTR(21); 141 1.1 pho CALL_OLD_GETATTR(22); 142 1.1 pho CALL_OLD_GETATTR(23); 143 1.1 pho CALL_OLD_GETATTR(25); 144 1.1 pho CALL_OLD_GETATTR(26); 145 1.1 pho CALL_OLD_GETATTR(28); 146 1.1 pho CALL_OLD_GETATTR(29); 147 1.1 pho #undef CALL_OLD_GETATTR 148 1.1 pho 149 1.1 pho #define CALL_GETATTR(VER) \ 150 1.1 pho case VER: \ 151 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr) \ 152 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr(path, buf, fi); \ 153 1.1 pho else \ 154 1.1 pho return -ENOSYS 155 1.1 pho CALL_GETATTR(30); 156 1.1 pho CALL_GETATTR(34); 157 1.2 pho CALL_GETATTR(35); 158 1.1 pho CALL_GETATTR(38); 159 1.1 pho #undef CALL_GETATTR 160 1.1 pho default: 161 1.1 pho UNKNOWN_VERSION(fs->op_version); 162 1.1 pho } 163 1.1 pho } 164 1.1 pho 165 1.1 pho int 166 1.1 pho fuse_fs_fgetattr(struct fuse_fs* fs, const char* path, struct stat* buf, 167 1.1 pho struct fuse_file_info* fi) { 168 1.1 pho clobber_context_user_data(fs); 169 1.1 pho /* fgetattr() was introduced on FUSE 2.5 then disappeared on FUSE 170 1.1 pho * 3.0. Fall back to getattr() if it's missing. */ 171 1.1 pho switch (fs->op_version) { 172 1.1 pho case 11: 173 1.1 pho case 21: 174 1.1 pho case 22: 175 1.1 pho case 23: 176 1.1 pho return fuse_fs_getattr_v30(fs, path, buf, fi); 177 1.1 pho 178 1.1 pho #define CALL_FGETATTR_OR_OLD_GETATTR(VER) \ 179 1.1 pho case VER: \ 180 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fgetattr) \ 181 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fgetattr(path, buf, fi); \ 182 1.1 pho else if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr) \ 183 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getattr(path, buf); \ 184 1.1 pho else \ 185 1.1 pho return -ENOSYS 186 1.1 pho CALL_FGETATTR_OR_OLD_GETATTR(25); 187 1.1 pho CALL_FGETATTR_OR_OLD_GETATTR(26); 188 1.1 pho CALL_FGETATTR_OR_OLD_GETATTR(28); 189 1.1 pho CALL_FGETATTR_OR_OLD_GETATTR(29); 190 1.1 pho #undef CALL_FGETATTR_OR_OLD_GETATTR 191 1.1 pho 192 1.1 pho case 30: 193 1.1 pho case 34: 194 1.2 pho case 35: 195 1.1 pho case 38: 196 1.1 pho return fuse_fs_getattr_v30(fs, path, buf, fi); 197 1.1 pho default: 198 1.1 pho UNKNOWN_VERSION(fs->op_version); 199 1.1 pho } 200 1.1 pho } 201 1.1 pho 202 1.1 pho int 203 1.1 pho fuse_fs_rename_v27(struct fuse_fs* fs, const char* oldpath, const char* newpath) { 204 1.1 pho return fuse_fs_rename_v30(fs, oldpath, newpath, 0); 205 1.1 pho } 206 1.1 pho 207 1.1 pho int 208 1.1 pho fuse_fs_rename_v30(struct fuse_fs* fs, const char* oldpath, 209 1.1 pho const char* newpath, unsigned int flags) { 210 1.1 pho clobber_context_user_data(fs); 211 1.1 pho switch (fs->op_version) { 212 1.1 pho #define CALL_OLD_RENAME(VER) \ 213 1.1 pho case VER: \ 214 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rename) \ 215 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rename(oldpath, newpath); \ 216 1.1 pho else \ 217 1.1 pho return -ENOSYS 218 1.1 pho CALL_OLD_RENAME(11); 219 1.1 pho CALL_OLD_RENAME(21); 220 1.1 pho CALL_OLD_RENAME(22); 221 1.1 pho CALL_OLD_RENAME(23); 222 1.1 pho CALL_OLD_RENAME(25); 223 1.1 pho CALL_OLD_RENAME(26); 224 1.1 pho CALL_OLD_RENAME(28); 225 1.1 pho CALL_OLD_RENAME(29); 226 1.1 pho #undef CALL_OLD_RENAME 227 1.1 pho 228 1.1 pho #define CALL_RENAME(VER) \ 229 1.1 pho case VER: \ 230 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rename) \ 231 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rename(oldpath, newpath, flags); \ 232 1.1 pho else \ 233 1.1 pho return -ENOSYS 234 1.1 pho CALL_RENAME(30); 235 1.1 pho CALL_RENAME(34); 236 1.2 pho CALL_RENAME(35); 237 1.1 pho CALL_RENAME(38); 238 1.1 pho #undef CALL_RENAME 239 1.1 pho default: 240 1.1 pho UNKNOWN_VERSION(fs->op_version); 241 1.1 pho } 242 1.1 pho } 243 1.1 pho 244 1.1 pho int 245 1.1 pho fuse_fs_unlink(struct fuse_fs* fs, const char* path) { 246 1.1 pho clobber_context_user_data(fs); 247 1.1 pho switch (fs->op_version) { 248 1.1 pho #define CALL_UNLINK(VER) \ 249 1.1 pho case VER: \ 250 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->unlink) \ 251 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->unlink(path); \ 252 1.1 pho else \ 253 1.1 pho return -ENOSYS 254 1.1 pho CALL_UNLINK(11); 255 1.1 pho CALL_UNLINK(21); 256 1.1 pho CALL_UNLINK(22); 257 1.1 pho CALL_UNLINK(23); 258 1.1 pho CALL_UNLINK(25); 259 1.1 pho CALL_UNLINK(26); 260 1.1 pho CALL_UNLINK(28); 261 1.1 pho CALL_UNLINK(29); 262 1.1 pho CALL_UNLINK(30); 263 1.1 pho CALL_UNLINK(34); 264 1.2 pho CALL_UNLINK(35); 265 1.1 pho CALL_UNLINK(38); 266 1.1 pho #undef CALL_UNLINK 267 1.1 pho default: 268 1.1 pho UNKNOWN_VERSION(fs->op_version); 269 1.1 pho } 270 1.1 pho } 271 1.1 pho 272 1.1 pho int 273 1.1 pho fuse_fs_rmdir(struct fuse_fs* fs, const char* path) { 274 1.1 pho clobber_context_user_data(fs); 275 1.1 pho switch (fs->op_version) { 276 1.1 pho #define CALL_RMDIR(VER) \ 277 1.1 pho case VER: \ 278 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rmdir) \ 279 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->rmdir(path); \ 280 1.1 pho else \ 281 1.1 pho return -ENOSYS 282 1.1 pho CALL_RMDIR(11); 283 1.1 pho CALL_RMDIR(21); 284 1.1 pho CALL_RMDIR(22); 285 1.1 pho CALL_RMDIR(23); 286 1.1 pho CALL_RMDIR(25); 287 1.1 pho CALL_RMDIR(26); 288 1.1 pho CALL_RMDIR(28); 289 1.1 pho CALL_RMDIR(29); 290 1.1 pho CALL_RMDIR(30); 291 1.1 pho CALL_RMDIR(34); 292 1.2 pho CALL_RMDIR(35); 293 1.1 pho CALL_RMDIR(38); 294 1.1 pho #undef CALL_RMDIR 295 1.1 pho default: 296 1.1 pho UNKNOWN_VERSION(fs->op_version); 297 1.1 pho } 298 1.1 pho } 299 1.1 pho 300 1.1 pho int 301 1.1 pho fuse_fs_symlink(struct fuse_fs* fs, const char* linkname, const char* path) { 302 1.1 pho clobber_context_user_data(fs); 303 1.1 pho switch (fs->op_version) { 304 1.1 pho #define CALL_SYMLINK(VER) \ 305 1.1 pho case VER: \ 306 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->symlink) \ 307 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->symlink(linkname, path); \ 308 1.1 pho else \ 309 1.1 pho return -ENOSYS 310 1.1 pho CALL_SYMLINK(11); 311 1.1 pho CALL_SYMLINK(21); 312 1.1 pho CALL_SYMLINK(22); 313 1.1 pho CALL_SYMLINK(23); 314 1.1 pho CALL_SYMLINK(25); 315 1.1 pho CALL_SYMLINK(26); 316 1.1 pho CALL_SYMLINK(28); 317 1.1 pho CALL_SYMLINK(29); 318 1.1 pho CALL_SYMLINK(30); 319 1.1 pho CALL_SYMLINK(34); 320 1.2 pho CALL_SYMLINK(35); 321 1.1 pho CALL_SYMLINK(38); 322 1.1 pho #undef CALL_SYMLINK 323 1.1 pho default: 324 1.1 pho UNKNOWN_VERSION(fs->op_version); 325 1.1 pho } 326 1.1 pho } 327 1.1 pho 328 1.1 pho int 329 1.1 pho fuse_fs_link(struct fuse_fs* fs, const char* oldpath, const char* newpath) { 330 1.1 pho clobber_context_user_data(fs); 331 1.1 pho switch (fs->op_version) { 332 1.1 pho #define CALL_LINK(VER) \ 333 1.1 pho case VER: \ 334 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->link) \ 335 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->link(oldpath, newpath); \ 336 1.1 pho else \ 337 1.1 pho return -ENOSYS 338 1.1 pho CALL_LINK(11); 339 1.1 pho CALL_LINK(21); 340 1.1 pho CALL_LINK(22); 341 1.1 pho CALL_LINK(23); 342 1.1 pho CALL_LINK(25); 343 1.1 pho CALL_LINK(26); 344 1.1 pho CALL_LINK(28); 345 1.1 pho CALL_LINK(29); 346 1.1 pho CALL_LINK(30); 347 1.1 pho CALL_LINK(34); 348 1.2 pho CALL_LINK(35); 349 1.1 pho CALL_LINK(38); 350 1.1 pho #undef CALL_LINK 351 1.1 pho default: 352 1.1 pho UNKNOWN_VERSION(fs->op_version); 353 1.1 pho } 354 1.1 pho } 355 1.1 pho 356 1.1 pho int 357 1.1 pho fuse_fs_release(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi) { 358 1.1 pho clobber_context_user_data(fs); 359 1.1 pho switch (fs->op_version) { 360 1.1 pho #define CALL_OLD_RELEASE(VER) \ 361 1.1 pho case VER: \ 362 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->release) \ 363 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->release(path, fi->flags); \ 364 1.1 pho else \ 365 1.1 pho return 0 /* Special case */ 366 1.1 pho CALL_OLD_RELEASE(11); 367 1.1 pho CALL_OLD_RELEASE(21); 368 1.1 pho #undef CALL_OLD_RELEASE 369 1.1 pho 370 1.1 pho #define CALL_RELEASE(VER) \ 371 1.1 pho case VER: \ 372 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->release) \ 373 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->release(path, fi); \ 374 1.1 pho else \ 375 1.1 pho return 0 /* Special case */ 376 1.1 pho CALL_RELEASE(22); 377 1.1 pho CALL_RELEASE(23); 378 1.1 pho CALL_RELEASE(25); 379 1.1 pho CALL_RELEASE(26); 380 1.1 pho CALL_RELEASE(28); 381 1.1 pho CALL_RELEASE(29); 382 1.1 pho CALL_RELEASE(30); 383 1.1 pho CALL_RELEASE(34); 384 1.2 pho CALL_RELEASE(35); 385 1.1 pho CALL_RELEASE(38); 386 1.1 pho #undef CALL_RELEASE 387 1.1 pho default: 388 1.1 pho UNKNOWN_VERSION(fs->op_version); 389 1.1 pho } 390 1.1 pho } 391 1.1 pho 392 1.1 pho int 393 1.1 pho fuse_fs_open(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi) { 394 1.1 pho clobber_context_user_data(fs); 395 1.1 pho switch (fs->op_version) { 396 1.1 pho #define CALL_OLD_OPEN(VER) \ 397 1.1 pho case VER: \ 398 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->open) \ 399 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->open(path, fi->flags); \ 400 1.1 pho else \ 401 1.1 pho return 0 /* Special case */ 402 1.1 pho CALL_OLD_OPEN(11); 403 1.1 pho CALL_OLD_OPEN(21); 404 1.1 pho #undef CALL_OLD_OPEN 405 1.1 pho 406 1.1 pho #define CALL_OPEN(VER) \ 407 1.1 pho case VER: \ 408 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->open) \ 409 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->open(path, fi); \ 410 1.1 pho else \ 411 1.1 pho return 0 /* Special case */ 412 1.1 pho CALL_OPEN(22); 413 1.1 pho CALL_OPEN(23); 414 1.1 pho CALL_OPEN(25); 415 1.1 pho CALL_OPEN(26); 416 1.1 pho CALL_OPEN(28); 417 1.1 pho CALL_OPEN(29); 418 1.1 pho CALL_OPEN(30); 419 1.1 pho CALL_OPEN(34); 420 1.2 pho CALL_OPEN(35); 421 1.1 pho CALL_OPEN(38); 422 1.1 pho #undef CALL_OPEN 423 1.1 pho default: 424 1.1 pho UNKNOWN_VERSION(fs->op_version); 425 1.1 pho } 426 1.1 pho } 427 1.1 pho 428 1.1 pho int 429 1.1 pho fuse_fs_read(struct fuse_fs* fs, const char* path, char* buf, 430 1.1 pho size_t size, off_t off, struct fuse_file_info* fi) { 431 1.1 pho clobber_context_user_data(fs); 432 1.1 pho switch (fs->op_version) { 433 1.1 pho #define CALL_OLD_READ(VER) \ 434 1.1 pho case VER: \ 435 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read) \ 436 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read(path, buf, size, off); \ 437 1.1 pho else \ 438 1.1 pho return -ENOSYS 439 1.1 pho CALL_OLD_READ(11); 440 1.1 pho CALL_OLD_READ(21); 441 1.1 pho #undef CALL_OLD_READ 442 1.1 pho 443 1.1 pho #define CALL_READ(VER) \ 444 1.1 pho case VER: \ 445 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read) \ 446 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read(path, buf, size, off, fi); \ 447 1.1 pho else \ 448 1.1 pho return -ENOSYS 449 1.1 pho CALL_READ(22); 450 1.1 pho CALL_READ(23); 451 1.1 pho CALL_READ(25); 452 1.1 pho CALL_READ(26); 453 1.1 pho CALL_READ(28); 454 1.1 pho CALL_READ(29); 455 1.1 pho CALL_READ(30); 456 1.1 pho CALL_READ(34); 457 1.2 pho CALL_READ(35); 458 1.1 pho CALL_READ(38); 459 1.1 pho #undef CALL_READ 460 1.1 pho default: 461 1.1 pho UNKNOWN_VERSION(fs->op_version); 462 1.1 pho } 463 1.1 pho } 464 1.1 pho 465 1.1 pho int 466 1.1 pho fuse_fs_read_buf(struct fuse_fs* fs, const char* path, 467 1.1 pho struct fuse_bufvec** bufp, size_t size, off_t off, 468 1.1 pho struct fuse_file_info* fi) { 469 1.1 pho clobber_context_user_data(fs); 470 1.1 pho switch (fs->op_version) { 471 1.1 pho /* FUSE < 2.9 didn't have read_buf(). */ 472 1.1 pho case 11: 473 1.1 pho case 21: 474 1.1 pho case 22: 475 1.1 pho case 23: 476 1.1 pho case 25: 477 1.1 pho case 26: 478 1.1 pho case 28: 479 1.1 pho return -ENOSYS; 480 1.1 pho #define CALL_READ_BUF(VER) \ 481 1.1 pho case VER: \ 482 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read_buf) \ 483 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->read_buf(path, bufp, size, off, fi); \ 484 1.1 pho else \ 485 1.1 pho return -ENOSYS 486 1.1 pho CALL_READ_BUF(29); 487 1.1 pho CALL_READ_BUF(30); 488 1.1 pho CALL_READ_BUF(34); 489 1.2 pho CALL_READ_BUF(35); 490 1.1 pho CALL_READ_BUF(38); 491 1.1 pho #undef CALL_READ_BUF 492 1.1 pho default: 493 1.1 pho UNKNOWN_VERSION(fs->op_version); 494 1.1 pho } 495 1.1 pho } 496 1.1 pho 497 1.1 pho int 498 1.1 pho fuse_fs_write(struct fuse_fs* fs, const char* path, const char* buf, 499 1.1 pho size_t size, off_t off, struct fuse_file_info* fi) { 500 1.1 pho clobber_context_user_data(fs); 501 1.1 pho switch (fs->op_version) { 502 1.1 pho #define CALL_OLD_WRITE(VER) \ 503 1.1 pho case VER: \ 504 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write) \ 505 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write(path, buf, size, off); \ 506 1.1 pho else \ 507 1.1 pho return -ENOSYS 508 1.1 pho CALL_OLD_WRITE(11); 509 1.1 pho CALL_OLD_WRITE(21); 510 1.1 pho #undef CALL_OLD_WRITE 511 1.1 pho 512 1.1 pho #define CALL_WRITE(VER) \ 513 1.1 pho case VER: \ 514 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write) \ 515 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write(path, buf, size, off, fi); \ 516 1.1 pho else \ 517 1.1 pho return -ENOSYS 518 1.1 pho CALL_WRITE(22); 519 1.1 pho CALL_WRITE(23); 520 1.1 pho CALL_WRITE(25); 521 1.1 pho CALL_WRITE(26); 522 1.1 pho CALL_WRITE(28); 523 1.1 pho CALL_WRITE(29); 524 1.1 pho CALL_WRITE(30); 525 1.1 pho CALL_WRITE(34); 526 1.2 pho CALL_WRITE(35); 527 1.1 pho CALL_WRITE(38); 528 1.1 pho #undef CALL_WRITE 529 1.1 pho default: 530 1.1 pho UNKNOWN_VERSION(fs->op_version); 531 1.1 pho } 532 1.1 pho } 533 1.1 pho 534 1.1 pho int 535 1.1 pho fuse_fs_write_buf(struct fuse_fs* fs, const char* path, 536 1.1 pho struct fuse_bufvec* bufp, off_t off, 537 1.1 pho struct fuse_file_info* fi) { 538 1.1 pho clobber_context_user_data(fs); 539 1.1 pho switch (fs->op_version) { 540 1.1 pho /* FUSE < 2.9 didn't have write_buf(). */ 541 1.1 pho case 11: 542 1.1 pho case 21: 543 1.1 pho case 22: 544 1.1 pho case 23: 545 1.1 pho case 25: 546 1.1 pho case 26: 547 1.1 pho case 28: 548 1.1 pho return -ENOSYS; 549 1.1 pho #define CALL_WRITE_BUF(VER) \ 550 1.1 pho case VER: \ 551 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write_buf) \ 552 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->write_buf(path, bufp, off, fi); \ 553 1.1 pho else \ 554 1.1 pho return -ENOSYS 555 1.1 pho CALL_WRITE_BUF(29); 556 1.1 pho CALL_WRITE_BUF(30); 557 1.1 pho CALL_WRITE_BUF(34); 558 1.2 pho CALL_WRITE_BUF(35); 559 1.1 pho CALL_WRITE_BUF(38); 560 1.1 pho #undef CALL_WRITE_BUF 561 1.1 pho default: 562 1.1 pho UNKNOWN_VERSION(fs->op_version); 563 1.1 pho } 564 1.1 pho } 565 1.1 pho 566 1.1 pho int 567 1.1 pho fuse_fs_fsync(struct fuse_fs* fs, const char* path, int datasync, struct fuse_file_info* fi) { 568 1.1 pho clobber_context_user_data(fs); 569 1.1 pho switch (fs->op_version) { 570 1.1 pho #define CALL_OLD_FSYNC(VER) \ 571 1.1 pho case VER: \ 572 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsync) \ 573 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsync(path, datasync); \ 574 1.1 pho else \ 575 1.1 pho return -ENOSYS 576 1.1 pho CALL_OLD_FSYNC(11); 577 1.1 pho CALL_OLD_FSYNC(21); 578 1.1 pho #undef CALL_OLD_FSYNC 579 1.1 pho 580 1.1 pho #define CALL_FSYNC(VER) \ 581 1.1 pho case VER: \ 582 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsync) \ 583 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsync(path, datasync, fi); \ 584 1.1 pho else \ 585 1.1 pho return -ENOSYS 586 1.1 pho CALL_FSYNC(22); 587 1.1 pho CALL_FSYNC(23); 588 1.1 pho CALL_FSYNC(25); 589 1.1 pho CALL_FSYNC(26); 590 1.1 pho CALL_FSYNC(28); 591 1.1 pho CALL_FSYNC(29); 592 1.1 pho CALL_FSYNC(30); 593 1.1 pho CALL_FSYNC(34); 594 1.2 pho CALL_FSYNC(35); 595 1.1 pho CALL_FSYNC(38); 596 1.1 pho #undef CALL_FSYNC 597 1.1 pho default: 598 1.1 pho UNKNOWN_VERSION(fs->op_version); 599 1.1 pho } 600 1.1 pho } 601 1.1 pho 602 1.1 pho int 603 1.1 pho fuse_fs_flush(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi) { 604 1.1 pho clobber_context_user_data(fs); 605 1.1 pho /* flush() appeared on FUSE 2.1 and its prototype was changed on 606 1.1 pho * 2.2. */ 607 1.1 pho switch (fs->op_version) { 608 1.1 pho case 11: 609 1.1 pho return -ENOSYS; 610 1.1 pho case 21: 611 1.1 pho if (((const struct fuse_operations_v21 *)fs->op)->flush) 612 1.1 pho return ((const struct fuse_operations_v21 *)fs->op)->flush(path); 613 1.1 pho else 614 1.1 pho return -ENOSYS; 615 1.1 pho 616 1.1 pho #define CALL_FLUSH(VER) \ 617 1.1 pho case VER: \ 618 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->flush) \ 619 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->flush(path, fi); \ 620 1.1 pho else \ 621 1.1 pho return -ENOSYS 622 1.1 pho CALL_FLUSH(22); 623 1.1 pho CALL_FLUSH(23); 624 1.1 pho CALL_FLUSH(25); 625 1.1 pho CALL_FLUSH(26); 626 1.1 pho CALL_FLUSH(28); 627 1.1 pho CALL_FLUSH(29); 628 1.1 pho CALL_FLUSH(30); 629 1.1 pho CALL_FLUSH(34); 630 1.2 pho CALL_FLUSH(35); 631 1.1 pho CALL_FLUSH(38); 632 1.1 pho #undef CALL_FLUSH 633 1.1 pho default: 634 1.1 pho UNKNOWN_VERSION(fs->op_version); 635 1.1 pho } 636 1.1 pho } 637 1.1 pho 638 1.1 pho static void 639 1.1 pho zero_statvfs(struct statvfs* dst) { 640 1.1 pho dst->f_bsize = 0; 641 1.1 pho dst->f_frsize = 0; 642 1.1 pho dst->f_blocks = 0; 643 1.1 pho dst->f_bfree = 0; 644 1.1 pho dst->f_bavail = 0; 645 1.1 pho dst->f_files = 0; 646 1.1 pho dst->f_ffree = 0; 647 1.1 pho dst->f_fresvd = 0; 648 1.1 pho } 649 1.1 pho static void 650 1.1 pho fuse_statfs_to_statvfs(struct statvfs* dst, const struct fuse_statfs* src) { 651 1.1 pho dst->f_bsize = (unsigned long)src->block_size; 652 1.1 pho dst->f_frsize = (unsigned long)src->block_size; /* Dunno if this is correct. */ 653 1.1 pho dst->f_blocks = (fsblkcnt_t)src->blocks; 654 1.1 pho dst->f_bfree = (fsblkcnt_t)src->blocks_free; 655 1.1 pho dst->f_bavail = (fsblkcnt_t)src->blocks_free; 656 1.1 pho dst->f_files = (fsfilcnt_t)src->files; 657 1.1 pho dst->f_ffree = (fsfilcnt_t)src->files_free; 658 1.1 pho } 659 1.1 pho static void 660 1.1 pho linux_statfs_to_statvfs(struct statvfs* dst, const struct statfs* src) { 661 1.1 pho dst->f_bsize = (unsigned long)src->f_bsize; 662 1.1 pho dst->f_frsize = (unsigned long)src->f_bsize; /* Dunno if this is correct. */ 663 1.1 pho dst->f_blocks = src->f_blocks; 664 1.1 pho dst->f_bfree = src->f_bfree; 665 1.1 pho dst->f_bavail = src->f_bavail; 666 1.1 pho dst->f_files = src->f_files; 667 1.1 pho dst->f_ffree = src->f_ffree; 668 1.1 pho } 669 1.1 pho int 670 1.1 pho fuse_fs_statfs(struct fuse_fs* fs, const char* path, struct statvfs* buf) { 671 1.1 pho clobber_context_user_data(fs); 672 1.1 pho 673 1.1 pho zero_statvfs(buf); 674 1.1 pho 675 1.1 pho switch (fs->op_version) { 676 1.1 pho /* FUSE < 2.1 used "struct fuse_statfs". */ 677 1.1 pho case 11: 678 1.1 pho if (((const struct fuse_operations_v11*)fs->op)->statfs) { 679 1.1 pho struct fuse_statfs statfs_v11; 680 1.1 pho int ret; 681 1.1 pho 682 1.1 pho ret = ((const struct fuse_operations_v11*)fs->op)->statfs(path, &statfs_v11); 683 1.1 pho if (ret == 0) 684 1.1 pho fuse_statfs_to_statvfs(buf, &statfs_v11); 685 1.1 pho 686 1.1 pho return ret; 687 1.1 pho } 688 1.1 pho else 689 1.1 pho return 0; /* Special case */ 690 1.1 pho 691 1.1 pho /* FUSE >= 2.2 && < 2.5 used Linux-specific "struct 692 1.1 pho * statfs". */ 693 1.1 pho #define CALL_LINUX_STATFS(VER) \ 694 1.1 pho case VER: \ 695 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->statfs) { \ 696 1.1 pho struct statfs statfs_v22; \ 697 1.1 pho int ret; \ 698 1.1 pho \ 699 1.1 pho ret = ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->statfs(path, &statfs_v22); \ 700 1.1 pho if (ret == 0) \ 701 1.1 pho linux_statfs_to_statvfs(buf, &statfs_v22); \ 702 1.1 pho \ 703 1.1 pho return ret; \ 704 1.1 pho } \ 705 1.1 pho else \ 706 1.1 pho return 0; /* Special case */ 707 1.1 pho CALL_LINUX_STATFS(22); 708 1.1 pho CALL_LINUX_STATFS(23); 709 1.1 pho #undef CALL_STATFS 710 1.1 pho 711 1.1 pho /* FUSE >= 2.5 use struct statvfs. */ 712 1.1 pho #define CALL_STATFS(VER) \ 713 1.1 pho case VER: \ 714 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->statfs) \ 715 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->statfs(path, buf); \ 716 1.1 pho else \ 717 1.1 pho return 0; /* Special case */ 718 1.1 pho CALL_STATFS(25); 719 1.1 pho CALL_STATFS(26); 720 1.1 pho CALL_STATFS(28); 721 1.1 pho CALL_STATFS(29); 722 1.1 pho CALL_STATFS(30); 723 1.1 pho CALL_STATFS(34); 724 1.2 pho CALL_STATFS(35); 725 1.1 pho CALL_STATFS(38); 726 1.1 pho #undef CALL_STATFS 727 1.1 pho default: 728 1.1 pho UNKNOWN_VERSION(fs->op_version); 729 1.1 pho } 730 1.1 pho } 731 1.1 pho 732 1.1 pho int 733 1.1 pho fuse_fs_opendir(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi) { 734 1.1 pho clobber_context_user_data(fs); 735 1.1 pho switch (fs->op_version) { 736 1.1 pho /* FUSE < 2.3 didn't have opendir() and used to read 737 1.1 pho * directories without opening them. */ 738 1.1 pho case 11: 739 1.1 pho case 21: 740 1.1 pho case 22: 741 1.1 pho return 0; /* Special case */ 742 1.1 pho 743 1.1 pho #define CALL_OPENDIR(VER) \ 744 1.1 pho case VER: \ 745 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->opendir) \ 746 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->opendir(path, fi); \ 747 1.1 pho else \ 748 1.1 pho return 0 /* Special case */ 749 1.1 pho CALL_OPENDIR(23); 750 1.1 pho CALL_OPENDIR(25); 751 1.1 pho CALL_OPENDIR(26); 752 1.1 pho CALL_OPENDIR(28); 753 1.1 pho CALL_OPENDIR(29); 754 1.1 pho CALL_OPENDIR(30); 755 1.1 pho CALL_OPENDIR(34); 756 1.2 pho CALL_OPENDIR(35); 757 1.1 pho CALL_OPENDIR(38); 758 1.1 pho #undef CALL_OPENDIR 759 1.1 pho default: 760 1.1 pho UNKNOWN_VERSION(fs->op_version); 761 1.1 pho } 762 1.1 pho } 763 1.1 pho 764 1.1 pho /* =================================== 765 1.1 pho * -=- The readdir Madness -=- 766 1.1 pho * Juggling with Nested Shims 767 1.1 pho * =================================== */ 768 1.1 pho 769 1.1 pho struct fuse_fill_dir_v23_shim { 770 1.1 pho void* dirh; 771 1.1 pho fuse_fill_dir_t_v23 fill_dir_v23; 772 1.1 pho }; 773 1.1 pho 774 1.1 pho /* Translate dirent DT_* to mode_t. Needed by shim functions. */ 775 1.1 pho static mode_t 776 1.1 pho dt_to_mode(int dt) { 777 1.1 pho switch (dt) { 778 1.1 pho case DT_UNKNOWN: return 0; 779 1.1 pho case DT_FIFO: return S_IFIFO; 780 1.1 pho case DT_CHR: return S_IFCHR; 781 1.1 pho case DT_DIR: return S_IFCHR; 782 1.1 pho case DT_BLK: return S_IFBLK; 783 1.1 pho case DT_REG: return S_IFREG; 784 1.1 pho case DT_LNK: return S_IFLNK; 785 1.1 pho case DT_SOCK: return S_IFSOCK; 786 1.1 pho case DT_WHT: return S_IFWHT; 787 1.1 pho default: 788 1.1 pho errx(EXIT_FAILURE, "%s: unknown dirent type: %d", 789 1.1 pho __func__, dt); 790 1.1 pho } 791 1.1 pho } 792 1.1 pho 793 1.1 pho /* This is a shim function that satisfies the type of 794 1.1 pho * fuse_dirfil_t_v11 but calls fuse_fill_dir_v23. */ 795 1.1 pho static int 796 1.1 pho fuse_dirfil_v11_to_fill_dir_v23(fuse_dirh_t handle, const char* name, int type) { 797 1.1 pho struct fuse_fill_dir_v23_shim* shim = handle; 798 1.1 pho struct stat stbuf; 799 1.1 pho int res; /* 1 or 0 */ 800 1.1 pho 801 1.1 pho memset(&stbuf, 0, sizeof(stbuf)); 802 1.1 pho stbuf.st_mode = dt_to_mode(type); 803 1.1 pho 804 1.1 pho res = shim->fill_dir_v23(shim->dirh, name, &stbuf, 0); 805 1.1 pho return res ? -ENOMEM : 0; 806 1.1 pho } 807 1.1 pho 808 1.1 pho /* This is a shim function that satisfies the type of 809 1.1 pho * fuse_dirfil_t_v22 but calls fuse_fill_dir_v23. */ 810 1.1 pho static int 811 1.1 pho fuse_dirfil_v22_to_fill_dir_v23(fuse_dirh_t handle, const char* name, int type, ino_t ino) { 812 1.1 pho struct fuse_fill_dir_v23_shim* shim = handle; 813 1.1 pho struct stat stbuf; 814 1.1 pho int res; /* 1 or 0 */ 815 1.1 pho 816 1.1 pho memset(&stbuf, 0, sizeof(stbuf)); 817 1.1 pho stbuf.st_mode = dt_to_mode(type); 818 1.1 pho stbuf.st_ino = ino; 819 1.1 pho 820 1.1 pho res = shim->fill_dir_v23(shim->dirh, name, &stbuf, 0); 821 1.1 pho return res ? -ENOMEM : 0; 822 1.1 pho } 823 1.1 pho 824 1.1 pho struct fuse_fill_dir_v30_shim { 825 1.1 pho void* dirh; 826 1.1 pho fuse_fill_dir_t_v30 fill_dir_v30; 827 1.1 pho }; 828 1.1 pho 829 1.1 pho /* This is a shim function that satisfies the type of 830 1.1 pho * fuse_fill_dir_v23 but calls fuse_fill_dir_v30. */ 831 1.1 pho static int 832 1.1 pho fuse_fill_dir_v23_to_v30(void* buf, const char* name, 833 1.1 pho const struct stat* stat, off_t off) { 834 1.1 pho 835 1.1 pho struct fuse_fill_dir_v30_shim* shim = buf; 836 1.1 pho 837 1.1 pho return shim->fill_dir_v30(shim->dirh, name, stat, off, (enum fuse_fill_dir_flags)0); 838 1.1 pho } 839 1.1 pho 840 1.1 pho int 841 1.1 pho fuse_fs_readdir_v27(struct fuse_fs* fs, const char* path, void* buf, 842 1.1 pho fuse_fill_dir_t_v23 filler, off_t off, 843 1.1 pho struct fuse_file_info* fi) { 844 1.1 pho 845 1.1 pho struct fuse_fill_dir_v23_shim v23_shim; 846 1.1 pho 847 1.1 pho v23_shim.dirh = buf; 848 1.1 pho v23_shim.fill_dir_v23 = filler; 849 1.1 pho 850 1.1 pho clobber_context_user_data(fs); 851 1.1 pho 852 1.1 pho switch (fs->op_version) { 853 1.1 pho /* FUSE < 2.2 had getdir() that used fuse_dirfil_t_v11. */ 854 1.1 pho #define CALL_GETDIR_V11(VER) \ 855 1.1 pho case VER: \ 856 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getdir) \ 857 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getdir(path, &v23_shim, fuse_dirfil_v11_to_fill_dir_v23); \ 858 1.1 pho else \ 859 1.1 pho return -ENOSYS 860 1.1 pho CALL_GETDIR_V11(11); 861 1.1 pho CALL_GETDIR_V11(21); 862 1.1 pho #undef CALL_GETDIR_V11 863 1.1 pho 864 1.1 pho /* FUSE 2.2 had getdir() that used fuse_dirfil_t_v22 but 865 1.1 pho * didn't have readdir(). */ 866 1.1 pho case 22: 867 1.1 pho if (((const struct fuse_operations_v22*)fs->op)->getdir) 868 1.1 pho return ((const struct fuse_operations_v22*)fs->op)->getdir(path, &v23_shim, fuse_dirfil_v22_to_fill_dir_v23); 869 1.1 pho else 870 1.1 pho return -ENOSYS; 871 1.1 pho 872 1.1 pho /* FUSE 2.3 introduced readdir() but still had getdir() as 873 1.1 pho * a deprecated operation. It had been this way until FUSE 3.0 874 1.1 pho * finally removed getdir() and also changed the prototype of 875 1.1 pho * readdir(). */ 876 1.1 pho #define CALL_READDIR_OR_GETDIR(VER) \ 877 1.1 pho case VER: \ 878 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readdir) \ 879 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readdir(path, buf, filler, off, fi); \ 880 1.1 pho else if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getdir) \ 881 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getdir(path, &v23_shim, fuse_dirfil_v22_to_fill_dir_v23); \ 882 1.1 pho else \ 883 1.1 pho return -ENOSYS 884 1.1 pho CALL_READDIR_OR_GETDIR(23); 885 1.1 pho CALL_READDIR_OR_GETDIR(25); 886 1.1 pho CALL_READDIR_OR_GETDIR(26); 887 1.1 pho CALL_READDIR_OR_GETDIR(28); 888 1.1 pho CALL_READDIR_OR_GETDIR(29); 889 1.1 pho #undef CALL_READDIR_OR_GETDIR 890 1.1 pho 891 1.1 pho default: 892 1.1 pho /* FUSE >= 3.0 filesystems will never call this function. We 893 1.1 pho * can safely ignore them here. */ 894 1.1 pho UNKNOWN_VERSION(fs->op_version); 895 1.1 pho } 896 1.1 pho } 897 1.1 pho 898 1.1 pho int 899 1.1 pho fuse_fs_readdir_v30(struct fuse_fs* fs, const char* path, void* buf, 900 1.1 pho fuse_fill_dir_t_v30 filler, off_t off, 901 1.1 pho struct fuse_file_info* fi, enum fuse_readdir_flags flags) { 902 1.1 pho clobber_context_user_data(fs); 903 1.1 pho 904 1.1 pho if (fs->op_version < 30) { 905 1.1 pho struct fuse_fill_dir_v30_shim v30_shim; 906 1.1 pho 907 1.1 pho v30_shim.dirh = buf; 908 1.1 pho v30_shim.fill_dir_v30 = filler; 909 1.1 pho 910 1.1 pho return fuse_fs_readdir_v27(fs, path, &v30_shim, fuse_fill_dir_v23_to_v30, off, fi); 911 1.1 pho } 912 1.1 pho else { 913 1.1 pho switch (fs->op_version) { 914 1.1 pho #define CALL_READDIR(VER) \ 915 1.1 pho case VER: \ 916 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readdir) \ 917 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readdir(path, buf, filler, off, fi, flags); \ 918 1.1 pho else \ 919 1.1 pho return -ENOSYS 920 1.1 pho CALL_READDIR(30); 921 1.1 pho CALL_READDIR(34); 922 1.2 pho CALL_READDIR(35); 923 1.1 pho CALL_READDIR(38); 924 1.1 pho #undef CALL_READDIR 925 1.1 pho default: 926 1.1 pho UNKNOWN_VERSION(fs->op_version); 927 1.1 pho } 928 1.1 pho } 929 1.1 pho } 930 1.1 pho 931 1.1 pho /* ============================== 932 1.1 pho * The End of readdir Madness 933 1.1 pho * ============================== */ 934 1.1 pho 935 1.1 pho int 936 1.1 pho fuse_fs_fsyncdir(struct fuse_fs* fs, const char* path, int datasync, struct fuse_file_info* fi) { 937 1.1 pho clobber_context_user_data(fs); 938 1.1 pho /* fsyncdir() appeared on FUSE 2.3. */ 939 1.1 pho switch (fs->op_version) { 940 1.1 pho case 11: 941 1.1 pho case 21: 942 1.1 pho case 22: 943 1.1 pho return -ENOSYS; 944 1.1 pho 945 1.1 pho #define CALL_FSYNCDIR(VER) \ 946 1.1 pho case VER: \ 947 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsyncdir) \ 948 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fsyncdir(path, datasync, fi); \ 949 1.1 pho else \ 950 1.1 pho return -ENOSYS 951 1.1 pho CALL_FSYNCDIR(23); 952 1.1 pho CALL_FSYNCDIR(25); 953 1.1 pho CALL_FSYNCDIR(26); 954 1.1 pho CALL_FSYNCDIR(28); 955 1.1 pho CALL_FSYNCDIR(29); 956 1.1 pho CALL_FSYNCDIR(30); 957 1.1 pho CALL_FSYNCDIR(34); 958 1.2 pho CALL_FSYNCDIR(35); 959 1.1 pho CALL_FSYNCDIR(38); 960 1.1 pho #undef CALL_FSYNCDIR 961 1.1 pho default: 962 1.1 pho UNKNOWN_VERSION(fs->op_version); 963 1.1 pho } 964 1.1 pho } 965 1.1 pho 966 1.1 pho int 967 1.1 pho fuse_fs_releasedir(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi) { 968 1.1 pho clobber_context_user_data(fs); 969 1.1 pho switch (fs->op_version) { 970 1.1 pho /* FUSE < 2.3 didn't have releasedir() and was reading 971 1.1 pho * directories without opening them. */ 972 1.1 pho case 11: 973 1.1 pho case 21: 974 1.1 pho case 22: 975 1.1 pho return 0; /* Special case */ 976 1.1 pho 977 1.1 pho #define CALL_RELEASEDIR(VER) \ 978 1.1 pho case VER: \ 979 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->releasedir) \ 980 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->releasedir(path, fi); \ 981 1.1 pho else \ 982 1.1 pho return 0 /* Special case */ 983 1.1 pho CALL_RELEASEDIR(23); 984 1.1 pho CALL_RELEASEDIR(25); 985 1.1 pho CALL_RELEASEDIR(26); 986 1.1 pho CALL_RELEASEDIR(28); 987 1.1 pho CALL_RELEASEDIR(29); 988 1.1 pho CALL_RELEASEDIR(30); 989 1.1 pho CALL_RELEASEDIR(34); 990 1.2 pho CALL_RELEASEDIR(35); 991 1.1 pho CALL_RELEASEDIR(38); 992 1.1 pho #undef CALL_RELEASEDIR 993 1.1 pho default: 994 1.1 pho UNKNOWN_VERSION(fs->op_version); 995 1.1 pho } 996 1.1 pho } 997 1.1 pho 998 1.1 pho int 999 1.1 pho fuse_fs_create(struct fuse_fs* fs, const char* path, mode_t mode, struct fuse_file_info* fi) { 1000 1.1 pho clobber_context_user_data(fs); 1001 1.1 pho switch (fs->op_version) { 1002 1.1 pho /* FUSE < 2.5 didn't have create(). */ 1003 1.1 pho case 11: 1004 1.1 pho case 21: 1005 1.1 pho case 22: 1006 1.1 pho case 23: 1007 1.1 pho return -ENOSYS; 1008 1.1 pho 1009 1.1 pho #define CALL_CREATE(VER) \ 1010 1.1 pho case VER: \ 1011 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->create) \ 1012 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->create(path, mode, fi); \ 1013 1.1 pho else \ 1014 1.1 pho return -ENOSYS 1015 1.1 pho CALL_CREATE(25); 1016 1.1 pho CALL_CREATE(26); 1017 1.1 pho CALL_CREATE(28); 1018 1.1 pho CALL_CREATE(29); 1019 1.1 pho CALL_CREATE(30); 1020 1.1 pho CALL_CREATE(34); 1021 1.2 pho CALL_CREATE(35); 1022 1.1 pho CALL_CREATE(38); 1023 1.1 pho #undef CALL_CREATE 1024 1.1 pho default: 1025 1.1 pho UNKNOWN_VERSION(fs->op_version); 1026 1.1 pho } 1027 1.1 pho } 1028 1.1 pho 1029 1.1 pho int 1030 1.1 pho fuse_fs_lock(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi, 1031 1.1 pho int cmd, struct flock* lock) { 1032 1.1 pho clobber_context_user_data(fs); 1033 1.1 pho /* locK() appeared on FUSE 2.6. */ 1034 1.1 pho switch (fs->op_version) { 1035 1.1 pho case 11: 1036 1.1 pho case 21: 1037 1.1 pho case 22: 1038 1.1 pho case 23: 1039 1.1 pho case 25: 1040 1.1 pho return -ENOSYS; 1041 1.1 pho 1042 1.1 pho #define CALL_LOCK(VER) \ 1043 1.1 pho case VER: \ 1044 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->lock) \ 1045 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->lock(path, fi, cmd, lock); \ 1046 1.1 pho else \ 1047 1.1 pho return -ENOSYS 1048 1.1 pho CALL_LOCK(26); 1049 1.1 pho CALL_LOCK(28); 1050 1.1 pho CALL_LOCK(29); 1051 1.1 pho CALL_LOCK(30); 1052 1.1 pho CALL_LOCK(34); 1053 1.2 pho CALL_LOCK(35); 1054 1.1 pho CALL_LOCK(38); 1055 1.1 pho #undef CALL_LOCK 1056 1.1 pho default: 1057 1.1 pho UNKNOWN_VERSION(fs->op_version); 1058 1.1 pho } 1059 1.1 pho } 1060 1.1 pho 1061 1.1 pho int 1062 1.1 pho fuse_fs_flock(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi, int op) { 1063 1.1 pho clobber_context_user_data(fs); 1064 1.1 pho /* flocK() appeared on FUSE 2.9. */ 1065 1.1 pho switch (fs->op_version) { 1066 1.1 pho case 11: 1067 1.1 pho case 21: 1068 1.1 pho case 22: 1069 1.1 pho case 23: 1070 1.1 pho case 25: 1071 1.1 pho case 26: 1072 1.1 pho case 28: 1073 1.1 pho return -ENOSYS; 1074 1.1 pho 1075 1.1 pho #define CALL_FLOCK(VER) \ 1076 1.1 pho case VER: \ 1077 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->flock) \ 1078 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->flock(path, fi, op); \ 1079 1.1 pho else \ 1080 1.1 pho return -ENOSYS 1081 1.1 pho CALL_FLOCK(29); 1082 1.1 pho CALL_FLOCK(30); 1083 1.1 pho CALL_FLOCK(34); 1084 1.2 pho CALL_FLOCK(35); 1085 1.1 pho CALL_FLOCK(38); 1086 1.1 pho #undef CALL_FLOCK 1087 1.1 pho default: 1088 1.1 pho UNKNOWN_VERSION(fs->op_version); 1089 1.1 pho } 1090 1.1 pho } 1091 1.1 pho 1092 1.1 pho int 1093 1.1 pho fuse_fs_chmod_v27(struct fuse_fs *fs, const char *path, mode_t mode) { 1094 1.1 pho return fuse_fs_chmod_v30(fs, path, mode, NULL); 1095 1.1 pho } 1096 1.1 pho 1097 1.1 pho int 1098 1.1 pho fuse_fs_chmod_v30(struct fuse_fs* fs, const char* path, 1099 1.1 pho mode_t mode, struct fuse_file_info* fi) { 1100 1.1 pho clobber_context_user_data(fs); 1101 1.1 pho switch (fs->op_version) { 1102 1.1 pho #define CALL_OLD_CHMOD(VER) \ 1103 1.1 pho case VER: \ 1104 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chmod) \ 1105 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chmod(path, mode); \ 1106 1.1 pho else \ 1107 1.1 pho return -ENOSYS 1108 1.1 pho CALL_OLD_CHMOD(11); 1109 1.1 pho CALL_OLD_CHMOD(21); 1110 1.1 pho CALL_OLD_CHMOD(22); 1111 1.1 pho CALL_OLD_CHMOD(23); 1112 1.1 pho CALL_OLD_CHMOD(25); 1113 1.1 pho CALL_OLD_CHMOD(26); 1114 1.1 pho CALL_OLD_CHMOD(28); 1115 1.1 pho CALL_OLD_CHMOD(29); 1116 1.1 pho #undef CALL_OLD_CHMOD 1117 1.1 pho 1118 1.1 pho #define CALL_CHMOD(VER) \ 1119 1.1 pho case VER: \ 1120 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chmod) \ 1121 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chmod(path, mode, fi); \ 1122 1.1 pho else \ 1123 1.1 pho return -ENOSYS 1124 1.1 pho CALL_CHMOD(30); 1125 1.1 pho CALL_CHMOD(34); 1126 1.2 pho CALL_CHMOD(35); 1127 1.1 pho CALL_CHMOD(38); 1128 1.1 pho #undef CALL_CHMOD 1129 1.1 pho default: 1130 1.1 pho UNKNOWN_VERSION(fs->op_version); 1131 1.1 pho } 1132 1.1 pho } 1133 1.1 pho 1134 1.1 pho int fuse_fs_chown_v27(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid) { 1135 1.1 pho return fuse_fs_chown_v30(fs, path, uid, gid, NULL); 1136 1.1 pho } 1137 1.1 pho 1138 1.1 pho int 1139 1.1 pho fuse_fs_chown_v30(struct fuse_fs* fs, const char* path, 1140 1.1 pho uid_t uid, gid_t gid, struct fuse_file_info* fi) { 1141 1.1 pho clobber_context_user_data(fs); 1142 1.1 pho switch (fs->op_version) { 1143 1.1 pho #define CALL_OLD_CHOWN(VER) \ 1144 1.1 pho case VER: \ 1145 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chown) \ 1146 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chown(path, uid, gid); \ 1147 1.1 pho else \ 1148 1.1 pho return -ENOSYS 1149 1.1 pho CALL_OLD_CHOWN(11); 1150 1.1 pho CALL_OLD_CHOWN(21); 1151 1.1 pho CALL_OLD_CHOWN(22); 1152 1.1 pho CALL_OLD_CHOWN(23); 1153 1.1 pho CALL_OLD_CHOWN(25); 1154 1.1 pho CALL_OLD_CHOWN(26); 1155 1.1 pho CALL_OLD_CHOWN(28); 1156 1.1 pho CALL_OLD_CHOWN(29); 1157 1.1 pho #undef CALL_OLD_CHOWN 1158 1.1 pho 1159 1.1 pho #define CALL_CHOWN(VER) \ 1160 1.1 pho case VER: \ 1161 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chown) \ 1162 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->chown(path, uid, gid, fi); \ 1163 1.1 pho else \ 1164 1.1 pho return -ENOSYS 1165 1.1 pho CALL_CHOWN(30); 1166 1.1 pho CALL_CHOWN(34); 1167 1.2 pho CALL_CHOWN(35); 1168 1.1 pho CALL_CHOWN(38); 1169 1.1 pho #undef CALL_CHOWN 1170 1.1 pho default: 1171 1.1 pho UNKNOWN_VERSION(fs->op_version); 1172 1.1 pho } 1173 1.1 pho } 1174 1.1 pho 1175 1.1 pho int fuse_fs_truncate_v27(struct fuse_fs *fs, const char *path, off_t size) { 1176 1.1 pho return fuse_fs_truncate_v30(fs, path, size, NULL); 1177 1.1 pho } 1178 1.1 pho 1179 1.1 pho int 1180 1.1 pho fuse_fs_truncate_v30(struct fuse_fs* fs, const char* path, off_t size, struct fuse_file_info* fi) { 1181 1.1 pho clobber_context_user_data(fs); 1182 1.1 pho switch (fs->op_version) { 1183 1.1 pho #define CALL_OLD_TRUNCATE(VER) \ 1184 1.1 pho case VER: \ 1185 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate) \ 1186 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate(path, size); \ 1187 1.1 pho else \ 1188 1.1 pho return -ENOSYS 1189 1.1 pho CALL_OLD_TRUNCATE(11); 1190 1.1 pho CALL_OLD_TRUNCATE(21); 1191 1.1 pho CALL_OLD_TRUNCATE(22); 1192 1.1 pho CALL_OLD_TRUNCATE(23); 1193 1.1 pho CALL_OLD_TRUNCATE(25); 1194 1.1 pho CALL_OLD_TRUNCATE(26); 1195 1.1 pho CALL_OLD_TRUNCATE(28); 1196 1.1 pho CALL_OLD_TRUNCATE(29); 1197 1.1 pho #undef CALL_OLD_TRUNCATE 1198 1.1 pho 1199 1.1 pho #define CALL_TRUNCATE(VER) \ 1200 1.1 pho case VER: \ 1201 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate) \ 1202 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate(path, size, fi); \ 1203 1.1 pho else \ 1204 1.1 pho return -ENOSYS 1205 1.1 pho CALL_TRUNCATE(30); 1206 1.1 pho CALL_TRUNCATE(34); 1207 1.2 pho CALL_TRUNCATE(35); 1208 1.1 pho CALL_TRUNCATE(38); 1209 1.1 pho #undef CALL_TRUNCATE 1210 1.1 pho default: 1211 1.1 pho UNKNOWN_VERSION(fs->op_version); 1212 1.1 pho } 1213 1.1 pho } 1214 1.1 pho 1215 1.1 pho int 1216 1.1 pho fuse_fs_ftruncate(struct fuse_fs* fs, const char* path, off_t size, struct fuse_file_info* fi) { 1217 1.1 pho clobber_context_user_data(fs); 1218 1.1 pho switch (fs->op_version) { 1219 1.1 pho /* FUSE < 2.5 didn't have ftruncate(). Always fall back to 1220 1.1 pho * truncate(). */ 1221 1.1 pho #define CALL_OLD_TRUNCATE(VER) \ 1222 1.1 pho case VER: \ 1223 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate) \ 1224 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate(path, size); \ 1225 1.1 pho else \ 1226 1.1 pho return -ENOSYS 1227 1.1 pho CALL_OLD_TRUNCATE(11); 1228 1.1 pho CALL_OLD_TRUNCATE(21); 1229 1.1 pho CALL_OLD_TRUNCATE(22); 1230 1.1 pho CALL_OLD_TRUNCATE(23); 1231 1.1 pho #undef CALL_OLD_TRUNCATE 1232 1.1 pho 1233 1.1 pho /* ftruncate() appeared on FUSE 2.5 and then disappeared on 1234 1.1 pho * FUSE 3.0. Call it if it exists, or fall back to truncate() 1235 1.1 pho * otherwise. */ 1236 1.1 pho #define CALL_FTRUNCATE_OR_TRUNCATE(VER) \ 1237 1.1 pho case VER: \ 1238 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ftruncate) \ 1239 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ftruncate(path, size, fi); \ 1240 1.1 pho else if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate) \ 1241 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate(path, size); \ 1242 1.1 pho else \ 1243 1.1 pho return -ENOSYS 1244 1.1 pho CALL_FTRUNCATE_OR_TRUNCATE(25); 1245 1.1 pho CALL_FTRUNCATE_OR_TRUNCATE(26); 1246 1.1 pho CALL_FTRUNCATE_OR_TRUNCATE(28); 1247 1.1 pho CALL_FTRUNCATE_OR_TRUNCATE(29); 1248 1.1 pho #undef CALL_FTRUNCATE_OR_TRUNCATE 1249 1.1 pho 1250 1.1 pho /* FUSE >= 3.0 have truncate() but with a different function 1251 1.1 pho * type. */ 1252 1.1 pho #define CALL_TRUNCATE(VER) \ 1253 1.1 pho case VER: \ 1254 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate) \ 1255 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->truncate(path, size, fi); \ 1256 1.1 pho else \ 1257 1.1 pho return -ENOSYS 1258 1.1 pho CALL_TRUNCATE(30); 1259 1.1 pho CALL_TRUNCATE(34); 1260 1.2 pho CALL_TRUNCATE(35); 1261 1.1 pho CALL_TRUNCATE(38); 1262 1.1 pho #undef CALL_TRUNCATE 1263 1.1 pho default: 1264 1.1 pho UNKNOWN_VERSION(fs->op_version); 1265 1.1 pho } 1266 1.1 pho } 1267 1.1 pho 1268 1.1 pho int 1269 1.1 pho fuse_fs_utimens_v27(struct fuse_fs *fs, const char *path, const struct timespec tv[2]) { 1270 1.1 pho return fuse_fs_utimens_v30(fs, path, tv, NULL); 1271 1.1 pho } 1272 1.1 pho 1273 1.1 pho int 1274 1.1 pho fuse_fs_utimens_v30(struct fuse_fs* fs, const char* path, 1275 1.1 pho const struct timespec tv[2], struct fuse_file_info* fi) { 1276 1.1 pho struct utimbuf timbuf; 1277 1.1 pho 1278 1.1 pho timbuf.actime = tv[0].tv_sec; 1279 1.1 pho timbuf.modtime = tv[1].tv_sec; 1280 1.1 pho 1281 1.1 pho clobber_context_user_data(fs); 1282 1.1 pho 1283 1.1 pho switch (fs->op_version) { 1284 1.1 pho /* FUSE < 2.6 didn't have utimens() but had utime() 1285 1.1 pho * instead. */ 1286 1.1 pho #define CALL_UTIME(VER) \ 1287 1.1 pho case VER: \ 1288 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utime) \ 1289 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utime(path, &timbuf); \ 1290 1.1 pho else \ 1291 1.1 pho return -ENOSYS 1292 1.1 pho CALL_UTIME(11); 1293 1.1 pho CALL_UTIME(21); 1294 1.1 pho CALL_UTIME(22); 1295 1.1 pho CALL_UTIME(23); 1296 1.1 pho CALL_UTIME(25); 1297 1.1 pho #undef CALL_UTIME 1298 1.1 pho 1299 1.1 pho /* utimens() appeared on FUSE 2.6. Call it if it exists, or fall back to 1300 1.1 pho * utime() otherwise. */ 1301 1.1 pho #define CALL_UTIMENS_OR_UTIME(VER) \ 1302 1.1 pho case VER: \ 1303 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utimens) \ 1304 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utimens(path, tv); \ 1305 1.1 pho else if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utime) \ 1306 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utime(path, &timbuf); \ 1307 1.1 pho else \ 1308 1.1 pho return -ENOSYS 1309 1.1 pho CALL_UTIMENS_OR_UTIME(26); 1310 1.1 pho CALL_UTIMENS_OR_UTIME(28); 1311 1.1 pho CALL_UTIMENS_OR_UTIME(29); 1312 1.1 pho #undef CALL_UTIMENS_OR_UTIME 1313 1.1 pho 1314 1.1 pho /* utime() disappeared on FUSE 3.0. */ 1315 1.1 pho #define CALL_UTIMENS(VER) \ 1316 1.1 pho case VER: \ 1317 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utimens) \ 1318 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->utimens(path, tv, fi); \ 1319 1.1 pho else \ 1320 1.1 pho return -ENOSYS 1321 1.1 pho CALL_UTIMENS(30); 1322 1.1 pho CALL_UTIMENS(34); 1323 1.2 pho CALL_UTIMENS(35); 1324 1.1 pho CALL_UTIMENS(38); 1325 1.1 pho #undef CALL_UTIMENS 1326 1.1 pho default: 1327 1.1 pho UNKNOWN_VERSION(fs->op_version); 1328 1.1 pho } 1329 1.1 pho } 1330 1.1 pho 1331 1.1 pho int 1332 1.1 pho fuse_fs_access(struct fuse_fs* fs, const char* path, int mask) { 1333 1.1 pho clobber_context_user_data(fs); 1334 1.1 pho /* access() appeared on FUSE 2.5. */ 1335 1.1 pho switch (fs->op_version) { 1336 1.1 pho case 11: 1337 1.1 pho case 21: 1338 1.1 pho case 22: 1339 1.1 pho case 23: 1340 1.1 pho return -ENOSYS; 1341 1.1 pho #define CALL_ACCESS(VER) \ 1342 1.1 pho case VER: \ 1343 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->access) \ 1344 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->access(path, mask); \ 1345 1.1 pho else \ 1346 1.1 pho return -ENOSYS 1347 1.1 pho CALL_ACCESS(25); 1348 1.1 pho CALL_ACCESS(26); 1349 1.1 pho CALL_ACCESS(28); 1350 1.1 pho CALL_ACCESS(29); 1351 1.1 pho CALL_ACCESS(30); 1352 1.1 pho CALL_ACCESS(34); 1353 1.2 pho CALL_ACCESS(35); 1354 1.1 pho CALL_ACCESS(38); 1355 1.1 pho #undef CALL_ACCESS 1356 1.1 pho default: 1357 1.1 pho UNKNOWN_VERSION(fs->op_version); 1358 1.1 pho } 1359 1.1 pho } 1360 1.1 pho 1361 1.1 pho int 1362 1.1 pho fuse_fs_readlink(struct fuse_fs* fs, const char* path, char* buf, size_t len) { 1363 1.1 pho clobber_context_user_data(fs); 1364 1.1 pho switch (fs->op_version) { 1365 1.1 pho #define CALL_READLINK(VER) \ 1366 1.1 pho case VER: \ 1367 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readlink) \ 1368 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->readlink(path, buf, len); \ 1369 1.1 pho else \ 1370 1.1 pho return -ENOSYS 1371 1.1 pho CALL_READLINK(11); 1372 1.1 pho CALL_READLINK(21); 1373 1.1 pho CALL_READLINK(22); 1374 1.1 pho CALL_READLINK(23); 1375 1.1 pho CALL_READLINK(25); 1376 1.1 pho CALL_READLINK(26); 1377 1.1 pho CALL_READLINK(28); 1378 1.1 pho CALL_READLINK(29); 1379 1.1 pho CALL_READLINK(30); 1380 1.1 pho CALL_READLINK(34); 1381 1.2 pho CALL_READLINK(35); 1382 1.1 pho CALL_READLINK(38); 1383 1.1 pho #undef CALL_READLINK 1384 1.1 pho default: 1385 1.1 pho UNKNOWN_VERSION(fs->op_version); 1386 1.1 pho } 1387 1.1 pho } 1388 1.1 pho 1389 1.1 pho int 1390 1.1 pho fuse_fs_mknod(struct fuse_fs* fs, const char* path, mode_t mode, dev_t rdev) { 1391 1.1 pho clobber_context_user_data(fs); 1392 1.1 pho switch (fs->op_version) { 1393 1.1 pho #define CALL_MKNOD(VER) \ 1394 1.1 pho case VER: \ 1395 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->mknod) \ 1396 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->mknod(path, mode, rdev); \ 1397 1.1 pho else \ 1398 1.1 pho return -ENOSYS 1399 1.1 pho CALL_MKNOD(11); 1400 1.1 pho CALL_MKNOD(21); 1401 1.1 pho CALL_MKNOD(22); 1402 1.1 pho CALL_MKNOD(23); 1403 1.1 pho CALL_MKNOD(25); 1404 1.1 pho CALL_MKNOD(26); 1405 1.1 pho CALL_MKNOD(28); 1406 1.1 pho CALL_MKNOD(29); 1407 1.1 pho CALL_MKNOD(30); 1408 1.1 pho CALL_MKNOD(34); 1409 1.2 pho CALL_MKNOD(35); 1410 1.1 pho CALL_MKNOD(38); 1411 1.1 pho #undef CALL_MKNOD 1412 1.1 pho default: 1413 1.1 pho UNKNOWN_VERSION(fs->op_version); 1414 1.1 pho } 1415 1.1 pho } 1416 1.1 pho 1417 1.1 pho int 1418 1.1 pho fuse_fs_mkdir(struct fuse_fs* fs, const char* path, mode_t mode) { 1419 1.1 pho clobber_context_user_data(fs); 1420 1.1 pho switch (fs->op_version) { 1421 1.1 pho #define CALL_MKDIR(VER) \ 1422 1.1 pho case VER: \ 1423 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->mkdir) \ 1424 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->mkdir(path, mode); \ 1425 1.1 pho else \ 1426 1.1 pho return -ENOSYS 1427 1.1 pho CALL_MKDIR(11); 1428 1.1 pho CALL_MKDIR(21); 1429 1.1 pho CALL_MKDIR(22); 1430 1.1 pho CALL_MKDIR(23); 1431 1.1 pho CALL_MKDIR(25); 1432 1.1 pho CALL_MKDIR(26); 1433 1.1 pho CALL_MKDIR(28); 1434 1.1 pho CALL_MKDIR(29); 1435 1.1 pho CALL_MKDIR(30); 1436 1.1 pho CALL_MKDIR(34); 1437 1.2 pho CALL_MKDIR(35); 1438 1.1 pho CALL_MKDIR(38); 1439 1.1 pho #undef CALL_MKDIR 1440 1.1 pho default: 1441 1.1 pho UNKNOWN_VERSION(fs->op_version); 1442 1.1 pho } 1443 1.1 pho } 1444 1.1 pho 1445 1.1 pho int fuse_fs_setxattr(struct fuse_fs* fs, const char* path, const char* name, 1446 1.1 pho const char* value, size_t size, int flags) { 1447 1.1 pho clobber_context_user_data(fs); 1448 1.1 pho /* setxattr() appeared on FUSE 2.1. */ 1449 1.1 pho switch (fs->op_version) { 1450 1.1 pho case 11: 1451 1.1 pho return -ENOSYS; 1452 1.1 pho #define CALL_SETXATTR(VER) \ 1453 1.1 pho case VER: \ 1454 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->setxattr) \ 1455 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->setxattr(path, name, value, size, flags); \ 1456 1.1 pho else \ 1457 1.1 pho return -ENOSYS 1458 1.1 pho CALL_SETXATTR(21); 1459 1.1 pho CALL_SETXATTR(22); 1460 1.1 pho CALL_SETXATTR(23); 1461 1.1 pho CALL_SETXATTR(25); 1462 1.1 pho CALL_SETXATTR(26); 1463 1.1 pho CALL_SETXATTR(28); 1464 1.1 pho CALL_SETXATTR(29); 1465 1.1 pho CALL_SETXATTR(30); 1466 1.1 pho CALL_SETXATTR(34); 1467 1.2 pho CALL_SETXATTR(35); 1468 1.1 pho CALL_SETXATTR(38); 1469 1.1 pho #undef CALL_SETXATTR 1470 1.1 pho default: 1471 1.1 pho UNKNOWN_VERSION(fs->op_version); 1472 1.1 pho } 1473 1.1 pho } 1474 1.1 pho 1475 1.1 pho int 1476 1.1 pho fuse_fs_getxattr(struct fuse_fs* fs, const char* path, const char* name, 1477 1.1 pho char* value, size_t size) { 1478 1.1 pho clobber_context_user_data(fs); 1479 1.1 pho /* getxattr() appeared on FUSE 2.1. */ 1480 1.1 pho switch (fs->op_version) { 1481 1.1 pho case 11: 1482 1.1 pho return -ENOSYS; 1483 1.1 pho #define CALL_GETXATTR(VER) \ 1484 1.1 pho case VER: \ 1485 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getxattr) \ 1486 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->getxattr(path, name, value, size); \ 1487 1.1 pho else \ 1488 1.1 pho return -ENOSYS 1489 1.1 pho CALL_GETXATTR(21); 1490 1.1 pho CALL_GETXATTR(22); 1491 1.1 pho CALL_GETXATTR(23); 1492 1.1 pho CALL_GETXATTR(25); 1493 1.1 pho CALL_GETXATTR(26); 1494 1.1 pho CALL_GETXATTR(28); 1495 1.1 pho CALL_GETXATTR(29); 1496 1.1 pho CALL_GETXATTR(30); 1497 1.1 pho CALL_GETXATTR(34); 1498 1.2 pho CALL_GETXATTR(35); 1499 1.1 pho CALL_GETXATTR(38); 1500 1.1 pho #undef CALL_GETXATTR 1501 1.1 pho default: 1502 1.1 pho UNKNOWN_VERSION(fs->op_version); 1503 1.1 pho } 1504 1.1 pho } 1505 1.1 pho 1506 1.1 pho int fuse_fs_listxattr(struct fuse_fs* fs, const char* path, char* list, size_t size) { 1507 1.1 pho clobber_context_user_data(fs); 1508 1.1 pho /* listxattr() appeared on FUSE 2.1. */ 1509 1.1 pho switch (fs->op_version) { 1510 1.1 pho case 11: 1511 1.1 pho return -ENOSYS; 1512 1.1 pho #define CALL_LISTXATTR(VER) \ 1513 1.1 pho case VER: \ 1514 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->listxattr) \ 1515 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->listxattr(path, list, size); \ 1516 1.1 pho else \ 1517 1.1 pho return -ENOSYS 1518 1.1 pho CALL_LISTXATTR(21); 1519 1.1 pho CALL_LISTXATTR(22); 1520 1.1 pho CALL_LISTXATTR(23); 1521 1.1 pho CALL_LISTXATTR(25); 1522 1.1 pho CALL_LISTXATTR(26); 1523 1.1 pho CALL_LISTXATTR(28); 1524 1.1 pho CALL_LISTXATTR(29); 1525 1.1 pho CALL_LISTXATTR(30); 1526 1.1 pho CALL_LISTXATTR(34); 1527 1.2 pho CALL_LISTXATTR(35); 1528 1.1 pho CALL_LISTXATTR(38); 1529 1.1 pho #undef CALL_LISTXATTR 1530 1.1 pho default: 1531 1.1 pho UNKNOWN_VERSION(fs->op_version); 1532 1.1 pho } 1533 1.1 pho } 1534 1.1 pho 1535 1.1 pho int 1536 1.1 pho fuse_fs_removexattr(struct fuse_fs* fs, const char* path, const char* name) { 1537 1.1 pho clobber_context_user_data(fs); 1538 1.1 pho /* removexattr() appeared on FUSE 2.1. */ 1539 1.1 pho switch (fs->op_version) { 1540 1.1 pho case 11: 1541 1.1 pho return -ENOSYS; 1542 1.1 pho #define CALL_REMOVEXATTR(VER) \ 1543 1.1 pho case VER: \ 1544 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->removexattr) \ 1545 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->removexattr(path, name); \ 1546 1.1 pho else \ 1547 1.1 pho return -ENOSYS 1548 1.1 pho CALL_REMOVEXATTR(21); 1549 1.1 pho CALL_REMOVEXATTR(22); 1550 1.1 pho CALL_REMOVEXATTR(23); 1551 1.1 pho CALL_REMOVEXATTR(25); 1552 1.1 pho CALL_REMOVEXATTR(26); 1553 1.1 pho CALL_REMOVEXATTR(28); 1554 1.1 pho CALL_REMOVEXATTR(29); 1555 1.1 pho CALL_REMOVEXATTR(30); 1556 1.1 pho CALL_REMOVEXATTR(34); 1557 1.2 pho CALL_REMOVEXATTR(35); 1558 1.1 pho CALL_REMOVEXATTR(38); 1559 1.1 pho #undef CALL_REMOVEXATTR 1560 1.1 pho default: 1561 1.1 pho UNKNOWN_VERSION(fs->op_version); 1562 1.1 pho } 1563 1.1 pho } 1564 1.1 pho 1565 1.1 pho int 1566 1.1 pho fuse_fs_bmap(struct fuse_fs* fs, const char* path, size_t blocksize, uint64_t *idx) { 1567 1.1 pho clobber_context_user_data(fs); 1568 1.1 pho /* bmap() appeared on FUSE 2.6. */ 1569 1.1 pho switch (fs->op_version) { 1570 1.1 pho case 11: 1571 1.1 pho case 22: 1572 1.1 pho case 23: 1573 1.1 pho case 25: 1574 1.1 pho return -ENOSYS; 1575 1.1 pho #define CALL_BMAP(VER) \ 1576 1.1 pho case VER: \ 1577 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->bmap) \ 1578 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->bmap(path, blocksize, idx); \ 1579 1.1 pho else \ 1580 1.1 pho return -ENOSYS 1581 1.1 pho CALL_BMAP(26); 1582 1.1 pho CALL_BMAP(28); 1583 1.1 pho CALL_BMAP(29); 1584 1.1 pho CALL_BMAP(30); 1585 1.1 pho CALL_BMAP(34); 1586 1.2 pho CALL_BMAP(35); 1587 1.1 pho CALL_BMAP(38); 1588 1.1 pho #undef CALL_BMAP 1589 1.1 pho default: 1590 1.1 pho UNKNOWN_VERSION(fs->op_version); 1591 1.1 pho } 1592 1.1 pho } 1593 1.1 pho 1594 1.1 pho int fuse_fs_ioctl_v28(struct fuse_fs* fs, const char* path, int cmd, void* arg, 1595 1.1 pho struct fuse_file_info* fi, unsigned int flags, void* data) { 1596 1.1 pho return fuse_fs_ioctl_v35(fs, path, (unsigned int)cmd, arg, fi, flags, data); 1597 1.1 pho } 1598 1.1 pho 1599 1.1 pho int fuse_fs_ioctl_v35(struct fuse_fs* fs, const char* path, unsigned int cmd, void* arg, 1600 1.1 pho struct fuse_file_info* fi, unsigned int flags, void* data) { 1601 1.1 pho clobber_context_user_data(fs); 1602 1.1 pho switch (fs->op_version) { 1603 1.1 pho /* ioctl() appeared on FUSE 2.8 but with (int)cmd. */ 1604 1.1 pho case 11: 1605 1.1 pho case 22: 1606 1.1 pho case 23: 1607 1.1 pho case 25: 1608 1.1 pho case 26: 1609 1.1 pho return -ENOSYS; 1610 1.1 pho #define CALL_OLD_IOCTL(VER) \ 1611 1.1 pho case VER: \ 1612 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ioctl) \ 1613 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ioctl(path, (int)cmd, arg, fi, flags, data); \ 1614 1.1 pho else \ 1615 1.1 pho return -ENOSYS 1616 1.1 pho CALL_OLD_IOCTL(28); 1617 1.1 pho CALL_OLD_IOCTL(29); 1618 1.1 pho CALL_OLD_IOCTL(30); 1619 1.1 pho CALL_OLD_IOCTL(34); 1620 1.1 pho #undef CALL_OLD_IOCTL 1621 1.1 pho 1622 1.1 pho /* It was then changed to (unsigned int)cmd on FUSE 3.5. */ 1623 1.1 pho #define CALL_IOCTL(VER) \ 1624 1.1 pho case VER: \ 1625 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ioctl) \ 1626 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->ioctl(path, cmd, arg, fi, flags, data); \ 1627 1.1 pho else \ 1628 1.1 pho return -ENOSYS 1629 1.1 pho CALL_IOCTL(35); 1630 1.1 pho CALL_IOCTL(38); 1631 1.1 pho #undef CALL_IOCTL 1632 1.1 pho default: 1633 1.1 pho UNKNOWN_VERSION(fs->op_version); 1634 1.1 pho } 1635 1.1 pho } 1636 1.1 pho 1637 1.1 pho int 1638 1.1 pho fuse_fs_poll(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi, 1639 1.1 pho struct fuse_pollhandle* ph, unsigned* reventsp) { 1640 1.1 pho clobber_context_user_data(fs); 1641 1.1 pho /* poll() appeared on FUSE 2.8. */ 1642 1.1 pho switch (fs->op_version) { 1643 1.1 pho case 11: 1644 1.1 pho case 22: 1645 1.1 pho case 23: 1646 1.1 pho case 25: 1647 1.1 pho case 26: 1648 1.1 pho return -ENOSYS; 1649 1.1 pho #define CALL_POLL(VER) \ 1650 1.1 pho case VER: \ 1651 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->poll) \ 1652 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->poll(path, fi, ph, reventsp); \ 1653 1.1 pho else \ 1654 1.1 pho return -ENOSYS 1655 1.1 pho CALL_POLL(28); 1656 1.1 pho CALL_POLL(29); 1657 1.1 pho CALL_POLL(30); 1658 1.1 pho CALL_POLL(34); 1659 1.2 pho CALL_POLL(35); 1660 1.1 pho CALL_POLL(38); 1661 1.1 pho #undef CALL_POLL 1662 1.1 pho default: 1663 1.1 pho UNKNOWN_VERSION(fs->op_version); 1664 1.1 pho } 1665 1.1 pho } 1666 1.1 pho 1667 1.1 pho int 1668 1.1 pho fuse_fs_fallocate(struct fuse_fs* fs, const char* path, int mode, off_t offset, 1669 1.1 pho off_t length, struct fuse_file_info* fi) { 1670 1.1 pho clobber_context_user_data(fs); 1671 1.1 pho /* fallocate() appeared on FUSE 2.9. */ 1672 1.1 pho switch (fs->op_version) { 1673 1.1 pho case 11: 1674 1.1 pho case 22: 1675 1.1 pho case 23: 1676 1.1 pho case 25: 1677 1.1 pho case 26: 1678 1.1 pho case 28: 1679 1.1 pho return -ENOSYS; 1680 1.1 pho #define CALL_FALLOCATE(VER) \ 1681 1.1 pho case VER: \ 1682 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fallocate) \ 1683 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->fallocate(path, mode, offset, length, fi); \ 1684 1.1 pho else \ 1685 1.1 pho return -ENOSYS 1686 1.1 pho CALL_FALLOCATE(29); 1687 1.1 pho CALL_FALLOCATE(30); 1688 1.1 pho CALL_FALLOCATE(34); 1689 1.2 pho CALL_FALLOCATE(35); 1690 1.1 pho CALL_FALLOCATE(38); 1691 1.1 pho #undef CALL_FALLOCATE 1692 1.1 pho default: 1693 1.1 pho UNKNOWN_VERSION(fs->op_version); 1694 1.1 pho } 1695 1.1 pho } 1696 1.1 pho 1697 1.1 pho ssize_t 1698 1.1 pho fuse_fs_copy_file_range(struct fuse_fs *fs, 1699 1.1 pho const char *path_in, struct fuse_file_info *fi_in, off_t off_in, 1700 1.1 pho const char *path_out, struct fuse_file_info *fi_out, off_t off_out, 1701 1.1 pho size_t len, int flags) { 1702 1.1 pho clobber_context_user_data(fs); 1703 1.1 pho /* copy_file_range() appeared on FUSE 3.4. */ 1704 1.1 pho switch (fs->op_version) { 1705 1.1 pho case 11: 1706 1.1 pho case 22: 1707 1.1 pho case 23: 1708 1.1 pho case 25: 1709 1.1 pho case 26: 1710 1.1 pho case 28: 1711 1.1 pho case 29: 1712 1.1 pho case 30: 1713 1.1 pho return -ENOSYS; 1714 1.1 pho #define CALL_COPY_FILE_RANGE(VER) \ 1715 1.1 pho case VER: \ 1716 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->copy_file_range) \ 1717 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->copy_file_range(path_in, fi_in, off_in, path_out, fi_out, off_out, len, flags); \ 1718 1.1 pho else \ 1719 1.1 pho return -ENOSYS 1720 1.1 pho CALL_COPY_FILE_RANGE(34); 1721 1.2 pho CALL_COPY_FILE_RANGE(35); 1722 1.1 pho CALL_COPY_FILE_RANGE(38); 1723 1.1 pho #undef CALL_COPY_FILE_RANGE 1724 1.1 pho default: 1725 1.1 pho UNKNOWN_VERSION(fs->op_version); 1726 1.1 pho } 1727 1.1 pho } 1728 1.1 pho 1729 1.1 pho off_t 1730 1.1 pho fuse_fs_lseek(struct fuse_fs* fs, const char* path, off_t off, int whence, 1731 1.1 pho struct fuse_file_info* fi) { 1732 1.1 pho clobber_context_user_data(fs); 1733 1.1 pho /* lseek() appeared on FUSE 3.8. */ 1734 1.1 pho switch (fs->op_version) { 1735 1.1 pho case 11: 1736 1.1 pho case 22: 1737 1.1 pho case 23: 1738 1.1 pho case 25: 1739 1.1 pho case 26: 1740 1.1 pho case 28: 1741 1.1 pho case 29: 1742 1.1 pho case 30: 1743 1.1 pho case 34: 1744 1.2 pho case 35: 1745 1.1 pho return -ENOSYS; 1746 1.1 pho #define CALL_LSEEK(VER) \ 1747 1.1 pho case VER: \ 1748 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->lseek) \ 1749 1.1 pho return ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->lseek(path, off, whence, fi); \ 1750 1.1 pho else \ 1751 1.1 pho return -ENOSYS 1752 1.1 pho CALL_LSEEK(38); 1753 1.1 pho #undef CALL_LSEEK 1754 1.1 pho default: 1755 1.1 pho UNKNOWN_VERSION(fs->op_version); 1756 1.1 pho } 1757 1.1 pho } 1758 1.1 pho 1759 1.1 pho void 1760 1.1 pho fuse_fs_init_v27(struct fuse_fs *fs, struct fuse_conn_info *conn) { 1761 1.1 pho fuse_fs_init_v30(fs, conn, NULL); 1762 1.1 pho } 1763 1.1 pho 1764 1.1 pho void 1765 1.1 pho fuse_fs_init_v30(struct fuse_fs* fs, struct fuse_conn_info* conn, 1766 1.1 pho struct fuse_config* cfg) { 1767 1.1 pho clobber_context_user_data(fs); 1768 1.1 pho switch (fs->op_version) { 1769 1.1 pho case 11: 1770 1.1 pho case 21: 1771 1.1 pho case 22: 1772 1.1 pho break; 1773 1.1 pho 1774 1.1 pho /* init() appeared on FUSE 2.3 as init(void). */ 1775 1.1 pho #define CALL_NULLARY_INIT(VER) \ 1776 1.1 pho case VER: \ 1777 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init) \ 1778 1.1 pho fs->user_data = ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init(); \ 1779 1.1 pho break 1780 1.1 pho CALL_NULLARY_INIT(23); 1781 1.1 pho CALL_NULLARY_INIT(25); 1782 1.1 pho #undef CALL_NULLARY_INIT 1783 1.1 pho 1784 1.1 pho /* It was changed to init(struct fuse_conn_info*) on FUSE 1785 1.1 pho * 2.6. */ 1786 1.1 pho #define CALL_UNARY_INIT(VER) \ 1787 1.1 pho case VER: \ 1788 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init) \ 1789 1.1 pho fs->user_data = ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init(conn); \ 1790 1.1 pho break 1791 1.1 pho CALL_UNARY_INIT(26); 1792 1.1 pho CALL_UNARY_INIT(28); 1793 1.1 pho CALL_UNARY_INIT(29); 1794 1.1 pho #undef CALL_INIT 1795 1.1 pho 1796 1.1 pho /* It was again changed to init(struct fuse_conn_info*, struct 1797 1.1 pho * fuse_config*) on FUSE 3.0. */ 1798 1.1 pho #define CALL_BINARY_INIT(VER) \ 1799 1.1 pho case VER: \ 1800 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init) \ 1801 1.1 pho fs->user_data = ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->init(conn, cfg); \ 1802 1.1 pho break 1803 1.1 pho CALL_BINARY_INIT(30); 1804 1.1 pho CALL_BINARY_INIT(34); 1805 1.2 pho CALL_BINARY_INIT(35); 1806 1.1 pho CALL_BINARY_INIT(38); 1807 1.1 pho #undef CALL_BINARY_INIT 1808 1.1 pho default: 1809 1.1 pho UNKNOWN_VERSION(fs->op_version); 1810 1.1 pho } 1811 1.1 pho } 1812 1.1 pho 1813 1.1 pho void 1814 1.1 pho fuse_fs_destroy(struct fuse_fs *fs) { 1815 1.1 pho clobber_context_user_data(fs); 1816 1.1 pho switch (fs->op_version) { 1817 1.1 pho /* destroy() appeared on FUSE 2.3. */ 1818 1.1 pho case 11: 1819 1.1 pho case 21: 1820 1.1 pho case 22: 1821 1.1 pho break; 1822 1.1 pho 1823 1.1 pho #define CALL_DESTROY(VER) \ 1824 1.1 pho case VER: \ 1825 1.1 pho if (((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->destroy) \ 1826 1.1 pho ((const struct __CONCAT(fuse_operations_v,VER)*)fs->op)->destroy(fs->user_data); \ 1827 1.1 pho break 1828 1.1 pho CALL_DESTROY(23); 1829 1.1 pho CALL_DESTROY(25); 1830 1.1 pho CALL_DESTROY(26); 1831 1.1 pho CALL_DESTROY(28); 1832 1.1 pho CALL_DESTROY(29); 1833 1.1 pho CALL_DESTROY(30); 1834 1.1 pho CALL_DESTROY(34); 1835 1.2 pho CALL_DESTROY(35); 1836 1.1 pho CALL_DESTROY(38); 1837 1.1 pho #undef CALL_DESTROY 1838 1.1 pho default: 1839 1.1 pho UNKNOWN_VERSION(fs->op_version); 1840 1.1 pho } 1841 1.1 pho 1842 1.1 pho /* fuse_fs_destroy(3) also deallocates struct fuse_fs itself. */ 1843 1.1 pho free(fs->op); 1844 1.1 pho free(fs); 1845 1.1 pho } 1846