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