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