1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::mem; 6 7 use bitflags::bitflags; 8 use enumn::N; 9 use zerocopy::AsBytes; 10 use zerocopy::FromBytes; 11 use zerocopy::FromZeroes; 12 13 /// Version number of this interface. 14 pub const KERNEL_VERSION: u32 = 7; 15 16 /// Oldest supported minor version of the fuse interface. 17 pub const OLDEST_SUPPORTED_KERNEL_MINOR_VERSION: u32 = 27; 18 19 /// Minor version number of this interface. 20 pub const KERNEL_MINOR_VERSION: u32 = 31; 21 22 /// The ID of the inode corresponding to the root directory of the file system. 23 pub const ROOT_ID: u64 = 1; 24 25 // Bitmasks for `fuse_setattr_in.valid`. 26 const FATTR_MODE: u32 = 1; 27 const FATTR_UID: u32 = 2; 28 const FATTR_GID: u32 = 4; 29 const FATTR_SIZE: u32 = 8; 30 const FATTR_ATIME: u32 = 16; 31 const FATTR_MTIME: u32 = 32; 32 pub const FATTR_FH: u32 = 64; 33 const FATTR_ATIME_NOW: u32 = 128; 34 const FATTR_MTIME_NOW: u32 = 256; 35 pub const FATTR_LOCKOWNER: u32 = 512; 36 const FATTR_CTIME: u32 = 1024; 37 38 bitflags! { 39 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 40 #[repr(transparent)] 41 pub struct SetattrValid: u32 { 42 const MODE = FATTR_MODE; 43 const UID = FATTR_UID; 44 const GID = FATTR_GID; 45 const SIZE = FATTR_SIZE; 46 const ATIME = FATTR_ATIME; 47 const MTIME = FATTR_MTIME; 48 const ATIME_NOW = FATTR_ATIME_NOW; 49 const MTIME_NOW = FATTR_MTIME_NOW; 50 const CTIME = FATTR_CTIME; 51 } 52 } 53 54 // Flags returned by the OPEN request. 55 56 /// Bypass page cache for this open file. 57 const FOPEN_DIRECT_IO: u32 = 1 << 0; 58 59 /// Don't invalidate the data cache on open. 60 const FOPEN_KEEP_CACHE: u32 = 1 << 1; 61 62 /// The file is not seekable. 63 const FOPEN_NONSEEKABLE: u32 = 1 << 2; 64 65 /// Allow caching the directory entries. 66 const FOPEN_CACHE_DIR: u32 = 1 << 3; 67 68 /// This file is stream-like (i.e., no file position). 69 const FOPEN_STREAM: u32 = 1 << 4; 70 71 /// New file was created in atomic open 72 const FOPEN_FILE_CREATED: u32 = 1 << 7; 73 74 bitflags! { 75 /// Options controlling the behavior of files opened by the server in response 76 /// to an open or create request. 77 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 78 #[repr(transparent)] 79 pub struct OpenOptions: u32 { 80 const DIRECT_IO = FOPEN_DIRECT_IO; 81 const KEEP_CACHE = FOPEN_KEEP_CACHE; 82 const NONSEEKABLE = FOPEN_NONSEEKABLE; 83 const CACHE_DIR = FOPEN_CACHE_DIR; 84 const STREAM = FOPEN_STREAM; 85 const FILE_CREATED = FOPEN_FILE_CREATED; 86 } 87 } 88 89 // INIT request/reply flags. 90 91 /// Asynchronous read requests. 92 const ASYNC_READ: u64 = 1; 93 94 /// Remote locking for POSIX file locks. 95 const POSIX_LOCKS: u64 = 2; 96 97 /// Kernel sends file handle for fstat, etc... (not yet supported). 98 const FILE_OPS: u64 = 4; 99 100 /// Handles the O_TRUNC open flag in the filesystem. 101 const ATOMIC_O_TRUNC: u64 = 8; 102 103 /// FileSystem handles lookups of "." and "..". 104 const EXPORT_SUPPORT: u64 = 16; 105 106 /// FileSystem can handle write size larger than 4kB. 107 const BIG_WRITES: u64 = 32; 108 109 /// Don't apply umask to file mode on create operations. 110 const DONT_MASK: u64 = 64; 111 112 /// Kernel supports splice write on the device. 113 const SPLICE_WRITE: u64 = 128; 114 115 /// Kernel supports splice move on the device. 116 const SPLICE_MOVE: u64 = 256; 117 118 /// Kernel supports splice read on the device. 119 const SPLICE_READ: u64 = 512; 120 121 /// Remote locking for BSD style file locks. 122 const FLOCK_LOCKS: u64 = 1024; 123 124 /// Kernel supports ioctl on directories. 125 const HAS_IOCTL_DIR: u64 = 2048; 126 127 /// Automatically invalidate cached pages. 128 const AUTO_INVAL_DATA: u64 = 4096; 129 130 /// Do READDIRPLUS (READDIR+LOOKUP in one). 131 const DO_READDIRPLUS: u64 = 8192; 132 133 /// Adaptive readdirplus. 134 const READDIRPLUS_AUTO: u64 = 16384; 135 136 /// Asynchronous direct I/O submission. 137 const ASYNC_DIO: u64 = 32768; 138 139 /// Use writeback cache for buffered writes. 140 const WRITEBACK_CACHE: u64 = 65536; 141 142 /// Kernel supports zero-message opens. 143 const NO_OPEN_SUPPORT: u64 = 131072; 144 145 /// Allow parallel lookups and readdir. 146 const PARALLEL_DIROPS: u64 = 262144; 147 148 /// Fs handles killing suid/sgid/cap on write/chown/trunc. 149 const HANDLE_KILLPRIV: u64 = 524288; 150 151 /// FileSystem supports posix acls. 152 const POSIX_ACL: u64 = 1048576; 153 154 /// Reading the device after an abort returns `ECONNABORTED`. 155 const ABORT_ERROR: u64 = 2097152; 156 157 /// The reply to the `init` message contains the max number of request pages. 158 const MAX_PAGES: u64 = 4194304; 159 160 /// Cache `readlink` responses. 161 const CACHE_SYMLINKS: u64 = 8388608; 162 163 /// Kernel supports zero-message opens for directories. 164 const NO_OPENDIR_SUPPORT: u64 = 16777216; 165 166 /// Kernel supports explicit cache invalidation. 167 const EXPLICIT_INVAL_DATA: u64 = 33554432; 168 169 /// The `map_alignment` field of the `InitOut` struct is valid. 170 const MAP_ALIGNMENT: u64 = 67108864; 171 172 /// Extended fuse_init_in request to hold additional flags 173 const INIT_EXT: u64 = 1073741824; 174 175 /// The client should send the security context along with open, mkdir, create, and symlink 176 /// requests. 177 const SECURITY_CONTEXT: u64 = 4294967296; 178 179 bitflags! { 180 /// A bitfield passed in as a parameter to and returned from the `init` method of the 181 /// `FileSystem` trait. 182 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 183 #[repr(transparent)] 184 pub struct FsOptions: u64 { 185 /// Indicates that the filesystem supports asynchronous read requests. 186 /// 187 /// If this capability is not requested/available, the kernel will ensure that there is at 188 /// most one pending read request per file-handle at any time, and will attempt to order 189 /// read requests by increasing offset. 190 /// 191 /// This feature is enabled by default when supported by the kernel. 192 const ASYNC_READ = ASYNC_READ; 193 194 /// Indicates that the filesystem supports "remote" locking. 195 /// 196 /// This feature is not enabled by default and should only be set if the filesystem 197 /// implements the `getlk` and `setlk` methods of the `FileSystem` trait. 198 const POSIX_LOCKS = POSIX_LOCKS; 199 200 /// Kernel sends file handle for fstat, etc... (not yet supported). 201 const FILE_OPS = FILE_OPS; 202 203 /// Indicates that the filesystem supports the `O_TRUNC` open flag. If disabled, and an 204 /// application specifies `O_TRUNC`, fuse first calls `setattr` to truncate the file and 205 /// then calls `open` with `O_TRUNC` filtered out. 206 /// 207 /// This feature is enabled by default when supported by the kernel. 208 const ATOMIC_O_TRUNC = ATOMIC_O_TRUNC; 209 210 /// Indicates that the filesystem supports lookups of "." and "..". 211 /// 212 /// This feature is disabled by default. 213 const EXPORT_SUPPORT = EXPORT_SUPPORT; 214 215 /// FileSystem can handle write size larger than 4kB. 216 const BIG_WRITES = BIG_WRITES; 217 218 /// Indicates that the kernel should not apply the umask to the file mode on create 219 /// operations. 220 /// 221 /// This feature is disabled by default. 222 const DONT_MASK = DONT_MASK; 223 224 /// Indicates that the server should try to use `splice(2)` when writing to the fuse device. 225 /// This may improve performance. 226 /// 227 /// This feature is not currently supported. 228 const SPLICE_WRITE = SPLICE_WRITE; 229 230 /// Indicates that the server should try to move pages instead of copying when writing to / 231 /// reading from the fuse device. This may improve performance. 232 /// 233 /// This feature is not currently supported. 234 const SPLICE_MOVE = SPLICE_MOVE; 235 236 /// Indicates that the server should try to use `splice(2)` when reading from the fuse 237 /// device. This may improve performance. 238 /// 239 /// This feature is not currently supported. 240 const SPLICE_READ = SPLICE_READ; 241 242 /// If set, then calls to `flock` will be emulated using POSIX locks and must 243 /// then be handled by the filesystem's `setlock()` handler. 244 /// 245 /// If not set, `flock` calls will be handled by the FUSE kernel module internally (so any 246 /// access that does not go through the kernel cannot be taken into account). 247 /// 248 /// This feature is disabled by default. 249 const FLOCK_LOCKS = FLOCK_LOCKS; 250 251 /// Indicates that the filesystem supports ioctl's on directories. 252 /// 253 /// This feature is enabled by default when supported by the kernel. 254 const HAS_IOCTL_DIR = HAS_IOCTL_DIR; 255 256 /// Traditionally, while a file is open the FUSE kernel module only asks the filesystem for 257 /// an update of the file's attributes when a client attempts to read beyond EOF. This is 258 /// unsuitable for e.g. network filesystems, where the file contents may change without the 259 /// kernel knowing about it. 260 /// 261 /// If this flag is set, FUSE will check the validity of the attributes on every read. If 262 /// the attributes are no longer valid (i.e., if the *attribute* timeout has expired) then 263 /// FUSE will first send another `getattr` request. If the new mtime differs from the 264 /// previous value, any cached file *contents* will be invalidated as well. 265 /// 266 /// This flag should always be set when available. If all file changes go through the 267 /// kernel, *attribute* validity should be set to a very large number to avoid unnecessary 268 /// `getattr()` calls. 269 /// 270 /// This feature is enabled by default when supported by the kernel. 271 const AUTO_INVAL_DATA = AUTO_INVAL_DATA; 272 273 /// Indicates that the filesystem supports readdirplus. 274 /// 275 /// The feature is not enabled by default and should only be set if the filesystem 276 /// implements the `readdirplus` method of the `FileSystem` trait. 277 const DO_READDIRPLUS = DO_READDIRPLUS; 278 279 /// Indicates that the filesystem supports adaptive readdirplus. 280 /// 281 /// If `DO_READDIRPLUS` is not set, this flag has no effect. 282 /// 283 /// If `DO_READDIRPLUS` is set and this flag is not set, the kernel will always issue 284 /// `readdirplus()` requests to retrieve directory contents. 285 /// 286 /// If `DO_READDIRPLUS` is set and this flag is set, the kernel will issue both `readdir()` 287 /// and `readdirplus()` requests, depending on how much information is expected to be 288 /// required. 289 /// 290 /// This feature is not enabled by default and should only be set if the file system 291 /// implements both the `readdir` and `readdirplus` methods of the `FileSystem` trait. 292 const READDIRPLUS_AUTO = READDIRPLUS_AUTO; 293 294 /// Indicates that the filesystem supports asynchronous direct I/O submission. 295 /// 296 /// If this capability is not requested/available, the kernel will ensure that there is at 297 /// most one pending read and one pending write request per direct I/O file-handle at any 298 /// time. 299 /// 300 /// This feature is enabled by default when supported by the kernel. 301 const ASYNC_DIO = ASYNC_DIO; 302 303 /// Indicates that writeback caching should be enabled. This means that individual write 304 /// request may be buffered and merged in the kernel before they are sent to the file 305 /// system. 306 /// 307 /// This feature is disabled by default. 308 const WRITEBACK_CACHE = WRITEBACK_CACHE; 309 310 /// Indicates support for zero-message opens. If this flag is set in the `capable` parameter 311 /// of the `init` trait method, then the file system may return `ENOSYS` from the open() handler 312 /// to indicate success. Further attempts to open files will be handled in the kernel. (If 313 /// this flag is not set, returning ENOSYS will be treated as an error and signaled to the 314 /// caller). 315 /// 316 /// Setting (or not setting) the field in the `FsOptions` returned from the `init` method 317 /// has no effect. 318 const ZERO_MESSAGE_OPEN = NO_OPEN_SUPPORT; 319 320 /// Indicates support for parallel directory operations. If this flag is unset, the FUSE 321 /// kernel module will ensure that lookup() and readdir() requests are never issued 322 /// concurrently for the same directory. 323 /// 324 /// This feature is enabled by default when supported by the kernel. 325 const PARALLEL_DIROPS = PARALLEL_DIROPS; 326 327 /// Indicates that the file system is responsible for unsetting setuid and setgid bits when a 328 /// file is written, truncated, or its owner is changed. 329 /// 330 /// This feature is enabled by default when supported by the kernel. 331 const HANDLE_KILLPRIV = HANDLE_KILLPRIV; 332 333 /// Indicates support for POSIX ACLs. 334 /// 335 /// If this feature is enabled, the kernel will cache and have responsibility for enforcing 336 /// ACLs. ACL will be stored as xattrs and passed to userspace, which is responsible for 337 /// updating the ACLs in the filesystem, keeping the file mode in sync with the ACL, and 338 /// ensuring inheritance of default ACLs when new filesystem nodes are created. Note that 339 /// this requires that the file system is able to parse and interpret the xattr 340 /// representation of ACLs. 341 /// 342 /// Enabling this feature implicitly turns on the `default_permissions` mount option (even 343 /// if it was not passed to mount(2)). 344 /// 345 /// This feature is disabled by default. 346 const POSIX_ACL = POSIX_ACL; 347 348 /// Indicates that the kernel may cache responses to `readlink` calls. 349 const CACHE_SYMLINKS = CACHE_SYMLINKS; 350 351 /// Indicates support for zero-message opens for directories. If this flag is set in the 352 /// `capable` parameter of the `init` trait method, then the file system may return `ENOSYS` 353 /// from the opendir() handler to indicate success. Further attempts to open directories 354 /// will be handled in the kernel. (If this flag is not set, returning ENOSYS will be 355 /// treated as an error and signaled to the caller). 356 /// 357 /// Setting (or not setting) the field in the `FsOptions` returned from the `init` method 358 /// has no effect. 359 const ZERO_MESSAGE_OPENDIR = NO_OPENDIR_SUPPORT; 360 361 /// Indicates support for invalidating cached pages only on explicit request. 362 /// 363 /// If this flag is set in the `capable` parameter of the `init` trait method, then the FUSE 364 /// kernel module supports invalidating cached pages only on explicit request by the 365 /// filesystem. 366 /// 367 /// By setting this flag in the return value of the `init` trait method, the filesystem is 368 /// responsible for invalidating cached pages through explicit requests to the kernel. 369 /// 370 /// Note that setting this flag does not prevent the cached pages from being flushed by OS 371 /// itself and/or through user actions. 372 /// 373 /// Note that if both EXPLICIT_INVAL_DATA and AUTO_INVAL_DATA are set in the `capable` 374 /// parameter of the `init` trait method then AUTO_INVAL_DATA takes precedence. 375 /// 376 /// This feature is disabled by default. 377 const EXPLICIT_INVAL_DATA = EXPLICIT_INVAL_DATA; 378 379 /// Indicates that the `map_alignment` field of the `InitOut` struct is valid. 380 /// 381 /// The `MAP_ALIGNMENT` field is used by the FUSE kernel driver to ensure that its DAX 382 /// mapping requests are pagesize-aligned. This field automatically set by the server and 383 /// this feature is enabled by default. 384 const MAP_ALIGNMENT = MAP_ALIGNMENT; 385 386 /// Indicates that the `max_pages` field of the `InitOut` struct is valid. 387 /// 388 /// This field is used by the kernel driver to determine the maximum number of pages that 389 /// may be used for any read or write requests. 390 const MAX_PAGES = MAX_PAGES; 391 392 /// Indicates that `InitIn`/`InitOut` struct is extended to hold additional flags. 393 const INIT_EXT = INIT_EXT; 394 395 /// Indicates support for sending the security context with creation requests. 396 const SECURITY_CONTEXT = SECURITY_CONTEXT; 397 } 398 } 399 400 // Release flags. 401 pub const RELEASE_FLUSH: u32 = 1; 402 pub const RELEASE_FLOCK_UNLOCK: u32 = 2; 403 404 // Getattr flags. 405 pub const GETATTR_FH: u32 = 1; 406 407 // Lock flags. 408 pub const LK_FLOCK: u32 = 1; 409 410 // Write flags. 411 412 /// Delayed write from page cache, file handle is guessed. 413 pub const WRITE_CACHE: u32 = 1; 414 415 /// `lock_owner` field is valid. 416 pub const WRITE_LOCKOWNER: u32 = 2; 417 418 /// Kill the suid and sgid bits. 419 pub const WRITE_KILL_PRIV: u32 = 3; 420 421 // Read flags. 422 pub const READ_LOCKOWNER: u32 = 2; 423 424 // Ioctl flags. 425 426 /// 32bit compat ioctl on 64bit machine 427 const IOCTL_COMPAT: u32 = 1; 428 429 /// Not restricted to well-formed ioctls, retry allowed 430 const IOCTL_UNRESTRICTED: u32 = 2; 431 432 /// Retry with new iovecs 433 const IOCTL_RETRY: u32 = 4; 434 435 /// 32bit ioctl 436 const IOCTL_32BIT: u32 = 8; 437 438 /// Is a directory 439 const IOCTL_DIR: u32 = 16; 440 441 /// 32-bit compat ioctl on 64-bit machine with 64-bit time_t. 442 const IOCTL_COMPAT_X32: u32 = 32; 443 444 /// Maximum of in_iovecs + out_iovecs 445 pub const IOCTL_MAX_IOV: usize = 256; 446 447 bitflags! { 448 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 449 #[repr(transparent)] 450 pub struct IoctlFlags: u32 { 451 /// 32bit compat ioctl on 64bit machine 452 const COMPAT = IOCTL_COMPAT; 453 454 /// Not restricted to well-formed ioctls, retry allowed 455 const UNRESTRICTED = IOCTL_UNRESTRICTED; 456 457 /// Retry with new iovecs 458 const RETRY = IOCTL_RETRY; 459 460 /// 32bit ioctl 461 const IOCTL_32BIT = IOCTL_32BIT; 462 463 /// Is a directory 464 const DIR = IOCTL_DIR; 465 466 /// 32-bit compat ioctl on 64-bit machine with 64-bit time_t. 467 const COMPAT_X32 = IOCTL_COMPAT_X32; 468 } 469 } 470 471 /// Request poll notify. 472 pub const POLL_SCHEDULE_NOTIFY: u32 = 1; 473 474 /// The read buffer is required to be at least 8k, but may be much larger. 475 pub const FUSE_MIN_READ_BUFFER: u32 = 8192; 476 477 pub const FUSE_COMPAT_ENTRY_OUT_SIZE: u32 = 120; 478 pub const FUSE_COMPAT_ATTR_OUT_SIZE: u32 = 96; 479 pub const FUSE_COMPAT_MKNOD_IN_SIZE: u32 = 8; 480 pub const FUSE_COMPAT_WRITE_IN_SIZE: u32 = 24; 481 pub const FUSE_COMPAT_STATFS_SIZE: u32 = 48; 482 pub const FUSE_COMPAT_INIT_OUT_SIZE: u32 = 8; 483 pub const FUSE_COMPAT_22_INIT_OUT_SIZE: u32 = 24; 484 485 const SETUPMAPPING_FLAG_WRITE: u64 = 1; 486 const SETUPMAPPING_FLAG_READ: u64 = 2; 487 488 bitflags! { 489 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 490 #[repr(transparent)] 491 pub struct SetUpMappingFlags: u64 { 492 /// Create writable mapping. 493 const WRITE = SETUPMAPPING_FLAG_WRITE; 494 /// Create readable mapping. 495 const READ = SETUPMAPPING_FLAG_READ; 496 } 497 } 498 499 // Request Extension Constants 500 /// Maximum security contexts in a request 501 pub const MAX_NR_SECCTX: u32 = 31; 502 503 #[repr(C)] 504 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 505 pub struct Attr { 506 pub ino: u64, 507 pub size: u64, 508 pub blocks: u64, 509 pub atime: u64, 510 pub mtime: u64, 511 pub ctime: u64, 512 pub atimensec: u32, 513 pub mtimensec: u32, 514 pub ctimensec: u32, 515 pub mode: u32, 516 pub nlink: u32, 517 pub uid: u32, 518 pub gid: u32, 519 pub rdev: u32, 520 pub blksize: u32, 521 pub padding: u32, 522 } 523 524 impl From<libc::stat64> for Attr { from(st: libc::stat64) -> Attr525 fn from(st: libc::stat64) -> Attr { 526 Attr { 527 ino: st.st_ino, 528 size: st.st_size as u64, 529 blocks: st.st_blocks as u64, 530 atime: st.st_atime as u64, 531 mtime: st.st_mtime as u64, 532 ctime: st.st_ctime as u64, 533 atimensec: st.st_atime_nsec as u32, 534 mtimensec: st.st_mtime_nsec as u32, 535 ctimensec: st.st_ctime_nsec as u32, 536 mode: st.st_mode, 537 #[allow(clippy::unnecessary_cast)] 538 nlink: st.st_nlink as u32, 539 uid: st.st_uid, 540 gid: st.st_gid, 541 rdev: st.st_rdev as u32, 542 blksize: st.st_blksize as u32, 543 ..Default::default() 544 } 545 } 546 } 547 548 #[repr(C)] 549 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 550 pub struct Kstatfs { 551 pub blocks: u64, 552 pub bfree: u64, 553 pub bavail: u64, 554 pub files: u64, 555 pub ffree: u64, 556 pub bsize: u32, 557 pub namelen: u32, 558 pub frsize: u32, 559 pub padding: u32, 560 pub spare: [u32; 6], 561 } 562 563 impl From<libc::statvfs64> for Kstatfs { 564 #[allow(clippy::unnecessary_cast)] from(st: libc::statvfs64) -> Self565 fn from(st: libc::statvfs64) -> Self { 566 Kstatfs { 567 blocks: st.f_blocks, 568 bfree: st.f_bfree, 569 bavail: st.f_bavail, 570 files: st.f_files, 571 ffree: st.f_ffree, 572 bsize: st.f_bsize as u32, 573 namelen: st.f_namemax as u32, 574 frsize: st.f_frsize as u32, 575 ..Default::default() 576 } 577 } 578 } 579 580 #[repr(C)] 581 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 582 pub struct FileLock { 583 pub start: u64, 584 pub end: u64, 585 pub type_: u32, 586 pub pid: u32, /* tgid */ 587 } 588 589 #[repr(u32)] 590 #[derive(Debug, Copy, Clone, N, AsBytes)] 591 pub enum Opcode { 592 Lookup = 1, 593 Forget = 2, /* No Reply */ 594 Getattr = 3, 595 Setattr = 4, 596 Readlink = 5, 597 Symlink = 6, 598 Mknod = 8, 599 Mkdir = 9, 600 Unlink = 10, 601 Rmdir = 11, 602 Rename = 12, 603 Link = 13, 604 Open = 14, 605 Read = 15, 606 Write = 16, 607 Statfs = 17, 608 Release = 18, 609 Fsync = 20, 610 Setxattr = 21, 611 Getxattr = 22, 612 Listxattr = 23, 613 Removexattr = 24, 614 Flush = 25, 615 Init = 26, 616 Opendir = 27, 617 Readdir = 28, 618 Releasedir = 29, 619 Fsyncdir = 30, 620 Getlk = 31, 621 Setlk = 32, 622 Setlkw = 33, 623 Access = 34, 624 Create = 35, 625 Interrupt = 36, 626 Bmap = 37, 627 Destroy = 38, 628 Ioctl = 39, 629 Poll = 40, 630 NotifyReply = 41, 631 BatchForget = 42, 632 Fallocate = 43, 633 Readdirplus = 44, 634 Rename2 = 45, 635 Lseek = 46, 636 CopyFileRange = 47, 637 SetUpMapping = 48, 638 RemoveMapping = 49, 639 // TODO(b/310102543): Update the opcode keep same with kernel patch after the atomic open 640 // kernel is merged to upstream. 641 OpenAtomic = u32::MAX - 1, 642 ChromeOsTmpfile = u32::MAX, 643 } 644 645 #[repr(u32)] 646 #[derive(Debug, Copy, Clone, N)] 647 pub enum NotifyOpcode { 648 Poll = 1, 649 InvalInode = 2, 650 InvalEntry = 3, 651 Store = 4, 652 Retrieve = 5, 653 Delete = 6, 654 CodeMax = 7, 655 } 656 657 #[repr(C)] 658 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 659 pub struct EntryOut { 660 pub nodeid: u64, /* Inode ID */ 661 pub generation: u64, /* Inode generation: nodeid:gen must be unique for the fs's lifetime */ 662 pub entry_valid: u64, /* Cache timeout for the name */ 663 pub attr_valid: u64, /* Cache timeout for the attributes */ 664 pub entry_valid_nsec: u32, 665 pub attr_valid_nsec: u32, 666 pub attr: Attr, 667 } 668 669 #[repr(C)] 670 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 671 pub struct ForgetIn { 672 pub nlookup: u64, 673 } 674 675 #[repr(C)] 676 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 677 pub struct ForgetOne { 678 pub nodeid: u64, 679 pub nlookup: u64, 680 } 681 682 #[repr(C)] 683 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 684 pub struct BatchForgetIn { 685 pub count: u32, 686 pub dummy: u32, 687 } 688 689 #[repr(C)] 690 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 691 pub struct GetattrIn { 692 pub flags: u32, 693 pub dummy: u32, 694 pub fh: u64, 695 } 696 697 #[repr(C)] 698 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 699 pub struct AttrOut { 700 pub attr_valid: u64, /* Cache timeout for the attributes */ 701 pub attr_valid_nsec: u32, 702 pub dummy: u32, 703 pub attr: Attr, 704 } 705 706 #[repr(C)] 707 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 708 pub struct MknodIn { 709 pub mode: u32, 710 pub rdev: u32, 711 pub umask: u32, 712 pub padding: u32, 713 } 714 715 #[repr(C)] 716 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 717 pub struct MkdirIn { 718 pub mode: u32, 719 pub umask: u32, 720 } 721 722 #[repr(C)] 723 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 724 pub struct ChromeOsTmpfileIn { 725 pub mode: u32, 726 pub umask: u32, 727 } 728 729 #[repr(C)] 730 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 731 pub struct RenameIn { 732 pub newdir: u64, 733 } 734 735 #[repr(C)] 736 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 737 pub struct Rename2In { 738 pub newdir: u64, 739 pub flags: u32, 740 pub padding: u32, 741 } 742 743 #[repr(C)] 744 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 745 pub struct LinkIn { 746 pub oldnodeid: u64, 747 } 748 749 #[repr(C)] 750 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 751 pub struct SetattrIn { 752 pub valid: u32, 753 pub padding: u32, 754 pub fh: u64, 755 pub size: u64, 756 pub lock_owner: u64, 757 pub atime: u64, 758 pub mtime: u64, 759 pub ctime: u64, 760 pub atimensec: u32, 761 pub mtimensec: u32, 762 pub ctimensec: u32, 763 pub mode: u32, 764 pub unused4: u32, 765 pub uid: u32, 766 pub gid: u32, 767 pub unused5: u32, 768 } 769 770 impl From<SetattrIn> for libc::stat64 { from(s: SetattrIn) -> libc::stat64771 fn from(s: SetattrIn) -> libc::stat64 { 772 // SAFETY: zero-initializing a struct with only POD fields. 773 let mut out: libc::stat64 = unsafe { mem::zeroed() }; 774 out.st_mode = s.mode; 775 out.st_uid = s.uid; 776 out.st_gid = s.gid; 777 out.st_size = s.size as i64; 778 out.st_atime = s.atime as libc::time_t; 779 out.st_mtime = s.mtime as libc::time_t; 780 out.st_ctime = s.ctime as libc::time_t; 781 out.st_atime_nsec = s.atimensec as libc::c_long; 782 out.st_mtime_nsec = s.mtimensec as libc::c_long; 783 out.st_ctime_nsec = s.ctimensec as libc::c_long; 784 785 out 786 } 787 } 788 789 #[repr(C)] 790 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 791 pub struct OpenIn { 792 pub flags: u32, 793 pub unused: u32, 794 } 795 796 #[repr(C)] 797 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 798 pub struct CreateIn { 799 pub flags: u32, 800 pub mode: u32, 801 pub umask: u32, 802 pub padding: u32, 803 } 804 805 #[repr(C)] 806 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 807 pub struct OpenOut { 808 pub fh: u64, 809 pub open_flags: u32, 810 pub padding: u32, 811 } 812 813 #[repr(C)] 814 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 815 pub struct ReleaseIn { 816 pub fh: u64, 817 pub flags: u32, 818 pub release_flags: u32, 819 pub lock_owner: u64, 820 } 821 822 #[repr(C)] 823 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 824 pub struct FlushIn { 825 pub fh: u64, 826 pub unused: u32, 827 pub padding: u32, 828 pub lock_owner: u64, 829 } 830 831 #[repr(C)] 832 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 833 pub struct ReadIn { 834 pub fh: u64, 835 pub offset: u64, 836 pub size: u32, 837 pub read_flags: u32, 838 pub lock_owner: u64, 839 pub flags: u32, 840 pub padding: u32, 841 } 842 843 #[repr(C)] 844 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 845 pub struct WriteIn { 846 pub fh: u64, 847 pub offset: u64, 848 pub size: u32, 849 pub write_flags: u32, 850 pub lock_owner: u64, 851 pub flags: u32, 852 pub padding: u32, 853 } 854 855 #[repr(C)] 856 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 857 pub struct WriteOut { 858 pub size: u32, 859 pub padding: u32, 860 } 861 862 #[repr(C)] 863 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 864 pub struct StatfsOut { 865 pub st: Kstatfs, 866 } 867 868 #[repr(C)] 869 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 870 pub struct FsyncIn { 871 pub fh: u64, 872 pub fsync_flags: u32, 873 pub padding: u32, 874 } 875 876 #[repr(C)] 877 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 878 pub struct SetxattrIn { 879 pub size: u32, 880 pub flags: u32, 881 } 882 883 #[repr(C)] 884 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 885 pub struct GetxattrIn { 886 pub size: u32, 887 pub padding: u32, 888 } 889 890 #[repr(C)] 891 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 892 pub struct GetxattrOut { 893 pub size: u32, 894 pub padding: u32, 895 } 896 897 #[repr(C)] 898 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 899 pub struct LkIn { 900 pub fh: u64, 901 pub owner: u64, 902 pub lk: FileLock, 903 pub lk_flags: u32, 904 pub padding: u32, 905 } 906 907 #[repr(C)] 908 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 909 pub struct LkOut { 910 pub lk: FileLock, 911 } 912 913 #[repr(C)] 914 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 915 pub struct AccessIn { 916 pub mask: u32, 917 pub padding: u32, 918 } 919 920 #[repr(C)] 921 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 922 pub struct InitIn { 923 pub major: u32, 924 pub minor: u32, 925 pub max_readahead: u32, 926 pub flags: u32, 927 } 928 929 #[repr(C)] 930 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 931 pub struct InitInExt { 932 pub flags2: u32, 933 pub unused: [u32; 11], 934 } 935 936 #[repr(C)] 937 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 938 pub struct InitOut { 939 pub major: u32, 940 pub minor: u32, 941 pub max_readahead: u32, 942 pub flags: u32, 943 pub max_background: u16, 944 pub congestion_threshold: u16, 945 pub max_write: u32, 946 pub time_gran: u32, 947 pub max_pages: u16, 948 pub map_alignment: u16, 949 pub flags2: u32, 950 pub unused: [u32; 7], 951 } 952 953 #[repr(C)] 954 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 955 pub struct InterruptIn { 956 pub unique: u64, 957 } 958 959 #[repr(C)] 960 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 961 pub struct BmapIn { 962 pub block: u64, 963 pub blocksize: u32, 964 pub padding: u32, 965 } 966 967 #[repr(C)] 968 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 969 pub struct BmapOut { 970 pub block: u64, 971 } 972 973 #[repr(C)] 974 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 975 pub struct IoctlIn { 976 pub fh: u64, 977 pub flags: u32, 978 pub cmd: u32, 979 pub arg: u64, 980 pub in_size: u32, 981 pub out_size: u32, 982 } 983 984 /// Describes a region of memory in the address space of the process that made the ioctl syscall. 985 /// Similar to `libc::iovec` but uses `u64`s for the address and the length. 986 #[repr(C)] 987 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 988 pub struct IoctlIovec { 989 /// The start address of the memory region. This must be in the address space of the process 990 /// that made the ioctl syscall. 991 pub base: u64, 992 993 /// The length of the memory region. 994 pub len: u64, 995 } 996 997 #[repr(C)] 998 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 999 pub struct IoctlOut { 1000 pub result: i32, 1001 pub flags: u32, 1002 pub in_iovs: u32, 1003 pub out_iovs: u32, 1004 } 1005 1006 #[repr(C)] 1007 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1008 pub struct PollIn { 1009 pub fh: u64, 1010 pub kh: u64, 1011 pub flags: u32, 1012 pub events: u32, 1013 } 1014 1015 #[repr(C)] 1016 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1017 pub struct PollOut { 1018 pub revents: u32, 1019 pub padding: u32, 1020 } 1021 1022 #[repr(C)] 1023 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1024 pub struct NotifyPollWakeupOut { 1025 pub kh: u64, 1026 } 1027 1028 #[repr(C)] 1029 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1030 pub struct FallocateIn { 1031 pub fh: u64, 1032 pub offset: u64, 1033 pub length: u64, 1034 pub mode: u32, 1035 pub padding: u32, 1036 } 1037 1038 #[repr(C)] 1039 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1040 pub struct InHeader { 1041 pub len: u32, 1042 pub opcode: u32, 1043 pub unique: u64, 1044 pub nodeid: u64, 1045 pub uid: u32, 1046 pub gid: u32, 1047 pub pid: u32, 1048 pub padding: u32, 1049 } 1050 1051 #[repr(C)] 1052 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1053 pub struct OutHeader { 1054 pub len: u32, 1055 pub error: i32, 1056 pub unique: u64, 1057 } 1058 1059 #[repr(C)] 1060 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1061 pub struct Dirent { 1062 pub ino: u64, 1063 pub off: u64, 1064 pub namelen: u32, 1065 pub type_: u32, 1066 // char name[]; 1067 } 1068 1069 #[repr(C)] 1070 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1071 pub struct Direntplus { 1072 pub entry_out: EntryOut, 1073 pub dirent: Dirent, 1074 } 1075 1076 #[repr(C)] 1077 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1078 pub struct NotifyInvalInodeOut { 1079 pub ino: u64, 1080 pub off: i64, 1081 pub len: i64, 1082 } 1083 1084 #[repr(C)] 1085 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1086 pub struct NotifyInvalEntryOut { 1087 pub parent: u64, 1088 pub namelen: u32, 1089 pub padding: u32, 1090 } 1091 1092 #[repr(C)] 1093 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1094 pub struct NotifyDeleteOut { 1095 pub parent: u64, 1096 pub child: u64, 1097 pub namelen: u32, 1098 pub padding: u32, 1099 } 1100 1101 #[repr(C)] 1102 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1103 pub struct NotifyStoreOut { 1104 pub nodeid: u64, 1105 pub offset: u64, 1106 pub size: u32, 1107 pub padding: u32, 1108 } 1109 1110 #[repr(C)] 1111 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1112 pub struct Notify_Retrieve_Out { 1113 pub notify_unique: u64, 1114 pub nodeid: u64, 1115 pub offset: u64, 1116 pub size: u32, 1117 pub padding: u32, 1118 } 1119 1120 /* Matches the size of fuse_write_in */ 1121 #[repr(C)] 1122 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1123 pub struct NotifyRetrieveIn { 1124 pub dummy1: u64, 1125 pub offset: u64, 1126 pub size: u32, 1127 pub dummy2: u32, 1128 pub dummy3: u64, 1129 pub dummy4: u64, 1130 } 1131 1132 #[repr(C)] 1133 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1134 pub struct LseekIn { 1135 pub fh: u64, 1136 pub offset: u64, 1137 pub whence: u32, 1138 pub padding: u32, 1139 } 1140 1141 #[repr(C)] 1142 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1143 pub struct LseekOut { 1144 pub offset: u64, 1145 } 1146 1147 #[repr(C)] 1148 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1149 pub struct CopyFileRangeIn { 1150 pub fh_src: u64, 1151 pub off_src: u64, 1152 pub nodeid_dst: u64, 1153 pub fh_dst: u64, 1154 pub off_dst: u64, 1155 pub len: u64, 1156 pub flags: u64, 1157 } 1158 1159 #[repr(C)] 1160 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1161 pub struct SetUpMappingIn { 1162 /* An already open handle */ 1163 pub fh: u64, 1164 /* Offset into the file to start the mapping */ 1165 pub foffset: u64, 1166 /* Length of mapping required */ 1167 pub len: u64, 1168 /* Flags, FUSE_SETUPMAPPING_FLAG_* */ 1169 pub flags: u64, 1170 /* Offset in Memory Window */ 1171 pub moffset: u64, 1172 } 1173 1174 #[repr(C)] 1175 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1176 pub struct RemoveMappingIn { 1177 /* number of fuse_removemapping_one follows */ 1178 pub count: u32, 1179 } 1180 1181 #[repr(C)] 1182 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1183 pub struct RemoveMappingOne { 1184 /* Offset into the dax window start the unmapping */ 1185 pub moffset: u64, 1186 /* Length of mapping required */ 1187 pub len: u64, 1188 } 1189 1190 /// For each security context, send fuse_secctx with size of security context 1191 /// fuse_secctx will be followed by security context name and this in turn 1192 /// will be followed by actual context label. 1193 /// fuse_secctx, name, context 1194 #[repr(C)] 1195 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1196 pub struct Secctx { 1197 pub size: u32, 1198 pub padding: u32, 1199 } 1200 1201 /// Contains the information about how many fuse_secctx structures are being 1202 /// sent and what's the total size of all security contexts (including 1203 /// size of fuse_secctx_header). 1204 #[repr(C)] 1205 #[derive(Debug, Default, Copy, Clone, AsBytes, FromZeroes, FromBytes)] 1206 pub struct SecctxHeader { 1207 pub size: u32, 1208 pub nr_secctx: u32, 1209 } 1210