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