fuse/
sys.rs

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
5use std::mem;
6
7use bitflags::bitflags;
8use enumn::N;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13use zerocopy::TryFromBytes;
14
15/// Version number of this interface.
16pub const KERNEL_VERSION: u32 = 7;
17
18/// Oldest supported minor version of the fuse interface.
19pub const OLDEST_SUPPORTED_KERNEL_MINOR_VERSION: u32 = 27;
20
21/// Minor version number of this interface.
22pub const KERNEL_MINOR_VERSION: u32 = 31;
23
24/// The ID of the inode corresponding to the root directory of the file system.
25pub const ROOT_ID: u64 = 1;
26
27// Bitmasks for `fuse_setattr_in.valid`.
28const FATTR_MODE: u32 = 1;
29const FATTR_UID: u32 = 2;
30const FATTR_GID: u32 = 4;
31const FATTR_SIZE: u32 = 8;
32const FATTR_ATIME: u32 = 16;
33const FATTR_MTIME: u32 = 32;
34pub const FATTR_FH: u32 = 64;
35const FATTR_ATIME_NOW: u32 = 128;
36const FATTR_MTIME_NOW: u32 = 256;
37pub const FATTR_LOCKOWNER: u32 = 512;
38const FATTR_CTIME: u32 = 1024;
39
40bitflags! {
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.
59const FOPEN_DIRECT_IO: u32 = 1 << 0;
60
61/// Don't invalidate the data cache on open.
62const FOPEN_KEEP_CACHE: u32 = 1 << 1;
63
64/// The file is not seekable.
65const FOPEN_NONSEEKABLE: u32 = 1 << 2;
66
67/// Allow caching the directory entries.
68const FOPEN_CACHE_DIR: u32 = 1 << 3;
69
70/// This file is stream-like (i.e., no file position).
71const FOPEN_STREAM: u32 = 1 << 4;
72
73/// New file was created in atomic open
74const FOPEN_FILE_CREATED: u32 = 1 << 7;
75
76bitflags! {
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.
94const ASYNC_READ: u64 = 1;
95
96/// Remote locking for POSIX file locks.
97const POSIX_LOCKS: u64 = 2;
98
99/// Kernel sends file handle for fstat, etc... (not yet supported).
100const FILE_OPS: u64 = 4;
101
102/// Handles the O_TRUNC open flag in the filesystem.
103const ATOMIC_O_TRUNC: u64 = 8;
104
105/// FileSystem handles lookups of "." and "..".
106const EXPORT_SUPPORT: u64 = 16;
107
108/// FileSystem can handle write size larger than 4kB.
109const BIG_WRITES: u64 = 32;
110
111/// Don't apply umask to file mode on create operations.
112const DONT_MASK: u64 = 64;
113
114/// Kernel supports splice write on the device.
115const SPLICE_WRITE: u64 = 128;
116
117/// Kernel supports splice move on the device.
118const SPLICE_MOVE: u64 = 256;
119
120/// Kernel supports splice read on the device.
121const SPLICE_READ: u64 = 512;
122
123/// Remote locking for BSD style file locks.
124const FLOCK_LOCKS: u64 = 1024;
125
126/// Kernel supports ioctl on directories.
127const HAS_IOCTL_DIR: u64 = 2048;
128
129/// Automatically invalidate cached pages.
130const AUTO_INVAL_DATA: u64 = 4096;
131
132/// Do READDIRPLUS (READDIR+LOOKUP in one).
133const DO_READDIRPLUS: u64 = 8192;
134
135/// Adaptive readdirplus.
136const READDIRPLUS_AUTO: u64 = 16384;
137
138/// Asynchronous direct I/O submission.
139const ASYNC_DIO: u64 = 32768;
140
141/// Use writeback cache for buffered writes.
142const WRITEBACK_CACHE: u64 = 65536;
143
144/// Kernel supports zero-message opens.
145const NO_OPEN_SUPPORT: u64 = 131072;
146
147/// Allow parallel lookups and readdir.
148const PARALLEL_DIROPS: u64 = 262144;
149
150/// Fs handles killing suid/sgid/cap on write/chown/trunc.
151const HANDLE_KILLPRIV: u64 = 524288;
152
153/// FileSystem supports posix acls.
154const POSIX_ACL: u64 = 1048576;
155
156/// Reading the device after an abort returns `ECONNABORTED`.
157const ABORT_ERROR: u64 = 2097152;
158
159/// The reply to the `init` message contains the max number of request pages.
160const MAX_PAGES: u64 = 4194304;
161
162/// Cache `readlink` responses.
163const CACHE_SYMLINKS: u64 = 8388608;
164
165/// Kernel supports zero-message opens for directories.
166const NO_OPENDIR_SUPPORT: u64 = 16777216;
167
168/// Kernel supports explicit cache invalidation.
169const EXPLICIT_INVAL_DATA: u64 = 33554432;
170
171/// The `map_alignment` field of the `InitOut` struct is valid.
172const MAP_ALIGNMENT: u64 = 67108864;
173
174/// Extended fuse_init_in request to hold additional flags
175const INIT_EXT: u64 = 1073741824;
176
177/// The client should send the security context along with open, mkdir, create, and symlink
178/// requests.
179const SECURITY_CONTEXT: u64 = 4294967296;
180
181bitflags! {
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.
403pub const RELEASE_FLUSH: u32 = 1;
404pub const RELEASE_FLOCK_UNLOCK: u32 = 2;
405
406// Getattr flags.
407pub const GETATTR_FH: u32 = 1;
408
409// Lock flags.
410pub const LK_FLOCK: u32 = 1;
411
412// Write flags.
413
414/// Delayed write from page cache, file handle is guessed.
415pub const WRITE_CACHE: u32 = 1;
416
417/// `lock_owner` field is valid.
418pub const WRITE_LOCKOWNER: u32 = 2;
419
420/// Kill the suid and sgid bits.
421pub const WRITE_KILL_PRIV: u32 = 3;
422
423// Read flags.
424pub const READ_LOCKOWNER: u32 = 2;
425
426// Ioctl flags.
427
428/// 32bit compat ioctl on 64bit machine
429const IOCTL_COMPAT: u32 = 1;
430
431/// Not restricted to well-formed ioctls, retry allowed
432const IOCTL_UNRESTRICTED: u32 = 2;
433
434/// Retry with new iovecs
435const IOCTL_RETRY: u32 = 4;
436
437/// 32bit ioctl
438const IOCTL_32BIT: u32 = 8;
439
440/// Is a directory
441const IOCTL_DIR: u32 = 16;
442
443/// 32-bit compat ioctl on 64-bit machine with 64-bit time_t.
444const IOCTL_COMPAT_X32: u32 = 32;
445
446/// Maximum of in_iovecs + out_iovecs
447pub const IOCTL_MAX_IOV: usize = 256;
448
449bitflags! {
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.
474pub const POLL_SCHEDULE_NOTIFY: u32 = 1;
475
476/// The read buffer is required to be at least 8k, but may be much larger.
477pub const FUSE_MIN_READ_BUFFER: u32 = 8192;
478
479pub const FUSE_COMPAT_ENTRY_OUT_SIZE: u32 = 120;
480pub const FUSE_COMPAT_ATTR_OUT_SIZE: u32 = 96;
481pub const FUSE_COMPAT_MKNOD_IN_SIZE: u32 = 8;
482pub const FUSE_COMPAT_WRITE_IN_SIZE: u32 = 24;
483pub const FUSE_COMPAT_STATFS_SIZE: u32 = 48;
484pub const FUSE_COMPAT_INIT_OUT_SIZE: u32 = 8;
485pub const FUSE_COMPAT_22_INIT_OUT_SIZE: u32 = 24;
486
487const SETUPMAPPING_FLAG_WRITE: u64 = 1;
488const SETUPMAPPING_FLAG_READ: u64 = 2;
489
490bitflags! {
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
503pub const MAX_NR_SECCTX: u32 = 31;
504
505#[repr(C)]
506#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
507pub 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
526impl From<libc::stat64> for Attr {
527    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)]
552pub 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
565impl From<libc::statvfs64> for Kstatfs {
566    #[allow(clippy::unnecessary_cast)]
567    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)]
584pub 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)]
593pub 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)]
649pub 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)]
661pub 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)]
673pub struct ForgetIn {
674    pub nlookup: u64,
675}
676
677#[repr(C)]
678#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
679pub 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)]
686pub 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)]
693pub 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)]
701pub 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)]
710pub 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)]
719pub 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)]
726pub 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)]
733pub struct RenameIn {
734    pub newdir: u64,
735}
736
737#[repr(C)]
738#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
739pub 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)]
747pub struct LinkIn {
748    pub oldnodeid: u64,
749}
750
751#[repr(C)]
752#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
753pub 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
772impl From<SetattrIn> for libc::stat64 {
773    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)]
793pub 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)]
800pub 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)]
809pub 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)]
817pub 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)]
826pub 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)]
835pub 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)]
847pub 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)]
859pub 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)]
866pub struct StatfsOut {
867    pub st: Kstatfs,
868}
869
870#[repr(C)]
871#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
872pub 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)]
880pub 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)]
887pub 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)]
894pub 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)]
901pub 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)]
911pub struct LkOut {
912    pub lk: FileLock,
913}
914
915#[repr(C)]
916#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
917pub 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)]
924pub 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)]
933pub 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)]
940pub 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)]
957pub struct InterruptIn {
958    pub unique: u64,
959}
960
961#[repr(C)]
962#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
963pub 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)]
971pub struct BmapOut {
972    pub block: u64,
973}
974
975#[repr(C)]
976#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
977pub 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)]
990pub 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)]
1001pub 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)]
1010pub 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)]
1019pub 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)]
1026pub struct NotifyPollWakeupOut {
1027    pub kh: u64,
1028}
1029
1030#[repr(C)]
1031#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1032pub 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)]
1042pub 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)]
1055pub 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)]
1063pub 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)]
1073pub 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)]
1080pub 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)]
1088pub 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)]
1096pub 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)]
1105pub 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)]
1114pub 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)]
1125pub 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)]
1136pub 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)]
1145pub struct LseekOut {
1146    pub offset: u64,
1147}
1148
1149#[repr(C)]
1150#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1151pub 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)]
1163pub 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)]
1178pub 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)]
1185pub 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)]
1198pub 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)]
1208pub struct SecctxHeader {
1209    pub size: u32,
1210    pub nr_secctx: u32,
1211}