1 /* 2 * Copyright (C) Eugene 'Vindex' Stulin, 2023 3 * 4 * Distributed under 5 * the Boost Software License 1.0 or (at your option) 6 * the GNU Lesser General Public License 3.0 or later. 7 * This file is offered as-is, without any warranty. 8 * 9 * This D wrapper was written following some header files 10 * of the FUSE library: https://github.com/libfuse/libfuse 11 */ 12 13 /** 14 * The module contains basic definitions 15 * of functions and structures from *libfuse*. 16 */ 17 18 module oxfuse.fusellw; // low level wrapper 19 pragma(lib, "fuse3"); 20 21 import std.bitmanip : bitfields; 22 23 public import core.sys.posix.sys.stat; 24 public import core.sys.posix.sys.types; 25 public import core.sys.posix.signal : timespec; 26 public import core.sys.posix.sys.statvfs : statvfs_t; 27 public import core.sys.posix.fcntl : flock_t = flock; 28 29 extern(C): 30 31 32 /** Handle for a FUSE filesystem */ 33 struct fuse; 34 35 struct fuse_pollhandle; 36 37 /** 38 * Readdir flags, passed to ->readdir() 39 */ 40 enum fuse_readdir_flags { 41 /** 42 * "Plus" mode. 43 * 44 * The kernel wants to prefill the inode cache during readdir. The 45 * filesystem may honour this by filling in the attributes and setting 46 * FUSE_FILL_DIR_FLAGS for the filler function. The filesystem may also 47 * just ignore this flag completely. 48 */ 49 FUSE_READDIR_PLUS = (1 << 0) 50 } 51 52 enum fuse_fill_dir_flags { 53 /** 54 * "Plus" mode: all file attributes are valid 55 * 56 * The attributes are used by the kernel to prefill the inode cache 57 * during a readdir. 58 * 59 * It is okay to set FUSE_FILL_DIR_PLUS if FUSE_READDIR_PLUS is not set 60 * and vice versa. 61 */ 62 FUSE_FILL_DIR_PLUS = (1 << 1) 63 } 64 65 66 /** Function to add an entry in a readdir() operation 67 * 68 * The *offset* parameter can be any non-zero value that enables the 69 * filesystem to identify the current point in the directory 70 * stream. It does not need to be the actual physical position. A 71 * value of zero is reserved to indicate that seeking in directories 72 * is not supported. 73 * Params: 74 * buf = the buffer passed to the readdir() operation 75 * name = the file name of the directory entry 76 * stbuf = file attributes, can be NULL 77 * offset = offset of the next entry or zero 78 * fill_dir = fill flags 79 * Returns: 80 * 1 if buffer is full, zero otherwise 81 */ 82 alias fuse_fill_dir_t = int function( 83 void* buf, char* name, stat_t* stbuf, off_t offset, int fill_dir 84 ) nothrow @nogc; 85 86 87 /** 88 * Configuration of the high-level API. 89 */ 90 struct fuse_config { 91 /** 92 * If `set_gid` is non-zero, the st_gid attribute of each file 93 * is overwritten with the value of `gid`. 94 */ 95 int set_gid; 96 uint gid; 97 98 /** 99 * If `set_uid` is non-zero, the st_uid attribute of each file 100 * is overwritten with the value of `uid`. 101 */ 102 int set_uid; 103 uint uid; 104 105 /** 106 * If `set_mode` is non-zero, the any permissions bits set in 107 * `umask` are unset in the st_mode attribute of each file. 108 */ 109 int set_mode; 110 uint umask; 111 112 /** 113 * The timeout in seconds for which name lookups will be 114 * cached. 115 */ 116 double entry_timeout; 117 118 /** 119 * The timeout in seconds for which a negative lookup will be 120 * cached. This means, that if file did not exist (lookup 121 * returned ENOENT), the lookup will only be redone after the 122 * timeout, and the file/directory will be assumed to not 123 * exist until then. A value of zero means that negative 124 * lookups are not cached. 125 */ 126 double negative_timeout; 127 128 /** 129 * The timeout in seconds for which file/directory attributes 130 * (as returned by e.g. the `getattr` handler) are cached. 131 */ 132 double attr_timeout; 133 134 /** 135 * Allow requests to be interrupted 136 */ 137 int intr; 138 139 /** 140 * Specify which signal number to send to the filesystem when 141 * a request is interrupted. The default is hardcoded to 142 * USR1. 143 */ 144 int intr_signal; 145 146 /** 147 * Normally, FUSE assigns inodes to paths only for as long as 148 * the kernel is aware of them. With this option inodes are 149 * instead remembered for at least this many seconds. This 150 * will require more memory, but may be necessary when using 151 * applications that make use of inode numbers. 152 * 153 * A number of -1 means that inodes will be remembered for the 154 * entire life-time of the file-system process. 155 */ 156 int remember; 157 158 /** 159 * The default behavior is that if an open file is deleted, 160 * the file is renamed to a hidden file (.fuse_hiddenXXX), and 161 * only removed when the file is finally released. This 162 * relieves the filesystem implementation of having to deal 163 * with this problem. This option disables the hiding 164 * behavior, and files are removed immediately in an unlink 165 * operation (or in a rename operation which overwrites an 166 * existing file). 167 * 168 * It is recommended that you not use the hard_remove 169 * option. When hard_remove is set, the following libc 170 * functions fail on unlinked files (returning errno of 171 * ENOENT): read(2), write(2), fsync(2), close(2), f*xattr(2), 172 * ftruncate(2), fstat(2), fchmod(2), fchown(2) 173 */ 174 int hard_remove; 175 176 /** 177 * Honor the st_ino field in the functions getattr() and 178 * fill_dir(). This value is used to fill in the st_ino field 179 * in the stat(2), lstat(2), fstat(2) functions and the d_ino 180 * field in the readdir(2) function. The filesystem does not 181 * have to guarantee uniqueness, however some applications 182 * rely on this value being unique for the whole filesystem. 183 * 184 * Note that this does *not* affect the inode that libfuse 185 * and the kernel use internally (also called the "nodeid"). 186 */ 187 int use_ino; 188 189 /** 190 * If use_ino option is not given, still try to fill in the 191 * d_ino field in readdir(2). If the name was previously 192 * looked up, and is still in the cache, the inode number 193 * found there will be used. Otherwise it will be set to -1. 194 * If use_ino option is given, this option is ignored. 195 */ 196 int readdir_ino; 197 198 /** 199 * This option disables the use of page cache (file content cache) 200 * in the kernel for this filesystem. This has several affects: 201 * 202 * 1. Each read(2) or write(2) system call will initiate one 203 * or more read or write operations, data will not be 204 * cached in the kernel. 205 * 206 * 2. The return value of the read() and write() system calls 207 * will correspond to the return values of the read and 208 * write operations. This is useful for example if the 209 * file size is not known in advance (before reading it). 210 * 211 * Internally, enabling this option causes fuse to set the 212 * `direct_io` field of `struct fuse_file_info` - overwriting 213 * any value that was put there by the file system. 214 */ 215 int direct_io; 216 217 /** 218 * This option disables flushing the cache of the file 219 * contents on every open(2). This should only be enabled on 220 * filesystems where the file data is never changed 221 * externally (not through the mounted FUSE filesystem). Thus 222 * it is not suitable for network filesystems and other 223 * intermediate filesystems. 224 * 225 * NOTE: if this option is not specified (and neither 226 * direct_io) data is still cached after the open(2), so a 227 * read(2) system call will not always initiate a read 228 * operation. 229 * 230 * Internally, enabling this option causes fuse to set the 231 * `keep_cache` field of `struct fuse_file_info` - overwriting 232 * any value that was put there by the file system. 233 */ 234 int kernel_cache; 235 236 /** 237 * This option is an alternative to `kernel_cache`. Instead of 238 * unconditionally keeping cached data, the cached data is 239 * invalidated on open(2) if if the modification time or the 240 * size of the file has changed since it was last opened. 241 */ 242 int auto_cache; 243 244 /** 245 * The timeout in seconds for which file attributes are cached 246 * for the purpose of checking if auto_cache should flush the 247 * file data on open. 248 */ 249 int ac_attr_timeout_set; 250 double ac_attr_timeout; 251 252 /** 253 * If this option is given the file-system handlers for the 254 * following operations will not receive path information: 255 * read, write, flush, release, fallocate, fsync, readdir, 256 * releasedir, fsyncdir, lock, ioctl and poll. 257 * 258 * For the truncate, getattr, chmod, chown and utimens 259 * operations the path will be provided only if the struct 260 * fuse_file_info argument is NULL. 261 */ 262 int nullpath_ok; 263 264 /** 265 * The remaining options are used by libfuse internally and 266 * should not be touched. 267 */ 268 int show_help; 269 char* modules; 270 int debug_; 271 } 272 273 274 /** 275 * Get the current context 276 * 277 * The context is only valid for the duration of a filesystem 278 * operation, and thus must not be stored and used later. 279 * 280 * Returns: 281 * the context 282 */ 283 fuse_context* fuse_get_context() nothrow @nogc; 284 285 286 /** 287 * The file system operations: 288 * 289 * Most of these should work very similarly to the well known UNIX 290 * file system operations. A major exception is that instead of 291 * returning an error in 'errno', the operation should return the 292 * negated error value (-errno) directly. 293 * 294 * All methods are optional, but some are essential for a useful 295 * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, 296 * releasedir, fsyncdir, access, create, truncate, lock, init and 297 * destroy are special purpose methods, without which a full featured 298 * filesystem can still be implemented. 299 * 300 * In general, all methods are expected to perform any necessary 301 * permission checking. However, a filesystem may delegate this task 302 * to the kernel by passing the `default_permissions` mount option to 303 * `fuse_new()`. In this case, methods will only be called if 304 * the kernel's permission check has succeeded. 305 * 306 * Almost all operations take a path which can be of any length. 307 */ 308 struct fuse_operations { 309 int function(const char*, stat_t*, fuse_file_info* fi) getattr; 310 int function(const char*, char*, size_t) readlink; 311 int function(const char*, mode_t, dev_t) mknod; 312 int function(const char*, mode_t) mkdir; 313 int function(const char*) unlink; 314 int function(const char*) rmdir; 315 int function(const char*, const char*) symlink; 316 int function(const char *, const char *, uint flags) rename; 317 int function(const char*, const char*) link; 318 int function(const char*, mode_t, fuse_file_info* fi) chmod; 319 int function(const char*, uid_t, gid_t, fuse_file_info* fi) chown; 320 int function(const char*, off_t, fuse_file_info* fi) truncate; 321 int function(const char*, fuse_file_info*) open; 322 int function(const char*, ubyte*, size_t, off_t, fuse_file_info*) read; 323 int function(const char*, 324 const ubyte*, 325 size_t, 326 off_t, 327 fuse_file_info*) write; 328 int function(const char*, statvfs_t*) statfs; 329 int function(const char*, fuse_file_info*) flush; 330 int function(const char*, fuse_file_info*) release; 331 int function(const char*, int, fuse_file_info*) fsync; 332 int function(const char*, const char*, const char*, size_t, int) setxattr; 333 int function(const char*, const char*, char*, size_t) getxattr; 334 int function(const char*, char*, size_t) listxattr; 335 int function(const char*, const char*) removexattr; 336 int function(const char*, fuse_file_info*) opendir; 337 int function(const char*, 338 void*, 339 fuse_fill_dir_t filler, 340 off_t, 341 fuse_file_info*, 342 fuse_readdir_flags readdir_flags) readdir; 343 int function(const char*, fuse_file_info*) releasedir; 344 int function(const char*, int, fuse_file_info*) fsyncdir; 345 void* function(fuse_conn_info* conn, fuse_config* cfg) init; 346 void function(void* private_data) destroy; 347 int function(const char*, int) access; 348 int function(const char*, mode_t, fuse_file_info*) create; 349 int function(const char*, fuse_file_info*, int cmd, flock_t*) lock; 350 int function(const char*, 351 ref const timespec[2] tv, 352 fuse_file_info* fi) utimens; 353 int function(const char*, size_t blocksize, ulong* idx) bmap; 354 int function(const char*, 355 uint cmd, 356 void* arg, 357 fuse_file_info*, 358 uint flags, 359 void* data) ioctl; 360 int function(const char*, 361 fuse_file_info*, 362 fuse_pollhandle* ph, 363 uint* reventsp) poll; 364 int function(const char*, 365 fuse_bufvec* buf, 366 off_t off, 367 fuse_file_info*) write_buf; 368 int function(const char*, 369 fuse_bufvec** bufp, 370 size_t size, off_t off, 371 fuse_file_info*) read_buf; 372 int function(const char*, fuse_file_info*, int op) flock; 373 int function(const char*, int, off_t, off_t, fuse_file_info*) fallocate; 374 ssize_t function(const char* path_in, 375 fuse_file_info* fi_in, 376 off_t offset_in, 377 const char* path_out, 378 fuse_file_info* fi_out, 379 off_t offset_out, 380 size_t size, 381 int flags) copy_file_range; 382 off_t function(const char*, off_t off, int whence, fuse_file_info*) lseek; 383 } 384 385 386 /** 387 * Information about an open file. 388 * 389 * File Handles are created by the open, opendir, and create methods and closed 390 * by the release and releasedir methods. Multiple file handles may be 391 * concurrently open for the same file. Generally, a client will create one 392 * file handle per file descriptor, though in some cases multiple file 393 * descriptors can share a single file handle. 394 */ 395 struct fuse_file_info { 396 /** Open flags. Available in open() and release() */ 397 int flags; 398 399 mixin(bitfields!( 400 uint, "writepage", 1, 401 uint, "direct_io", 1, 402 uint, "keep_cache", 1, 403 uint, "flush", 1, 404 uint, "nonseekable", 1, 405 uint, "flock_release", 1, 406 uint, "cache_readdir", 1, 407 uint, "noflush", 1, 408 uint, "padding", 24 409 )); 410 uint padding2; 411 412 /** File handle id. May be filled in by filesystem in create, 413 * open, and opendir(). Available in most other file operations on the 414 * same file handle. */ 415 ulong fh; 416 417 /** Lock owner id. Available in locking operations and flush */ 418 ulong lock_owner; 419 420 /** Requested poll events. Available in ->poll. Only set on kernels 421 which support it. If unsupported, this field is set to zero. */ 422 uint poll_events; 423 } 424 425 426 /** Extra context that may be needed by some filesystems 427 * 428 * The uid, gid and pid fields are not filled in case of a writepage 429 * operation. 430 */ 431 struct fuse_context { 432 .fuse* fuse; /// pointer to the fuse object 433 uid_t uid; /// user ID of the calling process 434 gid_t gid; /// group ID of the calling process 435 pid_t pid; /// process ID of the calling thread 436 void* private_data; /// private filesystem data 437 mode_t umask; /// umask of the calling process 438 } 439 440 441 /** 442 * Connection information, passed to the ->init() method 443 * 444 * Some of the elements are read-write, these can be changed to 445 * indicate the value requested by the filesystem. The requested 446 * value must usually be smaller than the indicated value. 447 */ 448 struct fuse_conn_info { 449 /** 450 * Major version of the protocol (read-only) 451 */ 452 uint proto_major; 453 454 /** 455 * Minor version of the protocol (read-only) 456 */ 457 uint proto_minor; 458 459 /** 460 * Maximum size of the write buffer 461 */ 462 uint max_write; 463 464 /** 465 * Maximum size of read requests. A value of zero indicates no 466 * limit. However, even if the filesystem does not specify a 467 * limit, the maximum size of read requests will still be 468 * limited by the kernel. 469 * 470 * NOTE: For the time being, the maximum size of read requests 471 * must be set both here *and* passed to fuse_session_new() 472 * using the ``-o max_read=<n>`` mount option. At some point 473 * in the future, specifying the mount option will no longer 474 * be necessary. 475 */ 476 uint max_read; 477 478 /** 479 * Maximum readahead 480 */ 481 uint max_readahead; 482 483 /** 484 * Capability flags that the kernel supports (read-only) 485 */ 486 uint capable; 487 488 /** 489 * Capability flags that the filesystem wants to enable. 490 * 491 * libfuse attempts to initialize this field with 492 * reasonable default values before calling the init() handler. 493 */ 494 uint want; 495 496 /** 497 * Maximum number of pending "background" requests. A 498 * background request is any type of request for which the 499 * total number is not limited by other means. As of kernel 500 * 4.8, only two types of requests fall into this category: 501 * 502 * 1. Read-ahead requests 503 * 2. Asynchronous direct I/O requests 504 * 505 * Read-ahead requests are generated (if max_readahead is 506 * non-zero) by the kernel to preemptively fill its caches 507 * when it anticipates that userspace will soon read more 508 * data. 509 * 510 * Asynchronous direct I/O requests are generated if 511 * FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large 512 * direct I/O request. In this case the kernel will internally 513 * split it up into multiple smaller requests and submit them 514 * to the filesystem concurrently. 515 * 516 * Note that the following requests are *not* background 517 * requests: writeback requests (limited by the kernel's 518 * flusher algorithm), regular (i.e., synchronous and 519 * buffered) userspace read/write requests (limited to one per 520 * thread), asynchronous read requests (Linux's io_submit(2) 521 * call actually blocks, so these are also limited to one per 522 * thread). 523 */ 524 uint max_background; 525 526 /** 527 * Kernel congestion threshold parameter. If the number of pending 528 * background requests exceeds this number, the FUSE kernel module will 529 * mark the filesystem as "congested". This instructs the kernel to 530 * expect that queued requests will take some time to complete, and to 531 * adjust its algorithms accordingly (e.g. by putting a waiting thread 532 * to sleep instead of using a busy-loop). 533 */ 534 uint congestion_threshold; 535 536 /** 537 * When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible 538 * for updating mtime and ctime when write requests are received. The 539 * updated values are passed to the filesystem with setattr() requests. 540 * However, if the filesystem does not support the full resolution of 541 * the kernel timestamps (nanoseconds), the mtime and ctime values used 542 * by kernel and filesystem will differ (and result in an apparent 543 * change of times after a cache flush). 544 * 545 * To prevent this problem, this variable can be used to inform the 546 * kernel about the timestamp granularity supported by the file-system. 547 * The value should be power of 10. The default is 1, i.e. full 548 * nano-second resolution. Filesystems supporting only second resolution 549 * should set this to 1000000000. 550 */ 551 uint time_gran; 552 553 /** 554 * For future use. 555 */ 556 uint[22] reserved; 557 } 558 559 560 /** 561 * Data buffer vector 562 * 563 * An array of data buffers, each containing a memory pointer or a 564 * file descriptor. 565 * 566 * Allocate dynamically to add more than one buffer. 567 */ 568 struct fuse_bufvec { 569 size_t count; // number of buffers in the array 570 size_t idx; // index of current buffer within the array 571 size_t off; // current offset within the current buffer 572 fuse_buf[1] buf; /// array of buffers 573 } 574 575 576 /** 577 * Buffer flags 578 */ 579 enum fuse_buf_flags { 580 /** 581 * Buffer contains a file descriptor 582 * 583 * If this flag is set, the .fd field is valid, otherwise the 584 * .mem fields is valid. 585 */ 586 FUSE_BUF_IS_FD = (1 << 1), 587 588 /** 589 * Seek on the file descriptor 590 * 591 * If this flag is set then the .pos field is valid and is 592 * used to seek to the given offset before performing 593 * operation on file descriptor. 594 */ 595 FUSE_BUF_FD_SEEK = (1 << 2), 596 597 /** 598 * Retry operation on file descriptor 599 * 600 * If this flag is set then retry operation on file descriptor 601 * until .size bytes have been copied or an error or EOF is 602 * detected. 603 */ 604 FUSE_BUF_FD_RETRY = (1 << 3) 605 } 606 607 608 /** 609 * Single data buffer 610 * 611 * Generic data buffer for I/O, extended attributes, etc... Data may 612 * be supplied as a memory pointer or as a file descriptor 613 */ 614 struct fuse_buf { 615 size_t size; /// size of data in bytes 616 fuse_buf_flags flags; /// buffer flags 617 void* mem; /// memory pointer; used unless FUSE_BUF_IS_FD flag is set 618 int fd; /// file descriptor; used if FUSE_BUF_IS_FD flag is set 619 off_t pos; /// file position, used if FUSE_BUF_FD_SEEK is set 620 } 621 622 623 /** 624 * Argument list 625 */ 626 struct fuse_args { 627 int argc; /// argument count 628 char **argv; /// argument vector; NULL terminated 629 int allocated; /// is 'argv' allocated? 630 } 631 632 633 /** 634 * Initializer for 'struct fuse_args' 635 */ 636 fuse_args FUSE_ARGS_INIT()(int argc, char** argv) nothrow @nogc { 637 return fuse_args(argc, argv, 0); 638 } 639 640 641 /* ----------------------------------------------------------- * 642 * Filesystem setup & teardown * 643 * ----------------------------------------------------------- */ 644 struct fuse_cmdline_opts { 645 int singlethread; 646 int foreground; 647 int debug_; 648 int nodefault_subtype; 649 char* mountpoint; 650 int show_version; 651 int show_help; 652 int clone_fd; 653 uint max_idle_threads; 654 } 655 656 657 /** 658 * Main function of FUSE. 659 * 660 * This is for the lazy. This is all that has to be called from the 661 * main() function. 662 * 663 * This function does the following: 664 * - parses command line options (-d -s and -h); 665 * - passes relevant mount options to the fuse_mount(); 666 * - installs signal handlers for INT, HUP, TERM and PIPE; 667 * - registers an exit handler to unmount the filesystem on program exit; 668 * - creates a fuse handle; 669 * - registers the operations; 670 * - calls either the single-threaded or the multi-threaded event loop. 671 * 672 * Params: 673 * argc = the argument counter passed to the main() function 674 * argv = the argument vector passed to the main() function 675 * op = the file system operation 676 * userData = user data supplied in the context during the init() method 677 * Returns: 678 * 0 on success, nonzero on failure 679 */ 680 int fuse_main(int argc, char** argv, fuse_operations* op, void* userData) 681 nothrow @nogc { 682 return fuse_main_real(argc, argv, op, fuse_operations.sizeof, userData); 683 } 684 685 private int fuse_main_real( 686 int argc, 687 char** argv, 688 const fuse_operations* op, 689 size_t op_size, 690 void* user_data 691 ) nothrow @nogc; 692 693 694 /** 695 * This function is used to notify that some expected event has occurred. 696 * Calling this function initiates a new poll() call. 697 */ 698 int fuse_notify_poll(fuse_pollhandle* ph) nothrow @nogc; 699 700 /// Destroy poll handle. 701 void fuse_pollhandle_destroy(fuse_pollhandle* ph); 702 703 704 /// Get the version of the library. 705 int fuse_version(); 706 707 708 /// Get the full package version string of the library. 709 const(char)* fuse_pkgversion(); 710