async_fusex/
protocol.rs

1//! FUSE kernel interface.
2//!
3//! Support FUSE ABI version from 7.8 up to 7.31.
4//! Compatible with OSXFUSE ABI version from 7.8 up to 7.19.
5//! <https://github.com/libfuse/libfuse/blob/master/include/fuse_kernel.h>
6
7/// Version number of this interface
8pub const FUSE_KERNEL_VERSION: u32 = 7;
9/// FUSE minimum minor version number 7.8
10#[cfg(not(feature = "abi-7-9"))]
11pub const FUSE_KERNEL_MINOR_VERSION: u32 = 8;
12/// FUSE minor version number 7.9
13#[cfg(all(feature = "abi-7-9", not(feature = "abi-7-10")))]
14pub const FUSE_KERNEL_MINOR_VERSION: u32 = 9;
15/// FUSE minor version number 7.10
16#[cfg(all(feature = "abi-7-10", not(feature = "abi-7-11")))]
17pub const FUSE_KERNEL_MINOR_VERSION: u32 = 10;
18/// FUSE minor version number 7.11
19#[cfg(all(feature = "abi-7-11", not(feature = "abi-7-12")))]
20pub const FUSE_KERNEL_MINOR_VERSION: u32 = 11;
21/// FUSE minor version number 7.12
22#[cfg(all(feature = "abi-7-12", not(feature = "abi-7-13")))]
23pub const FUSE_KERNEL_MINOR_VERSION: u32 = 12;
24/// FUSE minor version number 7.13
25#[cfg(all(feature = "abi-7-13", not(feature = "abi-7-14")))]
26pub const FUSE_KERNEL_MINOR_VERSION: u32 = 13;
27/// FUSE minor version number 7.14
28#[cfg(all(feature = "abi-7-14", not(feature = "abi-7-15")))]
29pub const FUSE_KERNEL_MINOR_VERSION: u32 = 14;
30/// FUSE minor version number 7.15
31#[cfg(all(feature = "abi-7-15", not(feature = "abi-7-16")))]
32pub const FUSE_KERNEL_MINOR_VERSION: u32 = 15;
33/// FUSE minor version number 7.16
34#[cfg(all(feature = "abi-7-16", not(feature = "abi-7-17")))]
35pub const FUSE_KERNEL_MINOR_VERSION: u32 = 16;
36/// FUSE minor version number 7.17
37#[cfg(all(feature = "abi-7-17", not(feature = "abi-7-18")))]
38pub const FUSE_KERNEL_MINOR_VERSION: u32 = 17;
39/// FUSE minor version number 7.18
40#[cfg(all(feature = "abi-7-18", not(feature = "abi-7-19")))]
41pub const FUSE_KERNEL_MINOR_VERSION: u32 = 18;
42/// FUSE minor version number 7.19
43#[cfg(all(feature = "abi-7-19", not(feature = "abi-7-20")))]
44pub const FUSE_KERNEL_MINOR_VERSION: u32 = 19;
45/// FUSE minor version number 7.20
46#[cfg(all(feature = "abi-7-20", not(feature = "abi-7-21")))]
47pub const FUSE_KERNEL_MINOR_VERSION: u32 = 20;
48/// FUSE minor version number 7.21
49#[cfg(all(feature = "abi-7-21", not(feature = "abi-7-22")))]
50pub const FUSE_KERNEL_MINOR_VERSION: u32 = 21;
51/// FUSE minor version number 7.22
52#[cfg(all(feature = "abi-7-22", not(feature = "abi-7-23")))]
53pub const FUSE_KERNEL_MINOR_VERSION: u32 = 22;
54/// FUSE minor version number 7.23
55#[cfg(all(feature = "abi-7-23", not(feature = "abi-7-24")))]
56pub const FUSE_KERNEL_MINOR_VERSION: u32 = 23;
57/// FUSE minor version number 7.24
58#[cfg(all(feature = "abi-7-24", not(feature = "abi-7-25")))]
59pub const FUSE_KERNEL_MINOR_VERSION: u32 = 24;
60/// FUSE minor version number 7.25
61#[cfg(all(feature = "abi-7-25", not(feature = "abi-7-26")))]
62pub const FUSE_KERNEL_MINOR_VERSION: u32 = 25;
63/// FUSE minor version number 7.26
64#[cfg(all(feature = "abi-7-26", not(feature = "abi-7-27")))]
65pub const FUSE_KERNEL_MINOR_VERSION: u32 = 26;
66/// FUSE minor version number 7.27
67#[cfg(all(feature = "abi-7-27", not(feature = "abi-7-28")))]
68pub const FUSE_KERNEL_MINOR_VERSION: u32 = 27;
69/// FUSE minor version number 7.28
70#[cfg(all(feature = "abi-7-28", not(feature = "abi-7-29")))]
71pub const FUSE_KERNEL_MINOR_VERSION: u32 = 28;
72/// FUSE minor version number 7.29
73#[cfg(all(feature = "abi-7-29", not(feature = "abi-7-30")))]
74pub const FUSE_KERNEL_MINOR_VERSION: u32 = 29;
75/// FUSE minor version number 7.30
76#[cfg(all(feature = "abi-7-30", not(feature = "abi-7-31")))]
77pub const FUSE_KERNEL_MINOR_VERSION: u32 = 30;
78/// FUSE minor version number 7.31
79#[cfg(all(feature = "abi-7-31", not(feature = "abi-7-32")))]
80pub const FUSE_KERNEL_MINOR_VERSION: u32 = 31;
81
82/// FUSE attribute `fuse_attr`
83#[repr(C)]
84pub struct FuseAttr {
85    /// Node i-number
86    pub ino: INum,
87    /// File size
88    pub size: u64,
89    /// Block numbers
90    pub blocks: u64,
91    /// Access time seconds
92    pub atime: u64,
93    /// Content modified time seconds
94    pub mtime: u64,
95    /// Meta-data changed time seconds
96    pub ctime: u64,
97    /// Access time nano-seconds
98    pub atimensec: u32,
99    /// Content modified time nano-seconds
100    pub mtimensec: u32,
101    /// Meta-data changed time nano-seconds
102    pub ctimensec: u32,
103    /// File mode
104    pub mode: u32,
105    /// Link numbers
106    pub nlink: u32,
107    /// User ID
108    pub uid: u32,
109    /// Group IP
110    pub gid: u32,
111    /// The device ID that this file (inode) represents if special file
112    pub rdev: u32,
113    /// Block size
114    #[cfg(feature = "abi-7-9")]
115    pub blksize: u32,
116    /// Alignment padding
117    #[cfg(feature = "abi-7-9")]
118    pub padding: u32,
119}
120
121impl std::fmt::Debug for FuseAttr {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        // fmt like : ino=xx,size=xx,blocks=xx,xx
124        write!(
125            f,
126            "ino={},size={},blocks={},atime={},mtime={},ctime={},atimensec={},mtimensec={},ctimensec={},mode={},nlink={},uid={},gid={},rdev={}",
127            self.ino,
128            self.size,
129            self.blocks,
130            self.atime,
131            self.mtime,
132            self.ctime,
133            self.atimensec,
134            self.mtimensec,
135            self.ctimensec,
136            self.mode,
137            self.nlink,
138            self.uid,
139            self.gid,
140            self.rdev,
141        )
142    }
143}
144
145/// FUSE kstatfs `fuse_kstatfs`
146#[derive(Debug)]
147#[repr(C)]
148pub struct FuseKStatFs {
149    /// Total blocks (in units of frsize)
150    pub blocks: u64,
151    /// Free blocks
152    pub bfree: u64,
153    /// Free blocks for unprivileged users
154    pub bavail: u64,
155    /// Total inodes
156    pub files: u64,
157    /// Free inodes
158    pub ffree: u64,
159    /// Filesystem block size
160    pub bsize: u32,
161    /// Maximum filename length
162    pub namelen: u32,
163    /// Fundamental file system block size
164    pub frsize: u32,
165    /// Alignment padding
166    pub padding: u32,
167    /// For future use
168    pub spare: [u32; 6],
169}
170
171/// FUSE file lock `fuse_file_lock`
172#[derive(Debug)]
173#[repr(C)]
174pub struct FuseFileLock {
175    /// The starting offset of the lock
176    pub start: u64,
177    /// The ending offset of the lock
178    pub end: u64,
179    /// The type of the lock
180    pub typ: u32,
181    /// The process ID of the lock, tgid
182    pub pid: u32,
183}
184
185/// Bitmasks for `fuse_setattr_in.valid`
186#[allow(dead_code)]
187pub mod setattr_flags {
188    /// To set file mode
189    pub const FATTR_MODE: u32 = 1 << 0_i32;
190    /// To set file user ID
191    pub const FATTR_UID: u32 = 1 << 1_i32;
192    /// To set file group ID
193    pub const FATTR_GID: u32 = 1 << 2_i32;
194    /// To set file size
195    pub const FATTR_SIZE: u32 = 1 << 3_i32;
196    /// To set file access time
197    pub const FATTR_ATIME: u32 = 1 << 4_i32;
198    /// To set content modified time
199    pub const FATTR_MTIME: u32 = 1 << 5_i32;
200    /// To set file handler
201    pub const FATTR_FH: u32 = 1 << 6_i32;
202    /// To set atime as of now
203    #[cfg(feature = "abi-7-9")]
204    pub const FATTR_ATIME_NOW: u32 = 1 << 7_i32;
205    /// To set mtime as of now
206    #[cfg(feature = "abi-7-9")]
207    pub const FATTR_MTIME_NOW: u32 = 1 << 8_i32;
208    /// To set file lock owner
209    #[cfg(feature = "abi-7-9")]
210    pub const FATTR_LOCKOWNER: u32 = 1 << 9_i32;
211    /// To set meta-data change time
212    #[cfg(feature = "abi-7-23")]
213    pub const FATTR_CTIME: u32 = 1 << 10_i32;
214}
215
216use std::mem;
217
218use clippy_utilities::{Cast, OverflowArithmetic};
219pub use setattr_flags::*;
220
221/// Flags returned by the OPEN request
222///
223/// `FOPEN_DIRECT_IO`: bypass page cache for this open file
224///
225/// `FOPEN_KEEP_CACHE`: don't invalidate the data cache on open
226///
227/// `FOPEN_NONSEEKABLE`: the file is not seekable
228///
229/// `FOPEN_CACHE_DIR`: allow caching this directory
230///
231/// `FOPEN_STREAM`: the file is stream-like (no file position at all)
232#[allow(dead_code)]
233pub mod fopen_flags {
234    /// bypass page cache for this open file
235    pub const FOPEN_DIRECT_IO: u32 = 1;
236
237    /// don't invalidate the data cache on open
238    pub const FOPEN_KEEP_CACHE: u32 = 1 << 1_i32;
239
240    /// the file is not seekable
241    #[cfg(feature = "abi-7-10")]
242    pub const FOPEN_NONSEEKABLE: u32 = 1 << 2_i32;
243
244    /// allow caching this directory
245    #[cfg(feature = "abi-7-28")]
246    pub const FOPEN_CACHE_DIR: u32 = 1 << 3_i32;
247
248    /// the file is stream-like (no file position at all)
249    #[cfg(feature = "abi-7-31")]
250    pub const FOPEN_STREAM: u32 = 1 << 4_i32;
251}
252
253pub use fopen_flags::*;
254
255/// INIT request/reply flags
256#[allow(dead_code)]
257pub mod init_flags {
258    /// `FUSE_ASYNC_READ`: asynchronous read requests
259    pub const FUSE_ASYNC_READ: u32 = 1;
260    /// `FUSE_POSIX_LOCKS`: remote locking for POSIX file locks
261    pub const FUSE_POSIX_LOCKS: u32 = 1 << 1_i32;
262    /// `FUSE_FILE_OPS`: kernel sends file handle for fstat, etc... (not yet
263    /// supported)
264    #[cfg(feature = "abi-7-9")]
265    pub const FUSE_FILE_OPS: u32 = 1 << 2_i32;
266    /// `FUSE_ATOMIC_O_TRUNC`: handles the `O_TRUNC` open flag in the filesystem
267    #[cfg(feature = "abi-7-9")]
268    pub const FUSE_ATOMIC_O_TRUNC: u32 = 1 << 3_i32;
269    /// `FUSE_EXPORT_SUPPORT`: filesystem handles lookups of "." and ".."
270    #[cfg(feature = "abi-7-10")]
271    pub const FUSE_EXPORT_SUPPORT: u32 = 1 << 4_i32;
272    /// `FUSE_BIG_WRITES`: filesystem can handle write size larger than 4kB
273    #[cfg(feature = "abi-7-9")]
274    pub const FUSE_BIG_WRITES: u32 = 1 << 5_i32;
275    /// `FUSE_DONT_MASK`: don't apply umask to file mode on create operations
276    #[cfg(feature = "abi-7-12")]
277    pub const FUSE_DONT_MASK: u32 = 1 << 6_i32;
278    /// `FUSE_SPLICE_WRITE`: kernel supports splice write on the device
279    #[cfg(feature = "abi-7-14")]
280    pub const FUSE_SPLICE_WRITE: u32 = 1 << 7_i32;
281    /// `FUSE_SPLICE_MOVE`: kernel supports splice move on the device
282    #[cfg(feature = "abi-7-14")]
283    pub const FUSE_SPLICE_MOVE: u32 = 1 << 8_i32;
284    /// `FUSE_SPLICE_READ`: kernel supports splice read on the device
285    #[cfg(feature = "abi-7-14")]
286    pub const FUSE_SPLICE_READ: u32 = 1 << 9_i32;
287    /// `FUSE_FLOCK_LOCKS`: remote locking for BSD style file locks
288    #[cfg(feature = "abi-7-17")]
289    pub const FUSE_FLOCK_LOCKS: u32 = 1 << 10_i32;
290    /// `FUSE_HAS_IOCTL_DIR`: kernel supports ioctl on directories
291    #[cfg(feature = "abi-7-18")]
292    pub const FUSE_HAS_IOCTL_DIR: u32 = 1 << 11_i32;
293    /// `FUSE_AUTO_INVAL_DATA`: automatically invalidate cached pages
294    #[cfg(feature = "abi-7-20")]
295    pub const FUSE_AUTO_INVAL_DATA: u32 = 1 << 12_i32;
296    /// `FUSE_DO_READDIRPLUS`: do READDIRPLUS (READDIR+LOOKUP in one)
297    #[cfg(feature = "abi-7-21")]
298    pub const FUSE_DO_READDIRPLUS: u32 = 1 << 13_i32;
299
300    /// `FUSE_READDIRPLUS_AUTO`: adaptive readdirplus
301    #[cfg(feature = "abi-7-21")]
302    pub const FUSE_READDIRPLUS_AUTO: u32 = 1 << 14_i32;
303    /// `FUSE_ASYNC_DIO`: asynchronous direct I/O submission
304    #[cfg(feature = "abi-7-22")]
305    pub const FUSE_ASYNC_DIO: u32 = 1 << 15_i32;
306    /// `FUSE_WRITEBACK_CACHE`: use writeback cache for buffered writes
307    #[cfg(feature = "abi-7-23")]
308    pub const FUSE_WRITEBACK_CACHE: u32 = 1 << 16_i32;
309    /// `FUSE_NO_OPEN_SUPPORT`: kernel supports zero-message opens
310    #[cfg(feature = "abi-7-23")]
311    pub const FUSE_NO_OPEN_SUPPORT: u32 = 1 << 17_i32;
312    /// `FUSE_PARALLEL_DIROPS`: allow parallel lookups and readdir
313    #[cfg(feature = "abi-7-25")]
314    pub const FUSE_PARALLEL_DIROPS: u32 = 1 << 18_i32;
315    /// `FUSE_HANDLE_KILLPRIV`: fs handles killing suid/sgid/cap on
316    /// write/chown/trunc
317    #[cfg(feature = "abi-7-26")]
318    pub const FUSE_HANDLE_KILLPRIV: u32 = 1 << 19_i32;
319    /// `FUSE_POSIX_ACL`: filesystem supports posix acls
320    #[cfg(feature = "abi-7-26")]
321    pub const FUSE_POSIX_ACL: u32 = 1 << 20_i32;
322    /// `FUSE_ABORT_ERROR`: reading the device after abort returns ECONNABORTED
323    #[cfg(feature = "abi-7-27")]
324    pub const FUSE_ABORT_ERROR: u32 = 1 << 21_i32;
325    /// `FUSE_MAX_PAGES`: `init_out.max_pages` contains the max number of req
326    /// pages
327    #[cfg(feature = "abi-7-28")]
328    pub const FUSE_MAX_PAGES: u32 = 1 << 22_i32;
329    /// `FUSE_CACHE_SYMLINKS`: cache READLINK responses
330    #[cfg(feature = "abi-7-28")]
331    pub const FUSE_CACHE_SYMLINKS: u32 = 1 << 23_i32;
332    /// `FUSE_NO_OPENDIR_SUPPORT`: kernel supports zero-message opendir
333    #[cfg(feature = "abi-7-29")]
334    pub const FUSE_NO_OPENDIR_SUPPORT: u32 = 1 << 24_i32;
335    /// `FUSE_EXPLICIT_INVAL_DATA`: only invalidate cached pages on explicit
336    /// request
337    #[cfg(feature = "abi-7-30")]
338    pub const FUSE_EXPLICIT_INVAL_DATA: u32 = 1 << 25_i32;
339}
340
341pub use init_flags::*;
342
343/// CUSE INIT request/reply flags
344///
345/// `CUSE_UNRESTRICTED_IOCTL`:  use unrestricted ioctl
346#[allow(dead_code)]
347#[cfg(feature = "abi-7-11")]
348pub const CUSE_UNRESTRICTED_IOCTL: u32 = 1 << 0_i32; // use unrestricted ioctl
349
350/// Release with flush
351pub const FUSE_RELEASE_FLUSH: u32 = 1 << 0_i32;
352/// Release with `flock` unlock
353#[allow(dead_code)]
354#[cfg(feature = "abi-7-17")]
355pub const FUSE_RELEASE_FLOCK_UNLOCK: u32 = 1 << 1_i32;
356
357/// Getattr flags
358#[allow(dead_code)]
359#[cfg(feature = "abi-7-9")]
360pub const FUSE_GETATTR_FH: u32 = 1 << 0_i32;
361
362/// Lock flags
363#[allow(dead_code)]
364#[cfg(feature = "abi-7-9")]
365pub const FUSE_LK_FLOCK: u32 = 1 << 0_i32;
366
367/// WRITE flags
368#[allow(dead_code)]
369pub mod write_flags {
370    /// `FUSE_WRITE_CACHE`: delayed write from page cache, file handle is
371    /// guessed
372    #[cfg(feature = "abi-7-9")]
373    pub const FUSE_WRITE_CACHE: u32 = 1 << 0_i32;
374    /// `FUSE_WRITE_LOCKOWNER`: `lock_owner` field is valid
375    #[cfg(feature = "abi-7-9")]
376    pub const FUSE_WRITE_LOCKOWNER: u32 = 1 << 1_i32;
377    /// `FUSE_WRITE_KILL_PRIV`: kill suid and sgid bits
378    #[cfg(feature = "abi-7-31")]
379    pub const FUSE_WRITE_KILL_PRIV: u32 = 1 << 2_i32;
380}
381
382pub use write_flags::*;
383
384/// Read flags
385#[allow(dead_code)]
386#[cfg(feature = "abi-7-9")]
387pub const FUSE_READ_LOCKOWNER: u32 = 1 << 1_i32;
388
389/// Ioctl flags
390#[allow(dead_code)]
391#[cfg(feature = "abi-7-11")]
392pub mod ioctl_flags {
393    /// `FUSE_IOCTL_COMPAT`: 32bit compat ioctl on 64bit machine
394    pub const FUSE_IOCTL_COMPAT: u32 = 1 << 0_i32;
395    /// `FUSE_IOCTL_UNRESTRICTED`: not restricted to well-formed ioctls, retry
396    /// allowed
397    pub const FUSE_IOCTL_UNRESTRICTED: u32 = 1 << 1_i32;
398    /// `FUSE_IOCTL_RETRY`: retry with new iovecs
399    pub const FUSE_IOCTL_RETRY: u32 = 1 << 2_i32;
400    /// `FUSE_IOCTL_32BIT`: 32bit ioctl
401    #[cfg(feature = "abi-7-16")]
402    pub const FUSE_IOCTL_32BIT: u32 = 1 << 3_i32;
403    /// `FUSE_IOCTL_DIR`: is a directory
404    #[cfg(feature = "abi-7-18")]
405    pub const FUSE_IOCTL_DIR: u32 = 1 << 4_i32;
406    /// `FUSE_IOCTL_COMPAT_X32`: x32 compat ioctl on 64bit machine (64bit
407    /// `time_t`)
408    #[cfg(feature = "abi-7-30")]
409    pub const FUSE_IOCTL_COMPAT_X32: u32 = 1 << 5_i32;
410    /// `FUSE_IOCTL_MAX_IOV`: maximum of `in_iovecs + out_iovecs`
411    pub const FUSE_IOCTL_MAX_IOV: u32 = 256;
412}
413
414#[cfg(feature = "abi-7-11")]
415pub use ioctl_flags::*;
416
417/// Poll flags
418///
419/// `FUSE_POLL_SCHEDULE_NOTIFY`: request poll notify
420#[allow(dead_code)]
421#[cfg(feature = "abi-7-11")]
422pub const FUSE_POLL_SCHEDULE_NOTIFY: u32 = 1 << 0_i32;
423
424/// Fsync flags
425///
426/// `FUSE_FSYNC_FDATASYNC`: sync data only, not metadata
427#[allow(dead_code)]
428#[cfg(feature = "abi-7-31")]
429pub const FUSE_FSYNC_FDATASYNC: u32 = 1 << 0_i32;
430
431/// FUSE operation code `fuse_opcode`
432#[allow(
433    non_camel_case_types,
434    // clippy::upper_case_acronyms,
435)]
436#[derive(Debug)]
437#[non_exhaustive]
438#[repr(C)]
439pub enum FuseOpCode {
440    /// Look up a directory entry by name and get its attributes
441    FUSE_LOOKUP = 1,
442    /// Forget about an inode, no reply
443    FUSE_FORGET = 2,
444    /// Get file attributes
445    FUSE_GETATTR = 3,
446    /// Set file attributes
447    FUSE_SETATTR = 4,
448    /// Read symbolic link
449    FUSE_READLINK = 5,
450    /// Create a symbolic link
451    FUSE_SYMLINK = 6,
452    /// Create file node
453    FUSE_MKNOD = 8,
454    /// Create a directory
455    FUSE_MKDIR = 9,
456    /// Remove a file
457    FUSE_UNLINK = 10,
458    /// Remove a directory
459    FUSE_RMDIR = 11,
460    /// Rename a file
461    FUSE_RENAME = 12,
462    /// Create a hard link
463    FUSE_LINK = 13,
464    /// Open a file
465    FUSE_OPEN = 14,
466    /// Read data from file
467    FUSE_READ = 15,
468    /// Write data to file
469    FUSE_WRITE = 16,
470    /// Get file system statistics
471    FUSE_STATFS = 17,
472    /// Release an open file
473    FUSE_RELEASE = 18,
474    /// Synchronize file contents
475    FUSE_FSYNC = 20,
476    /// Set an extended attribute
477    FUSE_SETXATTR = 21,
478    /// Get an extended attribute
479    FUSE_GETXATTR = 22,
480    /// List extended attribute names
481    FUSE_LISTXATTR = 23,
482    /// Remove an extended attribute
483    FUSE_REMOVEXATTR = 24,
484    /// Flush file
485    FUSE_FLUSH = 25,
486    /// Initialize filesystem
487    FUSE_INIT = 26,
488    /// Open a directory
489    FUSE_OPENDIR = 27,
490    /// Read directory
491    FUSE_READDIR = 28,
492    /// Release an open directory
493    FUSE_RELEASEDIR = 29,
494    /// Synchronize directory contents
495    FUSE_FSYNCDIR = 30,
496    /// Test for a POSIX file lock
497    FUSE_GETLK = 31,
498    /// Acquire, modify or release a POSIX file lock
499    FUSE_SETLK = 32,
500    /// Acquire, modify or release a POSIX file lock and wait
501    FUSE_SETLKW = 33,
502    /// Check file access permissions
503    FUSE_ACCESS = 34,
504    /// Create and open a file
505    FUSE_CREATE = 35,
506    /// Interrupt a previous FUSE request
507    FUSE_INTERRUPT = 36,
508    /// Map block index withClean up filesystemin file to block index within
509    /// device
510    FUSE_BMAP = 37,
511    /// Clean up filesystem
512    FUSE_DESTROY = 38,
513    /// Ioctl
514    #[cfg(feature = "abi-7-11")]
515    FUSE_IOCTL = 39,
516    /// Poll for IO readiness
517    #[cfg(feature = "abi-7-11")]
518    FUSE_POLL = 40,
519    /// A reply to a NOTIFY_RETRIEVE notification
520    #[cfg(feature = "abi-7-15")]
521    FUSE_NOTIFY_REPLY = 41,
522    /// Batch forget inodes
523    #[cfg(feature = "abi-7-16")]
524    FUSE_BATCH_FORGET = 42,
525    /// Allocate requested space
526    #[cfg(feature = "abi-7-19")]
527    FUSE_FALLOCATE = 43,
528    /// Read directory with attributes
529    #[cfg(feature = "abi-7-21")]
530    FUSE_READDIRPLUS = 44,
531    /// Rename2
532    #[cfg(feature = "abi-7-23")]
533    FUSE_RENAME2 = 45,
534    /// Find next data or hole after the specified offset
535    // #[cfg(feature = "abi-7-24")]
536    FUSE_LSEEK = 46,
537    /// Copy a range of data from an opened file to another
538    // #[cfg(feature = "abi-7-28")]
539    FUSE_COPY_FILE_RANGE = 47,
540    /// CUSE specific operations
541    #[cfg(feature = "abi-7-11")]
542    CUSE_INIT = 4096,
543}
544
545/// FUSE notify code `fuse_notify_code`
546#[allow(dead_code)]
547#[allow(
548    non_camel_case_types,
549    // clippy::upper_case_acronyms,
550)]
551#[cfg(feature = "abi-7-11")]
552#[derive(Debug)]
553#[repr(C)]
554pub enum FuseNotifyCode {
555    /// Poll
556    FUSE_POLL = 1,
557    /// Notify invalid inode
558    #[cfg(feature = "abi-7-12")]
559    FUSE_NOTIFY_INVAL_INODE = 2,
560    /// Notify invalid entry
561    #[cfg(feature = "abi-7-12")]
562    FUSE_NOTIFY_INVAL_ENTRY = 3,
563    /// Notify store
564    #[cfg(feature = "abi-7-15")]
565    FUSE_NOTIFY_STORE = 4,
566    /// Notify retrieve
567    #[cfg(feature = "abi-7-15")]
568    FUSE_NOTIFY_RETRIEVE = 5,
569    /// Notify delete
570    #[cfg(feature = "abi-7-18")]
571    FUSE_NOTIFY_DELETE = 6,
572    /// Max notify code
573    FUSE_NOTIFY_CODE_MAX,
574}
575
576/// The read buffer is required to be at least 8k, but may be much larger
577#[allow(dead_code)]
578pub const FUSE_MIN_READ_BUFFER: usize = 8192;
579
580/// FUSE compatible configurations
581#[allow(dead_code)]
582pub mod fuse_compat_configs {
583    /// FUSE compatible statfs size when minior version lower than 4
584    pub const FUSE_COMPAT_STATFS_SIZE: usize = 48;
585    /// FUSE compatible directory entry related response size for version < 7.9
586    #[cfg(feature = "abi-7-9")]
587    pub const FUSE_COMPAT_ENTRY_OUT_SIZE: usize = 120;
588    /// FUSE compatible attribute related response size for version < 7.9
589    #[cfg(feature = "abi-7-9")]
590    pub const FUSE_COMPAT_ATTR_OUT_SIZE: usize = 96;
591    /// FUSE compatible `mknod` request size for version < 7.12
592    #[cfg(feature = "abi-7-12")]
593    pub const FUSE_COMPAT_MKNOD_IN_SIZE: usize = 8;
594    /// FUSE compatible `write` request size for version < 7.9
595    #[cfg(feature = "abi-7-9")]
596    pub const FUSE_COMPAT_WRITE_IN_SIZE: usize = 24;
597    /// FUSE compatible `init` response size for version < 7.5
598    #[cfg(feature = "abi-7-23")]
599    pub const FUSE_COMPAT_INIT_OUT_SIZE: usize = 8;
600    /// FUSE compatible `init` response size for version < 7.23
601    #[cfg(feature = "abi-7-23")]
602    pub const FUSE_COMPAT_22_INIT_OUT_SIZE: usize = 24;
603}
604
605pub use fuse_compat_configs::*;
606
607use crate::fs_util::INum;
608
609/// FUSE entry response `fuse_entry_out`
610#[derive(Debug)]
611#[repr(C)]
612pub struct FuseEntryOut {
613    /// Inode ID
614    pub nodeid: u64,
615    /// Inode generation: nodeid:gen must be unique for the fs's lifetime
616    pub generation: u64,
617    /// Cache timeout seconds for the name
618    pub entry_valid: u64,
619    /// Cache timeout seconds for the attributes
620    pub attr_valid: u64,
621    /// Cache timeout nano-seconds for the name
622    pub entry_valid_nsec: u32,
623    /// Cache timeout nano-seconds for the attributes
624    pub attr_valid_nsec: u32,
625    /// FUSE attributes
626    pub attr: FuseAttr,
627}
628
629/// FUSE forget request input `fuse_forget_in`
630#[derive(Debug)]
631#[repr(C)]
632pub struct FuseForgetIn {
633    /// The number of lookup to forget
634    pub nlookup: u64,
635}
636
637/// FUSE forget request input `fuse_forget_one`
638#[cfg(feature = "abi-7-16")]
639#[derive(Debug)]
640#[repr(C)]
641pub struct FuseForgetOne {
642    /// The node i-number
643    pub nodeid: u64,
644    /// The number of lookup to forget
645    pub nlookup: u64,
646}
647
648/// FUSE batch forget request input `fuse_batch_forget_in`
649#[cfg(feature = "abi-7-16")]
650#[derive(Debug)]
651#[repr(C)]
652pub struct FuseBatchForgetIn {
653    /// Batch count
654    pub count: u32,
655    /// Alignment padding
656    pub dummy: u32,
657    // Followed by `count` number of FuseForgetOne
658    // forgets: &[FuseForgetOne]
659}
660
661/// FUSE get attribute request input `fuse_getattr_in`
662#[cfg(feature = "abi-7-9")]
663#[derive(Debug)]
664#[repr(C)]
665pub struct FuseGetAttrIn {
666    /// Get attribute flags
667    pub getattr_flags: u32,
668    /// Alignment padding
669    pub dummy: u32,
670    /// File handler
671    pub fh: u64,
672}
673
674/// FUSE get attribute response `fuse_attr_out`
675#[derive(Debug)]
676#[repr(C)]
677pub struct FuseAttrOut {
678    /// Cache timeout seconds for the attributes
679    pub attr_valid: u64,
680    /// Cache timeout nano-seconds for the attributes
681    pub attr_valid_nsec: u32,
682    /// Alignment padding
683    pub dummy: u32,
684    /// FUSE file attribute
685    pub attr: FuseAttr,
686}
687
688/// FUSE make node request input `fuse_mknod_in`
689#[derive(Debug)]
690#[repr(C)]
691pub struct FuseMkNodIn {
692    /// File mode
693    pub mode: u32,
694    /// The device ID that this file (inode) represents if special file
695    pub rdev: u32,
696    /// The user file creation mode mask
697    #[cfg(feature = "abi-7-12")]
698    pub umask: u32,
699    /// Alignment padding
700    #[cfg(feature = "abi-7-12")]
701    pub padding: u32,
702}
703
704/// FUSE make directory request input `fuse_mkdir_in`
705#[derive(Debug)]
706#[repr(C)]
707pub struct FuseMkDirIn {
708    /// Directory mode
709    pub mode: u32,
710    /// Alignment padding
711    #[cfg(not(feature = "abi-7-12"))]
712    pub padding: u32,
713    /// The user directory creation mode mask
714    #[cfg(feature = "abi-7-12")]
715    pub umask: u32,
716}
717
718/// FUSE rename request input `fuse_rename_in`
719#[derive(Debug)]
720#[repr(C)]
721pub struct FuseRenameIn {
722    /// The new directory i-number
723    pub newdir: u64,
724}
725
726/// FUSE rename2 request input `fuse_rename2_in`
727///
728/// Available when the protocol version is greater than 7.22.
729/// This is checked by the kernel so that the app won't receive such a request.
730///
731/// See [here](https://github.com/torvalds/linux/blob/8f6f76a6a29f36d2f3e4510d0bde5046672f6924/fs/fuse/dir.c#L1077C2-L1088C3)
732/// for the source code of checking.
733#[cfg(feature = "abi-7-23")]
734#[derive(Debug)]
735#[repr(C)]
736pub struct FuseRename2In {
737    /// The new directory i-number
738    pub newdir: u64,
739    /// The flags maybe either `RENAME_NOREPLACE`=1 or `RENAME_EXCHANGE`=2
740    pub flags: u32,
741    /// Alignment padding
742    pub padding: u32,
743}
744
745/// FUSE link request input `fuse_link_in`
746#[derive(Debug)]
747#[repr(C)]
748pub struct FuseLinkIn {
749    /// The old node i-number
750    pub oldnodeid: u64,
751}
752
753/// FUSE set attribute request input `fuse_setattr_in`
754#[derive(Debug)]
755#[repr(C)]
756pub struct FuseSetAttrIn {
757    /// FUSE set attribute bit mask
758    pub valid: u32,
759    /// Alignment padding
760    pub padding: u32,
761    /// File handler
762    pub fh: u64,
763    /// File size
764    pub size: u64,
765    /// Alignment padding
766    #[cfg(not(feature = "abi-7-9"))]
767    pub unused1: u64,
768    /// Lock owner
769    #[cfg(feature = "abi-7-9")]
770    pub lock_owner: u64,
771    /// Access time seconds
772    pub atime: u64,
773    /// Content modified time seconds
774    pub mtime: u64,
775    /// Alignment padding
776    #[cfg(not(feature = "abi-7-23"))]
777    pub unused2: u64,
778    /// Meta-data changed time seconds
779    #[cfg(feature = "abi-7-23")]
780    pub ctime: u64,
781    /// Access time nano-seconds
782    pub atimensec: u32,
783    /// Content modified time nano-seconds
784    pub mtimensec: u32,
785    /// Alignment padding
786    #[cfg(not(feature = "abi-7-23"))]
787    pub unused3: u32,
788    /// Meta-data changed time nano-seconds
789    #[cfg(feature = "abi-7-23")]
790    pub ctimensec: u32,
791    /// File mode
792    pub mode: u32,
793    /// Alignment padding
794    pub unused4: u32,
795    /// User ID
796    pub uid: u32,
797    /// Group ID
798    pub gid: u32,
799    /// Alignment padding
800    pub unused5: u32,
801}
802
803/// FUSE open request input `fuse_open_in`
804#[derive(Debug)]
805#[repr(C)]
806pub struct FuseOpenIn {
807    /// Open flags
808    pub flags: u32,
809    #[cfg(not(feature = "abi-7-12"))]
810    /// Access mode of the file
811    pub mode: u32,
812    #[cfg(feature = "abi-7-12")]
813    /// Alignment padding
814    pub unused: u32,
815}
816
817/// FUSE create request input `fuse_create_in`
818#[derive(Debug)]
819#[repr(C)]
820pub struct FuseCreateIn {
821    /// Creation flags
822    pub flags: u32,
823    /// File mode
824    pub mode: u32,
825    /// The user file creation mode mask
826    #[cfg(feature = "abi-7-12")]
827    pub umask: u32,
828    /// Alignment padding
829    #[cfg(feature = "abi-7-12")]
830    pub padding: u32,
831}
832
833/// FUSE open resoponse `fuse_open_out`
834#[derive(Debug)]
835#[repr(C)]
836pub struct FuseOpenOut {
837    /// File handler
838    pub fh: u64,
839    /// Open flags
840    pub open_flags: u32,
841    /// Alignment padding
842    pub padding: u32,
843}
844
845/// FUSE release request input `fuse_release_in`
846#[derive(Debug)]
847#[repr(C)]
848pub struct FuseReleaseIn {
849    /// File handler
850    pub fh: u64,
851    /// Open flags
852    pub flags: u32,
853    /// Release flags
854    pub release_flags: u32,
855    /// Lock owner
856    pub lock_owner: u64,
857}
858
859/// FUSE flush request input `fuse_flush_in`
860#[derive(Debug)]
861#[repr(C)]
862pub struct FuseFlushIn {
863    /// File handler
864    pub fh: u64,
865    /// Alignment padding
866    pub unused: u32,
867    /// Alignment padding
868    pub padding: u32,
869    /// Lock owner
870    pub lock_owner: u64,
871}
872
873/// FUSE read request input `fuse_read_in`
874#[derive(Debug)]
875#[repr(C)]
876pub struct FuseReadIn {
877    /// File handler
878    pub fh: u64,
879    /// Read offset
880    pub offset: u64,
881    /// Read size
882    pub size: u32,
883    /// Read flags
884    #[cfg(feature = "abi-7-9")]
885    pub read_flags: u32,
886    /// Lock owner
887    #[cfg(feature = "abi-7-9")]
888    pub lock_owner: u64,
889    /// Open flags
890    #[cfg(feature = "abi-7-9")]
891    pub flags: u32,
892    /// Alignment padding
893    pub padding: u32,
894}
895
896/// FUSE write request input `fuse_write_in`
897#[derive(Debug)]
898#[repr(C)]
899pub struct FuseWriteIn {
900    /// File handler
901    pub fh: u64,
902    /// Write offset
903    pub offset: u64,
904    /// Write size
905    pub size: u32,
906    /// Write flags
907    pub write_flags: u32,
908    /// Lock owner
909    #[cfg(feature = "abi-7-9")]
910    pub lock_owner: u64,
911    /// Open flags
912    #[cfg(feature = "abi-7-9")]
913    pub flags: u32,
914    /// Alignment padding
915    #[cfg(feature = "abi-7-9")]
916    pub padding: u32,
917}
918
919/// FUSE write response `fuse_write_out`
920#[derive(Debug)]
921#[repr(C)]
922pub struct FuseWriteOut {
923    /// Write size
924    pub size: u32,
925    /// Alignment padding
926    pub padding: u32,
927}
928
929/// FUSE statfs response `fuse_statfs_out`
930#[derive(Debug)]
931#[repr(C)]
932pub struct FuseStatFsOut {
933    /// FUSE kstatfs
934    pub st: FuseKStatFs,
935}
936
937/// FUSE fsync request input `fuse_fsync_in`
938#[derive(Debug)]
939#[repr(C)]
940pub struct FuseFSyncIn {
941    /// File handler
942    pub fh: u64,
943    /// File sync flags
944    pub fsync_flags: u32,
945    /// Alignment padding
946    pub padding: u32,
947}
948
949/// FUSE set extended attribute request input `fuse_setxattr_in`
950#[derive(Debug)]
951#[repr(C)]
952pub struct FuseSetXAttrIn {
953    /// The size of extended attribute value to set
954    pub size: u32,
955    /// The flags that specifies the meanings of this operation
956    pub flags: u32,
957}
958
959/// FUSE get extended attribute request input `fuse_getxattr_in`
960#[derive(Debug)]
961#[repr(C)]
962pub struct FuseGetXAttrIn {
963    /// The maximum length of the attribute value to be replied
964    pub size: u32,
965    /// Alignment padding
966    pub padding: u32,
967}
968
969/// FUSE get extended attribute response `fuse_getxattr_out`
970#[derive(Debug)]
971#[repr(C)]
972pub struct FuseGetXAttrOut {
973    /// The size of the extended attribute value
974    pub size: u32,
975    /// Alignment padding
976    pub padding: u32,
977}
978
979/// FUSE lock request input `fuse_lk_in`
980#[derive(Debug)]
981#[repr(C)]
982pub struct FuseLockIn {
983    /// File handler
984    pub fh: u64,
985    /// Lock owner
986    pub owner: u64,
987    /// FUSE file lock
988    pub lk: FuseFileLock,
989    /// Lock flags
990    #[cfg(feature = "abi-7-9")]
991    pub lk_flags: u32,
992    /// Alignment padding
993    #[cfg(feature = "abi-7-9")]
994    pub padding: u32,
995}
996
997/// FUSE lock response `fuse_lk_out`
998#[derive(Debug)]
999#[repr(C)]
1000pub struct FuseLockOut {
1001    /// FUSE file lock
1002    pub lk: FuseFileLock,
1003}
1004
1005/// FUSE access request input `fuse_access_in`
1006#[derive(Debug)]
1007#[repr(C)]
1008pub struct FuseAccessIn {
1009    /// The requested access mode
1010    pub mask: u32,
1011    /// Alignment padding
1012    pub padding: u32,
1013}
1014
1015/// FUSE init request input `fuse_init_in`
1016#[derive(Debug)]
1017#[repr(C)]
1018pub struct FuseInitIn {
1019    /// FUSE protocol major version
1020    pub major: u32,
1021    /// FUSE protocol minor version
1022    pub minor: u32,
1023    /// FUSE maximum readahead size
1024    pub max_readahead: u32,
1025    /// FUSE init flags
1026    pub flags: u32,
1027}
1028
1029/// FUSE init response `fuse_init_out`
1030#[derive(Debug)]
1031#[repr(C)]
1032pub struct FuseInitOut {
1033    /// FUSE protocol major version
1034    pub major: u32,
1035    /// FUSE protocol minor version
1036    pub minor: u32,
1037    /// FUSE maximum readahead size
1038    pub max_readahead: u32,
1039    /// FUSE init flags
1040    pub flags: u32,
1041    /// Alignment padding
1042    #[cfg(not(feature = "abi-7-13"))]
1043    pub unused: u32,
1044    /// Max background pending requests under processing
1045    #[cfg(feature = "abi-7-13")]
1046    pub max_background: u16,
1047    /// Notify FUSE kernel module to mark the filesystem as "congested"
1048    /// if the number of pending requests above this threshold
1049    #[cfg(feature = "abi-7-13")]
1050    pub congestion_threshold: u16,
1051    /// The max size of write requests from the kernel
1052    pub max_write: u32,
1053    /// The timestamp granularity supported by the FUSE filesystem
1054    /// The default is 1 for full nano-second resolution, 1000000000 for second
1055    /// resolution
1056    #[cfg(feature = "abi-7-23")]
1057    pub time_gran: u32,
1058    // unused: [u32; 9] is defined between 7-13 and 7-27
1059    // TODO: verify cfg works
1060    /// Alignment padding
1061    #[cfg(all(feature = "abi-7-23", not(feature = "abi-7-28")))]
1062    pub unused: [u32; 9],
1063    ///
1064    #[cfg(feature = "abi-7-28")]
1065    pub max_pages: u16,
1066    #[cfg(feature = "abi-7-28")]
1067    /// Alignment padding
1068    pub padding: u16,
1069    /// For future use
1070    #[cfg(feature = "abi-7-28")]
1071    pub unused: [u32; 8],
1072}
1073
1074/// CUSE device info max size
1075#[allow(dead_code)]
1076#[cfg(feature = "abi-7-11")]
1077pub const CUSE_INIT_INFO_MAX: u32 = 4096;
1078
1079/// CUSE init request input `cuse_init_in`
1080#[cfg(feature = "abi-7-11")]
1081#[derive(Debug)]
1082#[repr(C)]
1083pub struct CuseInitIn {
1084    /// Protocol major version
1085    pub major: u32,
1086    /// Protocol minor version
1087    pub minor: u32,
1088    /// Alignment padding
1089    pub unused: u32,
1090    /// CUSE flags
1091    pub flags: u32,
1092}
1093
1094/// CUSE init response `cuse_init_out`
1095#[cfg(feature = "abi-7-11")]
1096#[derive(Debug)]
1097#[repr(C)]
1098pub struct CuseInitOut {
1099    /// Protocol major version
1100    pub major: u32,
1101    /// Protocol minor version
1102    pub minor: u32,
1103    /// Alignment padding
1104    pub unused: u32,
1105    /// CUSE flags
1106    pub flags: u32,
1107    /// Max read size
1108    pub max_read: u32,
1109    /// Max write size
1110    pub max_write: u32,
1111    /// Device major version
1112    pub dev_major: u32,
1113    /// Device minor version
1114    pub dev_minor: u32,
1115    /// For future use
1116    pub spare: [u32; 10],
1117}
1118
1119/// FUSE interrupt request input `fuse_interrupt_in`
1120#[derive(Debug)]
1121#[repr(C)]
1122pub struct FuseInterruptIn {
1123    /// Interrupted FUSE request unique ID
1124    pub unique: u64,
1125}
1126
1127/// FUSE bmap request input `fuse_bmap_in`
1128#[derive(Debug)]
1129#[repr(C)]
1130pub struct FuseBMapIn {
1131    /// The block index within file to be mapped
1132    pub block: u64,
1133    /// The unit of block index
1134    pub blocksize: u32,
1135    /// Alignment padding
1136    pub padding: u32,
1137}
1138
1139/// FUSE bmap response `fuse_bmap_out`
1140#[derive(Debug)]
1141#[repr(C)]
1142pub struct FuseBMapOut {
1143    /// The block index to be mapped
1144    pub block: u64,
1145}
1146
1147/// FUSE ioctl request input `fuse_ioctl_in`
1148#[cfg(feature = "abi-7-11")]
1149#[derive(Debug)]
1150#[repr(C)]
1151pub struct FuseIoCtlIn {
1152    /// File handler
1153    pub fh: u64,
1154    /// FUSE ioctl flags
1155    pub flags: u32,
1156    /// FUSE ioctl command
1157    pub cmd: u32,
1158    /// FUSE ioctl command argument
1159    pub arg: u64,
1160    /// The number of fetched bytes
1161    pub in_size: u32,
1162    /// The maximum size of output data
1163    pub out_size: u32,
1164}
1165
1166/// FUSE ioctl iovec `fuse_ioctl_iovec`
1167#[cfg(feature = "abi-7-16")]
1168#[derive(Debug)]
1169#[repr(C)]
1170pub struct FuseIoCtlIoVec {
1171    /// iovec starting address
1172    pub base: u64,
1173    /// Number of bytes to transfer
1174    pub len: u64,
1175}
1176
1177/// FUSE ioctl response `fuse_ioctl_out`
1178#[cfg(feature = "abi-7-11")]
1179#[derive(Debug)]
1180#[repr(C)]
1181pub struct FuseIoCtlOut {
1182    /// Result to be passed to the caller
1183    pub result: i32,
1184    /// `FUSE_IOCTL_*` flags
1185    pub flags: u32,
1186    /// iovec specifying data to fetch from the caller
1187    pub in_iovs: u32,
1188    /// iovec specifying addresses to write output to
1189    pub out_iovs: u32,
1190}
1191
1192/// FUSE poll request input `fuse_poll_in`
1193#[cfg(feature = "abi-7-11")]
1194#[derive(Debug)]
1195#[repr(C)]
1196pub struct FusePollIn {
1197    /// File handler
1198    pub fh: u64,
1199    /// Wakeup handler
1200    pub kh: u64,
1201    /// Poll flags
1202    pub flags: u32,
1203    /// Alignment padding
1204    #[cfg(not(feature = "abi-7-21"))]
1205    pub padding: u32,
1206    /// Poll events
1207    #[cfg(feature = "abi-7-21")]
1208    pub events: u32,
1209}
1210
1211/// FUSE poll response `fuse_poll_out`
1212#[cfg(feature = "abi-7-11")]
1213#[derive(Debug)]
1214#[repr(C)]
1215pub struct FusePollOut {
1216    /// Poll result event mask
1217    pub revents: u32,
1218    /// Padding
1219    pub padding: u32,
1220}
1221
1222/// FUSE notify poll wakeup response `fuse_notify_poll_wakeup_out`
1223#[cfg(feature = "abi-7-11")]
1224#[derive(Debug)]
1225#[repr(C)]
1226pub struct FuseNotifyPollWakeUpOut {
1227    /// Wakeup handler
1228    pub kh: u64,
1229}
1230
1231/// FUSE file allocate request input `fuse_fallocate_in`
1232#[cfg(feature = "abi-7-19")]
1233#[derive(Debug)]
1234#[repr(C)]
1235pub struct FuseFAllocateIn {
1236    /// File handler
1237    pub fh: u64,
1238    /// File allocate offset
1239    pub offset: u64,
1240    /// File allocate length
1241    pub length: u64,
1242    /// File mode
1243    pub mode: u32,
1244    /// Alignment padding
1245    pub padding: u32,
1246}
1247
1248/// FUSE request header `fuse_in_header`
1249#[derive(Debug)]
1250#[repr(C)]
1251pub struct FuseInHeader {
1252    /// Request size
1253    pub len: u32,
1254    /// FUSE operation code
1255    pub opcode: u32,
1256    /// The request unique ID
1257    pub unique: u64,
1258    /// The i-number of the node
1259    pub nodeid: u64,
1260    /// User ID
1261    pub uid: u32,
1262    /// Group ID
1263    pub gid: u32,
1264    /// Process ID
1265    pub pid: u32,
1266    /// Alignment padding
1267    pub padding: u32,
1268}
1269
1270/// FUSE response header `fuse_out_header`
1271#[derive(Debug)]
1272#[repr(C)]
1273pub struct FuseOutHeader {
1274    /// Response size
1275    pub len: u32,
1276    /// Response error code
1277    pub error: i32,
1278    /// The associated request unique ID of this response
1279    pub unique: u64,
1280}
1281
1282/// FUSE directory entry `fuse_dirent`
1283#[derive(Debug)]
1284#[repr(C)]
1285pub struct FuseDirEnt {
1286    /// The i-number of the entry
1287    pub ino: INum,
1288    /// Entry offset in the directory
1289    pub off: u64,
1290    /// Entry name length
1291    pub namelen: u32,
1292    /// Entry type
1293    pub typ: u32,
1294    // Followed by name of namelen bytes
1295    // char name[],
1296}
1297
1298impl FuseDirEnt {
1299    /// Get the exctual size of `FuseDirEnt`,
1300    /// equals to the size of entry header and the length of following name.
1301    ///
1302    /// The behaviour of this method is similar to marco `FUSE_DIRENT_SIZE(d)`
1303    /// in `fuse.h`.
1304    ///
1305    /// <https://github.com/torvalds/linux/blob/00c570f4ba43ae73b41fa0a2269c3b0ac20386ef/include/uapi/linux/fuse.h#L701-L702>
1306    #[must_use]
1307    pub fn size_with_name(&self) -> usize {
1308        mem::size_of::<Self>().overflow_add(self.namelen.cast())
1309    }
1310}
1311
1312/// FUSE directory entry plus `fuse_direntplus`
1313/// used in `readdirplus()`
1314#[cfg(feature = "abi-7-21")]
1315#[derive(Debug)]
1316#[repr(C)]
1317pub struct FuseDirEntPlus {
1318    /// FUSE directory entry extra info
1319    pub entry_out: FuseEntryOut,
1320    /// FUSE directory entry
1321    pub dirent: FuseDirEnt,
1322}
1323
1324#[cfg(feature = "abi-7-21")]
1325impl FuseDirEntPlus {
1326    /// Get the exctual size of `FuseDirEntPlus`,
1327    /// equals to the size of header and the length of following name.
1328    ///
1329    /// The behaviour of this method is similar to marco
1330    /// `FUSE_DIRENTPLUS_SIZE(d)` in `fuse.h`.
1331    ///
1332    /// <https://github.com/torvalds/linux/blob/00c570f4ba43ae73b41fa0a2269c3b0ac20386ef/include/uapi/linux/fuse.h#L711-L712>
1333    ///
1334    /// This method is not used now, that's because the FUSE operation
1335    /// `ReadDirPlus` has not yet been implemented.
1336    #[must_use]
1337    #[allow(dead_code)]
1338    pub fn size_with_name(&self) -> usize {
1339        mem::size_of::<Self>().overflow_add(self.dirent.namelen.cast())
1340    }
1341}
1342
1343/// FUSE notify invalid inode response `fuse_notify_inval_inode_out`
1344#[cfg(feature = "abi-7-12")]
1345#[derive(Debug)]
1346#[repr(C)]
1347pub struct FuseNotifyInvalINodeOut {
1348    /// Node ID
1349    pub ino: INum,
1350    /// Offset
1351    pub off: i64,
1352    /// Length
1353    pub len: i64,
1354}
1355
1356/// FUSE notify invalid entry response `fuse_notify_inval_entry_out`
1357#[cfg(feature = "abi-7-12")]
1358#[derive(Debug)]
1359#[repr(C)]
1360pub struct FuseNotifyInvalEntryOut {
1361    /// Parent inode
1362    pub parent: INum,
1363    /// Name length
1364    pub namelen: u32,
1365    /// Padding
1366    pub padding: u32,
1367}
1368
1369/// Fuse notify delete response `fuse_notify_delete_out`
1370#[cfg(feature = "abi-7-18")]
1371#[derive(Debug)]
1372#[repr(C)]
1373pub struct FuseNotifyDeleteOut {
1374    /// Parent inode
1375    pub parent: INum,
1376    /// Child inode
1377    pub child: INum,
1378    /// Name length
1379    pub namelen: u32,
1380    /// Padding
1381    pub padding: u32,
1382}
1383
1384/// FUSE notify store response `fuse_notify_store_out`
1385#[cfg(feature = "abi-7-15")]
1386#[derive(Debug)]
1387#[repr(C)]
1388pub struct FuseNotifyStoreOut {
1389    /// Node ID
1390    pub nodeid: INum,
1391    /// Offset
1392    pub offset: u64,
1393    /// Size
1394    pub size: u32,
1395    /// Padding
1396    pub padding: u32,
1397}
1398
1399/// FUSE notify retrieve response `fuse_notify_retrieve_out`
1400#[cfg(feature = "abi-7-15")]
1401#[derive(Debug)]
1402#[repr(C)]
1403pub struct FuseNotifyRetrieveOut {
1404    /// Unique ID
1405    pub notify_unique: u64,
1406    /// Node ID
1407    pub nodeid: u64,
1408    /// Offset
1409    pub offset: u64,
1410    /// Size
1411    pub size: u32,
1412    /// Padding
1413    pub padding: u32,
1414}
1415
1416/// FUSE notify retrieve request input `fuse_notify_retrieve_in`
1417/// matches the size of `fuse_write_in`
1418#[cfg(feature = "abi-7-15")]
1419#[derive(Debug)]
1420#[repr(C)]
1421pub struct FuseNotifyRetrieveIn {
1422    /// Padding
1423    pub dummy1: u64,
1424    /// Offset
1425    pub offset: u64,
1426    /// Size
1427    pub size: u32,
1428    /// Padding
1429    pub dummy2: u32,
1430    /// Padding
1431    pub dummy3: u64,
1432    /// Padding
1433    pub dummy4: u64,
1434}
1435
1436/// FUSE lseek request input `fuse_lseek_in`
1437// #[cfg(feature = "abi-7-24")]
1438#[derive(Debug)]
1439#[repr(C)]
1440pub struct FuseLSeekIn {
1441    /// File handler
1442    pub fh: u64,
1443    /// Seek offset
1444    pub offset: u64,
1445    /// The directive that tells lseek what the offset is relative to
1446    pub whence: u32,
1447    /// Alignment padding
1448    pub padding: u32,
1449}
1450
1451/// FUSE lseek response `fuse_lseek_out`
1452// #[cfg(feature = "abi-7-24")]
1453#[derive(Debug)]
1454#[repr(C)]
1455pub struct FuseLSeekOut {
1456    /// Seek offset
1457    pub offset: u64,
1458}
1459
1460/// FUSE copy file range request input `fuse_copy_file_range_in`
1461// #[cfg(feature = "abi-7-28")]
1462#[derive(Debug)]
1463#[repr(C)]
1464pub struct FuseCopyFileRangeIn {
1465    /// The file handler of the source file
1466    pub fh_in: u64,
1467    /// The starting point from were the data should be read
1468    pub off_in: u64,
1469    /// The i-number or the destination file
1470    pub nodeid_out: u64,
1471    /// The file handler of the destination file
1472    pub fh_out: u64,
1473    /// The starting point where the data should be written
1474    pub off_out: u64,
1475    /// The maximum size of the data to copy
1476    pub len: u64,
1477    /// The flags passed along with the `copy_file_range()` syscall
1478    pub flags: u64,
1479}