1 /* 2 FUSE: Filesystem in Userspace 3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4 5 This program can be distributed under the terms of the GNU LGPLv2. 6 See the file COPYING.LIB. 7 */ 8 9 module c.fuse.fuse_common; 10 11 public import c.fuse.fuse_opt; 12 13 import core.sys.posix.config; 14 import core.sys.posix.sys.types; 15 16 import std.bitmanip; 17 import std.stdint; 18 19 enum FUSE_MAJOR_VERSION = 2; 20 enum FUSE_MINOR_VERSION = 9; 21 22 auto FUSE_MAKE_VERSION(Maj, Min)(Maj maj, Min min) { return ((maj) * 10 + (min)); } 23 enum FUSE_VERSION = FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION); 24 25 static assert(_FILE_OFFSET_BITS == 64); 26 27 extern (C): 28 29 /** 30 * Information about open files 31 * 32 * Changed in version 2.5 33 */ 34 struct fuse_file_info 35 { 36 /** Open flags. Available in open() and release() */ 37 int flags; 38 39 /** Old file handle, don't use */ 40 c_ulong fh_old; 41 42 /** In case of a write operation indicates if this was caused by a 43 writepage */ 44 int writepage; 45 46 mixin(bitfields!( 47 /** Can be filled in by open, to use direct I/O on this file. 48 Introduced in version 2.4 */ 49 uint, q{direct_io}, 1, 50 51 /** Can be filled in by open, to indicate, that cached file data 52 need not be invalidated. Introduced in version 2.4 */ 53 uint, q{keep_cache}, 1, 54 55 /** Indicates a flush operation. Set in flush operation, also 56 maybe set in highlevel lock operation and lowlevel release 57 operation. Introduced in version 2.6 */ 58 uint, q{flush}, 1, 59 60 /** Can be filled in by open, to indicate that the file is not 61 seekable. Introduced in version 2.8 */ 62 uint, q{nonseekable}, 1, 63 64 /* Indicates that flock locks for this file should be 65 released. If set, lock_owner shall contain a valid value. 66 May only be set in ->release(). Introduced in version 67 2.9 */ 68 uint, q{flock_release}, 1, 69 70 /** Padding. Do not use*/ 71 uint, q{padding}, 27, 72 )); 73 74 /** File handle. May be filled in by filesystem in open(). 75 Available in all other file operations */ 76 uint64_t fh; 77 78 /** Lock owner id. Available in locking operations and flush */ 79 uint64_t lock_owner; 80 } 81 version (D_LP64) 82 static assert(fuse_file_info.sizeof == 40); 83 else 84 static assert(fuse_file_info.sizeof == 32); 85 86 /** 87 * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' 88 * 89 * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests 90 * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking 91 * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag 92 * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." 93 * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB 94 * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations 95 * FUSE_CAP_SPLICE_WRITE: ability to use splice() to write to the fuse device 96 * FUSE_CAP_SPLICE_MOVE: ability to move data to the fuse device with splice() 97 * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device 98 * FUSE_CAP_IOCTL_DIR: ioctl support on directories 99 */ 100 enum FUSE_CAP_ASYNC_READ = (1 << 0); 101 enum FUSE_CAP_POSIX_LOCKS = (1 << 1); 102 enum FUSE_CAP_ATOMIC_O_TRUNC = (1 << 3); 103 enum FUSE_CAP_EXPORT_SUPPORT = (1 << 4); 104 enum FUSE_CAP_BIG_WRITES = (1 << 5); 105 enum FUSE_CAP_DONT_MASK = (1 << 6); 106 enum FUSE_CAP_SPLICE_WRITE = (1 << 7); 107 enum FUSE_CAP_SPLICE_MOVE = (1 << 8); 108 enum FUSE_CAP_SPLICE_READ = (1 << 9); 109 enum FUSE_CAP_FLOCK_LOCKS = (1 << 10); 110 enum FUSE_CAP_IOCTL_DIR = (1 << 11); 111 112 /** 113 * Ioctl flags 114 * 115 * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine 116 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed 117 * FUSE_IOCTL_RETRY: retry with new iovecs 118 * FUSE_IOCTL_DIR: is a directory 119 * 120 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs 121 */ 122 enum FUSE_IOCTL_COMPAT = (1 << 0); 123 enum FUSE_IOCTL_UNRESTRICTED = (1 << 1); 124 enum FUSE_IOCTL_RETRY = (1 << 2); 125 enum FUSE_IOCTL_DIR = (1 << 4); 126 127 enum FUSE_IOCTL_MAX_IOV = 256; 128 129 /** 130 * Connection information, passed to the ->init() method 131 * 132 * Some of the elements are read-write, these can be changed to 133 * indicate the value requested by the filesystem. The requested 134 * value must usually be smaller than the indicated value. 135 */ 136 struct fuse_conn_info 137 { 138 /** 139 * Major version of the protocol (read-only) 140 */ 141 uint proto_major; 142 143 /** 144 * Minor version of the protocol (read-only) 145 */ 146 uint proto_minor; 147 148 /** 149 * Is asynchronous read supported (read-write) 150 */ 151 uint async_read; 152 153 /** 154 * Maximum size of the write buffer 155 */ 156 uint max_write; 157 158 /** 159 * Maximum readahead 160 */ 161 uint max_readahead; 162 163 /** 164 * Capability flags, that the kernel supports 165 */ 166 uint capable; 167 168 /** 169 * Capability flags, that the filesystem wants to enable 170 */ 171 uint want; 172 173 /** 174 * Maximum number of backgrounded requests 175 */ 176 uint max_background; 177 178 /** 179 * Kernel congestion threshold parameter 180 */ 181 uint congestion_threshold; 182 183 /** 184 * For future use. 185 */ 186 uint[23] reserved; 187 } 188 static assert(fuse_conn_info.sizeof == 128); 189 190 struct fuse_session; 191 struct fuse_chan; 192 struct fuse_pollhandle; 193 194 /** 195 * Create a FUSE mountpoint 196 * 197 * Returns a control file descriptor suitable for passing to 198 * fuse_new() 199 * 200 * @param mountpoint the mount point path 201 * @param args argument vector 202 * @return the communication channel on success, NULL on failure 203 */ 204 fuse_chan* fuse_mount(const char* mountpoint, fuse_args *args); 205 206 /** 207 * Umount a FUSE mountpoint 208 * 209 * @param mountpoint the mount point path 210 * @param ch the communication channel 211 */ 212 void fuse_unmount(const char* mountpoint, fuse_chan *ch); 213 214 /** 215 * Parse common options 216 * 217 * The following options are parsed: 218 * 219 * '-f' foreground 220 * '-d' '-odebug' foreground, but keep the debug option 221 * '-s' single threaded 222 * '-h' '--help' help 223 * '-ho' help without header 224 * '-ofsname=..' file system name, if not present, then set to the program 225 * name 226 * 227 * All parameters may be NULL 228 * 229 * @param args argument vector 230 * @param mountpoint the returned mountpoint, should be freed after use 231 * @param multithreaded set to 1 unless the '-s' option is present 232 * @param foreground set to 1 if one of the relevant options is present 233 * @return 0 on success, -1 on failure 234 */ 235 int fuse_parse_cmdline(fuse_args* args, char** mountpoint, 236 int* multithreaded, int* foreground); 237 238 /** 239 * Go into the background 240 * 241 * @param foreground if true, stay in the foreground 242 * @return 0 on success, -1 on failure 243 */ 244 int fuse_daemonize(int foreground); 245 246 /** 247 * Get the version of the library 248 * 249 * @return the version 250 */ 251 int fuse_version(); 252 253 /** 254 * Destroy poll handle 255 * 256 * @param ph the poll handle 257 */ 258 void fuse_pollhandle_destroy(fuse_pollhandle* ph); 259 260 /* ----------------------------------------------------------- * 261 * Data buffer * 262 * ----------------------------------------------------------- */ 263 264 /** 265 * Buffer flags 266 */ 267 enum fuse_buf_flags 268 { 269 /** 270 * Buffer contains a file descriptor 271 * 272 * If this flag is set, the .fd field is valid, otherwise the 273 * .mem fields is valid. 274 */ 275 FUSE_BUF_IS_FD = (1 << 1), 276 277 /** 278 * Seek on the file descriptor 279 * 280 * If this flag is set then the .pos field is valid and is 281 * used to seek to the given offset before performing 282 * operation on file descriptor. 283 */ 284 FUSE_BUF_FD_SEEK = (1 << 2), 285 286 /** 287 * Retry operation on file descriptor 288 * 289 * If this flag is set then retry operation on file descriptor 290 * until .size bytes have been copied or an error or EOF is 291 * detected. 292 */ 293 FUSE_BUF_FD_RETRY = (1 << 3), 294 } 295 enum FUSE_BUF_IS_FD = fuse_buf_flags.FUSE_BUF_IS_FD; 296 enum FUSE_BUF_FD_SEEK = fuse_buf_flags.FUSE_BUF_FD_SEEK; 297 enum FUSE_BUF_FD_RETRY = fuse_buf_flags.FUSE_BUF_FD_RETRY; 298 299 /** 300 * Buffer copy flags 301 */ 302 enum fuse_buf_copy_flags 303 { 304 /** 305 * Don't use splice(2) 306 * 307 * Always fall back to using read and write instead of 308 * splice(2) to copy data from one file descriptor to another. 309 * 310 * If this flag is not set, then only fall back if splice is 311 * unavailable. 312 */ 313 FUSE_BUF_NO_SPLICE = (1 << 1), 314 315 /** 316 * Force splice 317 * 318 * Always use splice(2) to copy data from one file descriptor 319 * to another. If splice is not available, return -EINVAL. 320 */ 321 FUSE_BUF_FORCE_SPLICE = (1 << 2), 322 323 /** 324 * Try to move data with splice. 325 * 326 * If splice is used, try to move pages from the source to the 327 * destination instead of copying. See documentation of 328 * SPLICE_F_MOVE in splice(2) man page. 329 */ 330 FUSE_BUF_SPLICE_MOVE = (1 << 3), 331 332 /** 333 * Don't block on the pipe when copying data with splice 334 * 335 * Makes the operations on the pipe non-blocking (if the pipe 336 * is full or empty). See SPLICE_F_NONBLOCK in the splice(2) 337 * man page. 338 */ 339 FUSE_BUF_SPLICE_NONBLOCK= (1 << 4), 340 } 341 enum FUSE_BUF_NO_SPLICE = fuse_buf_copy_flags.FUSE_BUF_NO_SPLICE; 342 enum FUSE_BUF_FORCE_SPLICE = fuse_buf_copy_flags.FUSE_BUF_FORCE_SPLICE; 343 enum FUSE_BUF_SPLICE_MOVE = fuse_buf_copy_flags.FUSE_BUF_SPLICE_MOVE; 344 enum FUSE_BUF_SPLICE_NONBLOCK = fuse_buf_copy_flags.FUSE_BUF_SPLICE_NONBLOCK; 345 346 /** 347 * Single data buffer 348 * 349 * Generic data buffer for I/O, extended attributes, etc... Data may 350 * be supplied as a memory pointer or as a file descriptor 351 */ 352 struct fuse_buf 353 { 354 /** 355 * Size of data in bytes 356 */ 357 size_t size; 358 359 /** 360 * Buffer flags 361 */ 362 fuse_buf_flags flags; 363 364 /** 365 * Memory pointer 366 * 367 * Used unless FUSE_BUF_IS_FD flag is set. 368 */ 369 void* mem; 370 371 /** 372 * File descriptor 373 * 374 * Used if FUSE_BUF_IS_FD flag is set. 375 */ 376 int fd; 377 378 /** 379 * File position 380 * 381 * Used if FUSE_BUF_FD_SEEK flag is set. 382 */ 383 off_t pos; 384 } 385 386 /** 387 * Data buffer vector 388 * 389 * An array of data buffers, each containing a memory pointer or a 390 * file descriptor. 391 * 392 * Allocate dynamically to add more than one buffer. 393 */ 394 struct fuse_bufvec 395 { 396 /** 397 * Number of buffers in the array 398 */ 399 size_t count; 400 401 /** 402 * Index of current buffer within the array 403 */ 404 size_t idx; 405 406 /** 407 * Current offset within the current buffer 408 */ 409 size_t off; 410 411 /** 412 * Array of buffers 413 */ 414 fuse_buf[1] buf; 415 } 416 417 /* Initialize bufvec with a single buffer of given size */ 418 fuse_bufvec FUSE_BUFVEC_INIT()(size_t size__) 419 { 420 fuse_bufvec result = { 421 /* .count= */ 1, 422 /* .idx = */ 0, 423 /* .off = */ 0, 424 /* .buf = */ [ /* [0] = */ { 425 /* .size = */ (size__), 426 /* .flags = */ cast(fuse_buf_flags) 0, 427 /* .mem = */ null, 428 /* .fd = */ -1, 429 /* .pos = */ 0, 430 } ] 431 }; 432 return result; 433 } 434 435 /** 436 * Get total size of data in a fuse buffer vector 437 * 438 * @param bufv buffer vector 439 * @return size of data 440 */ 441 size_t fuse_buf_size(const fuse_bufvec* bufv); 442 443 /** 444 * Copy data from one buffer vector to another 445 * 446 * @param dst destination buffer vector 447 * @param src source buffer vector 448 * @param flags flags controlling the copy 449 * @return actual number of bytes copied or -errno on error 450 */ 451 ssize_t fuse_buf_copy(fuse_bufvec* dst, fuse_bufvec* src, 452 fuse_buf_copy_flags flags); 453 454 /* ----------------------------------------------------------- * 455 * Signal handling * 456 * ----------------------------------------------------------- */ 457 458 /** 459 * Exit session on HUP, TERM and INT signals and ignore PIPE signal 460 * 461 * Stores session in a global variable. May only be called once per 462 * process until fuse_remove_signal_handlers() is called. 463 * 464 * @param se the session to exit 465 * @return 0 on success, -1 on failure 466 */ 467 int fuse_set_signal_handlers(fuse_session* se); 468 469 /** 470 * Restore default signal handlers 471 * 472 * Resets global session. After this fuse_set_signal_handlers() may 473 * be called again. 474 * 475 * @param se the same session as given in fuse_set_signal_handlers() 476 */ 477 void fuse_remove_signal_handlers(fuse_session* se); 478 479 /* ----------------------------------------------------------- * 480 * Compatibility stuff * 481 * ----------------------------------------------------------- */ 482 483 /// See FuseCompat in fuse.d. 484 mixin template FuseCommonCompat(uint FUSE_USE_VERSION = default_FUSE_USE_VERSION) 485 { 486 import c.fuse.fuse; 487 static if (FUSE_USE_VERSION < 26) 488 { 489 version (FreeBSD) 490 { 491 static if (FUSE_USE_VERSION < 25) 492 static assert(false, "On FreeBSD API version 25 or greater must be used"); 493 } 494 import c.fuse.fuse_common_compat; 495 alias fuse_unmount = fuse_unmount_compat22; 496 static if (FUSE_USE_VERSION == 25) 497 { 498 enum FUSE_MINOR_VERSION = 5; 499 alias fuse_mount = fuse_mount_compat25; 500 } 501 else static if (FUSE_USE_VERSION == 24 || FUSE_USE_VERSION == 22) 502 { 503 enum FUSE_MINOR_VERSION = 4; 504 alias fuse_mount = fuse_mount_compat22; 505 } 506 else static if (FUSE_USE_VERSION == 21) 507 { 508 enum FUSE_MINOR_VERSION = 1; 509 alias fuse_mount = fuse_mount_compat22; 510 } 511 else static if (FUSE_USE_VERSION == 11) 512 { 513 pragma(msg, "Compatibility with API version 11 is deprecated"); 514 enum FUSE_MAJOR_VERSION = 1; 515 enum FUSE_MINOR_VERSION = 1; 516 alias fuse_mount = fuse_mount_compat1; 517 } 518 else 519 static assert(false, "Compatibility with API version other than 21, 22, 24, 25 and 11 not supported"); 520 } 521 } 522 523 enum default_FUSE_USE_VERSION = 21;