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