fuser/ll/
fuse_abi.rs

1//! FUSE kernel interface.
2//!
3//! Types and definitions used for communication between the kernel driver and the userspace
4//! part of a FUSE filesystem. Since the kernel driver may be installed independently, the ABI
5//! interface is versioned and capabilities are exchanged during the initialization (mounting)
6//! of a filesystem.
7//!
8//! OSXFUSE (macOS): <https://github.com/osxfuse/fuse/blob/master/include/fuse_kernel.h>
9//! - supports ABI 7.8 in OSXFUSE 2.x
10//! - supports ABI 7.19 since OSXFUSE 3.0.0
11//!
12//! libfuse (Linux/BSD): <https://github.com/libfuse/libfuse/blob/master/include/fuse_kernel.h>
13//! - supports ABI 7.8 since FUSE 2.6.0
14//! - supports ABI 7.12 since FUSE 2.8.0
15//! - supports ABI 7.18 since FUSE 2.9.0
16//! - supports ABI 7.19 since FUSE 2.9.1
17//! - supports ABI 7.26 since FUSE 3.0.0
18//!
19//! Items without a version annotation are valid with ABI 7.8 and later
20
21#![warn(missing_debug_implementations)]
22#![allow(missing_docs)]
23
24use crate::consts::{FATTR_ATIME_NOW, FATTR_MTIME_NOW};
25use std::convert::TryFrom;
26use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
27
28pub const FUSE_KERNEL_VERSION: u32 = 7;
29
30#[cfg(not(feature = "abi-7-19"))]
31pub const FUSE_KERNEL_MINOR_VERSION: u32 = 18;
32#[cfg(all(feature = "abi-7-19", not(feature = "abi-7-20")))]
33pub const FUSE_KERNEL_MINOR_VERSION: u32 = 19;
34#[cfg(all(feature = "abi-7-20", not(feature = "abi-7-21")))]
35pub const FUSE_KERNEL_MINOR_VERSION: u32 = 20;
36#[cfg(all(feature = "abi-7-21", not(feature = "abi-7-22")))]
37pub const FUSE_KERNEL_MINOR_VERSION: u32 = 21;
38#[cfg(all(feature = "abi-7-22", not(feature = "abi-7-23")))]
39pub const FUSE_KERNEL_MINOR_VERSION: u32 = 22;
40#[cfg(all(feature = "abi-7-23", not(feature = "abi-7-24")))]
41pub const FUSE_KERNEL_MINOR_VERSION: u32 = 23;
42#[cfg(all(feature = "abi-7-24", not(feature = "abi-7-25")))]
43pub const FUSE_KERNEL_MINOR_VERSION: u32 = 24;
44#[cfg(all(feature = "abi-7-25", not(feature = "abi-7-26")))]
45pub const FUSE_KERNEL_MINOR_VERSION: u32 = 25;
46#[cfg(all(feature = "abi-7-26", not(feature = "abi-7-27")))]
47pub const FUSE_KERNEL_MINOR_VERSION: u32 = 26;
48#[cfg(all(feature = "abi-7-27", not(feature = "abi-7-28")))]
49pub const FUSE_KERNEL_MINOR_VERSION: u32 = 27;
50#[cfg(all(feature = "abi-7-28", not(feature = "abi-7-29")))]
51pub const FUSE_KERNEL_MINOR_VERSION: u32 = 28;
52#[cfg(all(feature = "abi-7-29", not(feature = "abi-7-30")))]
53pub const FUSE_KERNEL_MINOR_VERSION: u32 = 29;
54#[cfg(all(feature = "abi-7-30", not(feature = "abi-7-31")))]
55pub const FUSE_KERNEL_MINOR_VERSION: u32 = 30;
56#[cfg(all(feature = "abi-7-31", not(feature = "abi-7-36")))]
57pub const FUSE_KERNEL_MINOR_VERSION: u32 = 31;
58#[cfg(all(feature = "abi-7-36", not(feature = "abi-7-40")))]
59pub const FUSE_KERNEL_MINOR_VERSION: u32 = 36;
60#[cfg(feature = "abi-7-40")]
61pub const FUSE_KERNEL_MINOR_VERSION: u32 = 40;
62
63pub const FUSE_ROOT_ID: u64 = 1;
64
65#[repr(C)]
66#[derive(Debug, IntoBytes, Clone, Copy, KnownLayout, Immutable)]
67pub struct fuse_attr {
68    pub ino: u64,
69    pub size: u64,
70    pub blocks: u64,
71    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
72    // to match stat.st_atime
73    pub atime: i64,
74    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
75    // to match stat.st_mtime
76    pub mtime: i64,
77    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
78    // to match stat.st_ctime
79    pub ctime: i64,
80    #[cfg(target_os = "macos")]
81    pub crtime: u64,
82    pub atimensec: u32,
83    pub mtimensec: u32,
84    pub ctimensec: u32,
85    #[cfg(target_os = "macos")]
86    pub crtimensec: u32,
87    pub mode: u32,
88    pub nlink: u32,
89    pub uid: u32,
90    pub gid: u32,
91    pub rdev: u32,
92    #[cfg(target_os = "macos")]
93    pub flags: u32, // see chflags(2)
94    pub blksize: u32,
95    pub padding: u32,
96}
97
98#[repr(C)]
99#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
100pub struct fuse_kstatfs {
101    pub blocks: u64,  // Total blocks (in units of frsize)
102    pub bfree: u64,   // Free blocks
103    pub bavail: u64,  // Free blocks for unprivileged users
104    pub files: u64,   // Total inodes
105    pub ffree: u64,   // Free inodes
106    pub bsize: u32,   // Filesystem block size
107    pub namelen: u32, // Maximum filename length
108    pub frsize: u32,  // Fundamental file system block size
109    pub padding: u32,
110    pub spare: [u32; 6],
111}
112
113#[repr(C)]
114#[derive(Debug, IntoBytes, FromBytes, KnownLayout, Immutable)]
115pub struct fuse_file_lock {
116    pub start: u64,
117    pub end: u64,
118    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is treated as signed
119    pub typ: i32,
120    pub pid: u32,
121}
122
123pub mod consts {
124    // Bitmasks for fuse_setattr_in.valid
125    pub const FATTR_MODE: u32 = 1 << 0;
126    pub const FATTR_UID: u32 = 1 << 1;
127    pub const FATTR_GID: u32 = 1 << 2;
128    pub const FATTR_SIZE: u32 = 1 << 3;
129    pub const FATTR_ATIME: u32 = 1 << 4;
130    pub const FATTR_MTIME: u32 = 1 << 5;
131    pub const FATTR_FH: u32 = 1 << 6;
132    pub const FATTR_ATIME_NOW: u32 = 1 << 7;
133    pub const FATTR_MTIME_NOW: u32 = 1 << 8;
134    pub const FATTR_LOCKOWNER: u32 = 1 << 9;
135    #[cfg(feature = "abi-7-23")]
136    pub const FATTR_CTIME: u32 = 1 << 10;
137
138    #[cfg(target_os = "macos")]
139    pub const FATTR_CRTIME: u32 = 1 << 28;
140    #[cfg(target_os = "macos")]
141    pub const FATTR_CHGTIME: u32 = 1 << 29;
142    #[cfg(target_os = "macos")]
143    pub const FATTR_BKUPTIME: u32 = 1 << 30;
144    #[cfg(target_os = "macos")]
145    pub const FATTR_FLAGS: u32 = 1 << 31;
146
147    // Flags returned by the open request
148    pub const FOPEN_DIRECT_IO: u32 = 1 << 0; // bypass page cache for this open file
149    pub const FOPEN_KEEP_CACHE: u32 = 1 << 1; // don't invalidate the data cache on open
150    pub const FOPEN_NONSEEKABLE: u32 = 1 << 2; // the file is not seekable
151    #[cfg(feature = "abi-7-28")]
152    pub const FOPEN_CACHE_DIR: u32 = 1 << 3; // allow caching this directory
153    #[cfg(feature = "abi-7-31")]
154    pub const FOPEN_STREAM: u32 = 1 << 4; // the file is stream-like (no file position at all)
155    #[cfg(feature = "abi-7-40")]
156    pub const FOPEN_PASSTHROUGH: u32 = 1 << 7; // the file is fd-backed (via the backing_id field)
157
158    #[cfg(target_os = "macos")]
159    pub const FOPEN_PURGE_ATTR: u32 = 1 << 30;
160    #[cfg(target_os = "macos")]
161    pub const FOPEN_PURGE_UBC: u32 = 1 << 31;
162
163    // Init request/reply flags
164    pub const FUSE_ASYNC_READ: u64 = 1 << 0; // asynchronous read requests
165    pub const FUSE_POSIX_LOCKS: u64 = 1 << 1; // remote locking for POSIX file locks
166    pub const FUSE_FILE_OPS: u64 = 1 << 2; // kernel sends file handle for fstat, etc...
167    pub const FUSE_ATOMIC_O_TRUNC: u64 = 1 << 3; // handles the O_TRUNC open flag in the filesystem
168    pub const FUSE_EXPORT_SUPPORT: u64 = 1 << 4; // filesystem handles lookups of "." and ".."
169    pub const FUSE_BIG_WRITES: u64 = 1 << 5; // filesystem can handle write size larger than 4kB
170    pub const FUSE_DONT_MASK: u64 = 1 << 6; // don't apply umask to file mode on create operations
171    pub const FUSE_SPLICE_WRITE: u64 = 1 << 7; // kernel supports splice write on the device
172    pub const FUSE_SPLICE_MOVE: u64 = 1 << 8; // kernel supports splice move on the device
173    pub const FUSE_SPLICE_READ: u64 = 1 << 9; // kernel supports splice read on the device
174    pub const FUSE_FLOCK_LOCKS: u64 = 1 << 10; // remote locking for BSD style file locks
175    pub const FUSE_HAS_IOCTL_DIR: u64 = 1 << 11; // kernel supports ioctl on directories
176    #[cfg(feature = "abi-7-20")]
177    pub const FUSE_AUTO_INVAL_DATA: u64 = 1 << 12; // automatically invalidate cached pages
178    #[cfg(feature = "abi-7-21")]
179    pub const FUSE_DO_READDIRPLUS: u64 = 1 << 13; // do READDIRPLUS (READDIR+LOOKUP in one)
180    #[cfg(feature = "abi-7-21")]
181    pub const FUSE_READDIRPLUS_AUTO: u64 = 1 << 14; // adaptive readdirplus
182    #[cfg(feature = "abi-7-22")]
183    pub const FUSE_ASYNC_DIO: u64 = 1 << 15; // asynchronous direct I/O submission
184    #[cfg(feature = "abi-7-23")]
185    pub const FUSE_WRITEBACK_CACHE: u64 = 1 << 16; // use writeback cache for buffered writes
186    #[cfg(feature = "abi-7-23")]
187    pub const FUSE_NO_OPEN_SUPPORT: u64 = 1 << 17; // kernel supports zero-message opens
188    #[cfg(feature = "abi-7-25")]
189    pub const FUSE_PARALLEL_DIROPS: u64 = 1 << 18; // allow parallel lookups and readdir
190    #[cfg(feature = "abi-7-26")]
191    pub const FUSE_HANDLE_KILLPRIV: u64 = 1 << 19; // fs handles killing suid/sgid/cap on write/chown/trunc
192    #[cfg(feature = "abi-7-26")]
193    pub const FUSE_POSIX_ACL: u64 = 1 << 20; // filesystem supports posix acls
194    #[cfg(feature = "abi-7-27")]
195    pub const FUSE_ABORT_ERROR: u64 = 1 << 21; // reading the device after abort returns ECONNABORTED
196    #[cfg(feature = "abi-7-28")]
197    pub const FUSE_MAX_PAGES: u64 = 1 << 22; // init_out.max_pages contains the max number of req pages
198    #[cfg(feature = "abi-7-28")]
199    pub const FUSE_CACHE_SYMLINKS: u64 = 1 << 23; // cache READLINK responses
200    #[cfg(feature = "abi-7-29")]
201    pub const FUSE_NO_OPENDIR_SUPPORT: u64 = 1 << 24; // kernel supports zero-message opendir
202    #[cfg(feature = "abi-7-30")]
203    pub const FUSE_EXPLICIT_INVAL_DATA: u64 = 1 << 25; // only invalidate cached pages on explicit request
204    #[cfg(feature = "abi-7-36")]
205    pub const FUSE_INIT_EXT: u64 = 1 << 30; // extended fuse_init_in request
206    #[cfg(feature = "abi-7-36")]
207    pub const FUSE_INIT_RESERVED: u64 = 1 << 31; // reserved, do not use
208    #[cfg(feature = "abi-7-40")]
209    pub const FUSE_PASSTHROUGH: u64 = 1 << 37; // filesystem wants to use passthrough files
210
211    #[cfg(target_os = "macos")]
212    pub const FUSE_ALLOCATE: u64 = 1 << 27;
213    #[cfg(target_os = "macos")]
214    pub const FUSE_EXCHANGE_DATA: u64 = 1 << 28;
215    #[cfg(target_os = "macos")]
216    pub const FUSE_CASE_INSENSITIVE: u64 = 1 << 29;
217    #[cfg(target_os = "macos")]
218    pub const FUSE_VOL_RENAME: u64 = 1 << 30;
219    #[cfg(target_os = "macos")]
220    pub const FUSE_XTIMES: u64 = 1 << 31;
221
222    // CUSE init request/reply flags
223    pub const CUSE_UNRESTRICTED_IOCTL: u32 = 1 << 0; // use unrestricted ioctl
224
225    // Release flags
226    pub const FUSE_RELEASE_FLUSH: u32 = 1 << 0;
227    pub const FUSE_RELEASE_FLOCK_UNLOCK: u32 = 1 << 1;
228
229    // Getattr flags
230    pub const FUSE_GETATTR_FH: u32 = 1 << 0;
231
232    // Lock flags
233    pub const FUSE_LK_FLOCK: u32 = 1 << 0;
234
235    // Write flags
236    pub const FUSE_WRITE_CACHE: u32 = 1 << 0; // delayed write from page cache, file handle is guessed
237    pub const FUSE_WRITE_LOCKOWNER: u32 = 1 << 1; // lock_owner field is valid
238    #[cfg(feature = "abi-7-31")]
239    pub const FUSE_WRITE_KILL_PRIV: u32 = 1 << 2; // kill suid and sgid bits
240
241    // Read flags
242    pub const FUSE_READ_LOCKOWNER: u32 = 1 << 1;
243
244    // IOCTL flags
245    pub const FUSE_IOCTL_COMPAT: u32 = 1 << 0; // 32bit compat ioctl on 64bit machine
246    pub const FUSE_IOCTL_UNRESTRICTED: u32 = 1 << 1; // not restricted to well-formed ioctls, retry allowed
247    pub const FUSE_IOCTL_RETRY: u32 = 1 << 2; // retry with new iovecs
248    pub const FUSE_IOCTL_32BIT: u32 = 1 << 3; // 32bit ioctl
249    pub const FUSE_IOCTL_DIR: u32 = 1 << 4; // is a directory
250    #[cfg(feature = "abi-7-30")]
251    pub const FUSE_IOCTL_COMPAT_X32: u32 = 1 << 5; // x32 compat ioctl on 64bit machine (64bit time_t)
252    pub const FUSE_IOCTL_MAX_IOV: u32 = 256; // maximum of in_iovecs + out_iovecs
253
254    // Poll flags
255    pub const FUSE_POLL_SCHEDULE_NOTIFY: u32 = 1 << 0; // request poll notify
256
257    // fsync flags
258    pub const FUSE_FSYNC_FDATASYNC: u32 = 1 << 0; // Sync data only, not metadata
259
260    // The read buffer is required to be at least 8k, but may be much larger
261    pub const FUSE_MIN_READ_BUFFER: usize = 8192;
262}
263
264/// Invalid opcode error.
265#[derive(Debug)]
266pub struct InvalidOpcodeError;
267
268#[repr(C)]
269#[derive(Debug)]
270#[allow(non_camel_case_types)]
271pub enum fuse_opcode {
272    FUSE_LOOKUP = 1,
273    FUSE_FORGET = 2, // no reply
274    FUSE_GETATTR = 3,
275    FUSE_SETATTR = 4,
276    FUSE_READLINK = 5,
277    FUSE_SYMLINK = 6,
278    FUSE_MKNOD = 8,
279    FUSE_MKDIR = 9,
280    FUSE_UNLINK = 10,
281    FUSE_RMDIR = 11,
282    FUSE_RENAME = 12,
283    FUSE_LINK = 13,
284    FUSE_OPEN = 14,
285    FUSE_READ = 15,
286    FUSE_WRITE = 16,
287    FUSE_STATFS = 17,
288    FUSE_RELEASE = 18,
289    FUSE_FSYNC = 20,
290    FUSE_SETXATTR = 21,
291    FUSE_GETXATTR = 22,
292    FUSE_LISTXATTR = 23,
293    FUSE_REMOVEXATTR = 24,
294    FUSE_FLUSH = 25,
295    FUSE_INIT = 26,
296    FUSE_OPENDIR = 27,
297    FUSE_READDIR = 28,
298    FUSE_RELEASEDIR = 29,
299    FUSE_FSYNCDIR = 30,
300    FUSE_GETLK = 31,
301    FUSE_SETLK = 32,
302    FUSE_SETLKW = 33,
303    FUSE_ACCESS = 34,
304    FUSE_CREATE = 35,
305    FUSE_INTERRUPT = 36,
306    FUSE_BMAP = 37,
307    FUSE_DESTROY = 38,
308    FUSE_IOCTL = 39,
309    FUSE_POLL = 40,
310    FUSE_NOTIFY_REPLY = 41,
311    FUSE_BATCH_FORGET = 42,
312    #[cfg(feature = "abi-7-19")]
313    FUSE_FALLOCATE = 43,
314    #[cfg(feature = "abi-7-21")]
315    FUSE_READDIRPLUS = 44,
316    #[cfg(feature = "abi-7-23")]
317    FUSE_RENAME2 = 45,
318    #[cfg(feature = "abi-7-24")]
319    FUSE_LSEEK = 46,
320    #[cfg(feature = "abi-7-28")]
321    FUSE_COPY_FILE_RANGE = 47,
322
323    #[cfg(target_os = "macos")]
324    FUSE_SETVOLNAME = 61,
325    #[cfg(target_os = "macos")]
326    FUSE_GETXTIMES = 62,
327    #[cfg(target_os = "macos")]
328    FUSE_EXCHANGE = 63,
329
330    CUSE_INIT = 4096,
331}
332
333impl TryFrom<u32> for fuse_opcode {
334    type Error = InvalidOpcodeError;
335
336    fn try_from(n: u32) -> Result<Self, Self::Error> {
337        match n {
338            1 => Ok(fuse_opcode::FUSE_LOOKUP),
339            2 => Ok(fuse_opcode::FUSE_FORGET),
340            3 => Ok(fuse_opcode::FUSE_GETATTR),
341            4 => Ok(fuse_opcode::FUSE_SETATTR),
342            5 => Ok(fuse_opcode::FUSE_READLINK),
343            6 => Ok(fuse_opcode::FUSE_SYMLINK),
344            8 => Ok(fuse_opcode::FUSE_MKNOD),
345            9 => Ok(fuse_opcode::FUSE_MKDIR),
346            10 => Ok(fuse_opcode::FUSE_UNLINK),
347            11 => Ok(fuse_opcode::FUSE_RMDIR),
348            12 => Ok(fuse_opcode::FUSE_RENAME),
349            13 => Ok(fuse_opcode::FUSE_LINK),
350            14 => Ok(fuse_opcode::FUSE_OPEN),
351            15 => Ok(fuse_opcode::FUSE_READ),
352            16 => Ok(fuse_opcode::FUSE_WRITE),
353            17 => Ok(fuse_opcode::FUSE_STATFS),
354            18 => Ok(fuse_opcode::FUSE_RELEASE),
355            20 => Ok(fuse_opcode::FUSE_FSYNC),
356            21 => Ok(fuse_opcode::FUSE_SETXATTR),
357            22 => Ok(fuse_opcode::FUSE_GETXATTR),
358            23 => Ok(fuse_opcode::FUSE_LISTXATTR),
359            24 => Ok(fuse_opcode::FUSE_REMOVEXATTR),
360            25 => Ok(fuse_opcode::FUSE_FLUSH),
361            26 => Ok(fuse_opcode::FUSE_INIT),
362            27 => Ok(fuse_opcode::FUSE_OPENDIR),
363            28 => Ok(fuse_opcode::FUSE_READDIR),
364            29 => Ok(fuse_opcode::FUSE_RELEASEDIR),
365            30 => Ok(fuse_opcode::FUSE_FSYNCDIR),
366            31 => Ok(fuse_opcode::FUSE_GETLK),
367            32 => Ok(fuse_opcode::FUSE_SETLK),
368            33 => Ok(fuse_opcode::FUSE_SETLKW),
369            34 => Ok(fuse_opcode::FUSE_ACCESS),
370            35 => Ok(fuse_opcode::FUSE_CREATE),
371            36 => Ok(fuse_opcode::FUSE_INTERRUPT),
372            37 => Ok(fuse_opcode::FUSE_BMAP),
373            38 => Ok(fuse_opcode::FUSE_DESTROY),
374            39 => Ok(fuse_opcode::FUSE_IOCTL),
375            40 => Ok(fuse_opcode::FUSE_POLL),
376            41 => Ok(fuse_opcode::FUSE_NOTIFY_REPLY),
377            42 => Ok(fuse_opcode::FUSE_BATCH_FORGET),
378            #[cfg(feature = "abi-7-19")]
379            43 => Ok(fuse_opcode::FUSE_FALLOCATE),
380            #[cfg(feature = "abi-7-21")]
381            44 => Ok(fuse_opcode::FUSE_READDIRPLUS),
382            #[cfg(feature = "abi-7-23")]
383            45 => Ok(fuse_opcode::FUSE_RENAME2),
384            #[cfg(feature = "abi-7-24")]
385            46 => Ok(fuse_opcode::FUSE_LSEEK),
386            #[cfg(feature = "abi-7-28")]
387            47 => Ok(fuse_opcode::FUSE_COPY_FILE_RANGE),
388
389            #[cfg(target_os = "macos")]
390            61 => Ok(fuse_opcode::FUSE_SETVOLNAME),
391            #[cfg(target_os = "macos")]
392            62 => Ok(fuse_opcode::FUSE_GETXTIMES),
393            #[cfg(target_os = "macos")]
394            63 => Ok(fuse_opcode::FUSE_EXCHANGE),
395
396            4096 => Ok(fuse_opcode::CUSE_INIT),
397
398            _ => Err(InvalidOpcodeError),
399        }
400    }
401}
402
403/// Invalid notify code error.
404#[derive(Debug)]
405pub struct InvalidNotifyCodeError;
406
407#[repr(C)]
408#[derive(Debug)]
409#[allow(non_camel_case_types)]
410pub enum fuse_notify_code {
411    FUSE_POLL = 1,
412    FUSE_NOTIFY_INVAL_INODE = 2,
413    FUSE_NOTIFY_INVAL_ENTRY = 3,
414    FUSE_NOTIFY_STORE = 4,
415    FUSE_NOTIFY_RETRIEVE = 5,
416    FUSE_NOTIFY_DELETE = 6,
417}
418
419impl TryFrom<u32> for fuse_notify_code {
420    type Error = InvalidNotifyCodeError;
421
422    fn try_from(n: u32) -> Result<Self, Self::Error> {
423        match n {
424            1 => Ok(fuse_notify_code::FUSE_POLL),
425            2 => Ok(fuse_notify_code::FUSE_NOTIFY_INVAL_INODE),
426            3 => Ok(fuse_notify_code::FUSE_NOTIFY_INVAL_ENTRY),
427            4 => Ok(fuse_notify_code::FUSE_NOTIFY_STORE),
428            5 => Ok(fuse_notify_code::FUSE_NOTIFY_RETRIEVE),
429            6 => Ok(fuse_notify_code::FUSE_NOTIFY_DELETE),
430
431            _ => Err(InvalidNotifyCodeError),
432        }
433    }
434}
435
436#[repr(C)]
437#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
438pub struct fuse_entry_out {
439    pub nodeid: u64,
440    pub generation: u64,
441    pub entry_valid: u64,
442    pub attr_valid: u64,
443    pub entry_valid_nsec: u32,
444    pub attr_valid_nsec: u32,
445    pub attr: fuse_attr,
446}
447
448#[repr(C)]
449#[derive(Debug, FromBytes, KnownLayout, Immutable)]
450pub struct fuse_forget_in {
451    pub nlookup: u64,
452}
453
454#[repr(C)]
455#[derive(Debug, FromBytes, KnownLayout, Immutable)]
456pub struct fuse_forget_one {
457    pub nodeid: u64,
458    pub nlookup: u64,
459}
460
461#[repr(C)]
462#[derive(Debug, FromBytes, KnownLayout, Immutable)]
463pub struct fuse_batch_forget_in {
464    pub count: u32,
465    pub dummy: u32,
466}
467
468#[repr(C)]
469#[derive(Debug, FromBytes, KnownLayout, Immutable)]
470pub struct fuse_getattr_in {
471    pub getattr_flags: u32,
472    pub dummy: u32,
473    pub fh: u64,
474}
475
476#[repr(C)]
477#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
478pub struct fuse_attr_out {
479    pub attr_valid: u64,
480    pub attr_valid_nsec: u32,
481    pub dummy: u32,
482    pub attr: fuse_attr,
483}
484
485#[cfg(target_os = "macos")]
486#[repr(C)]
487#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
488pub struct fuse_getxtimes_out {
489    pub bkuptime: u64,
490    pub crtime: u64,
491    pub bkuptimensec: u32,
492    pub crtimensec: u32,
493}
494
495#[repr(C)]
496#[derive(Debug, FromBytes, KnownLayout, Immutable)]
497pub struct fuse_mknod_in {
498    pub mode: u32,
499    pub rdev: u32,
500    pub umask: u32,
501    pub padding: u32,
502}
503
504#[repr(C)]
505#[derive(Debug, FromBytes, KnownLayout, Immutable)]
506pub struct fuse_mkdir_in {
507    pub mode: u32,
508    pub umask: u32,
509}
510
511#[repr(C)]
512#[derive(Debug, FromBytes, KnownLayout, Immutable)]
513pub struct fuse_rename_in {
514    pub newdir: u64,
515    #[cfg(feature = "macfuse-4-compat")]
516    pub flags: u32,
517    #[cfg(feature = "macfuse-4-compat")]
518    pub padding: u32,
519}
520
521#[repr(C)]
522#[derive(Debug, FromBytes, KnownLayout, Immutable)]
523pub struct fuse_rename2_in {
524    pub newdir: u64,
525    pub flags: u32,
526    pub padding: u32,
527}
528
529#[cfg(target_os = "macos")]
530#[repr(C)]
531#[derive(Debug, FromBytes, KnownLayout, Immutable)]
532pub struct fuse_exchange_in {
533    pub olddir: u64,
534    pub newdir: u64,
535    pub options: u64,
536}
537
538#[repr(C)]
539#[derive(Debug, FromBytes, KnownLayout, Immutable)]
540pub struct fuse_link_in {
541    pub oldnodeid: u64,
542}
543
544#[repr(C)]
545#[derive(Debug, FromBytes, KnownLayout, Immutable)]
546pub struct fuse_setattr_in {
547    pub valid: u32,
548    pub padding: u32,
549    pub fh: u64,
550    pub size: u64,
551    pub lock_owner: u64,
552    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
553    // to match stat.st_atime
554    pub atime: i64,
555    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
556    // to match stat.st_mtime
557    pub mtime: i64,
558    #[cfg(not(feature = "abi-7-23"))]
559    pub unused2: u64,
560    #[cfg(feature = "abi-7-23")]
561    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
562    // to match stat.st_ctime
563    pub ctime: i64,
564    pub atimensec: u32,
565    pub mtimensec: u32,
566    #[cfg(not(feature = "abi-7-23"))]
567    pub unused3: u32,
568    #[cfg(feature = "abi-7-23")]
569    pub ctimensec: u32,
570    pub mode: u32,
571    pub unused4: u32,
572    pub uid: u32,
573    pub gid: u32,
574    pub unused5: u32,
575    #[cfg(target_os = "macos")]
576    pub bkuptime: u64,
577    #[cfg(target_os = "macos")]
578    pub chgtime: u64,
579    #[cfg(target_os = "macos")]
580    pub crtime: u64,
581    #[cfg(target_os = "macos")]
582    pub bkuptimensec: u32,
583    #[cfg(target_os = "macos")]
584    pub chgtimensec: u32,
585    #[cfg(target_os = "macos")]
586    pub crtimensec: u32,
587    #[cfg(target_os = "macos")]
588    pub flags: u32, // see chflags(2)
589}
590
591impl fuse_setattr_in {
592    pub fn atime_now(&self) -> bool {
593        self.valid & FATTR_ATIME_NOW != 0
594    }
595
596    pub fn mtime_now(&self) -> bool {
597        self.valid & FATTR_MTIME_NOW != 0
598    }
599}
600
601#[repr(C)]
602#[derive(Debug, FromBytes, KnownLayout, Immutable)]
603pub struct fuse_open_in {
604    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
605    // to an i32 when invoking the filesystem's open method and this matches the open() syscall
606    pub flags: i32,
607    pub unused: u32,
608}
609
610#[repr(C)]
611#[derive(Debug, FromBytes, KnownLayout, Immutable)]
612pub struct fuse_create_in {
613    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
614    // to an i32 when invoking the filesystem's create method and this matches the open() syscall
615    pub flags: i32,
616    pub mode: u32,
617    pub umask: u32,
618    pub padding: u32,
619}
620
621#[repr(C)]
622#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
623pub struct fuse_create_out(pub fuse_entry_out, pub fuse_open_out);
624
625#[repr(C)]
626#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
627pub struct fuse_open_out {
628    pub fh: u64,
629    pub open_flags: u32,
630    #[cfg(not(feature = "abi-7-40"))]
631    pub padding: u32,
632    #[cfg(feature = "abi-7-40")]
633    pub backing_id: u32,
634}
635
636#[repr(C)]
637#[derive(Debug, FromBytes, KnownLayout, Immutable)]
638pub struct fuse_release_in {
639    pub fh: u64,
640    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
641    // to an i32 when invoking the filesystem's read method
642    pub flags: i32,
643    pub release_flags: u32,
644    pub lock_owner: u64,
645}
646
647#[repr(C)]
648#[derive(Debug, FromBytes, KnownLayout, Immutable)]
649pub struct fuse_flush_in {
650    pub fh: u64,
651    pub unused: u32,
652    pub padding: u32,
653    pub lock_owner: u64,
654}
655
656#[repr(C)]
657#[derive(Debug, FromBytes, KnownLayout, Immutable)]
658pub struct fuse_read_in {
659    pub fh: u64,
660    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is then cast
661    // to an i64 when invoking the filesystem's read method
662    pub offset: i64,
663    pub size: u32,
664    pub read_flags: u32,
665    pub lock_owner: u64,
666    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
667    // to an i32 when invoking the filesystem's read method
668    pub flags: i32,
669    pub padding: u32,
670}
671
672#[repr(C)]
673#[derive(Debug, FromBytes, KnownLayout, Immutable)]
674pub struct fuse_write_in {
675    pub fh: u64,
676    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is then cast
677    // to an i64 when invoking the filesystem's write method
678    pub offset: i64,
679    pub size: u32,
680    pub write_flags: u32,
681    pub lock_owner: u64,
682    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
683    // to an i32 when invoking the filesystem's read method
684    pub flags: i32,
685    pub padding: u32,
686}
687
688#[repr(C)]
689#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
690pub struct fuse_write_out {
691    pub size: u32,
692    pub padding: u32,
693}
694
695#[repr(C)]
696#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
697pub struct fuse_statfs_out {
698    pub st: fuse_kstatfs,
699}
700
701#[repr(C)]
702#[derive(Debug, FromBytes, KnownLayout, Immutable)]
703pub struct fuse_fsync_in {
704    pub fh: u64,
705    pub fsync_flags: u32,
706    pub padding: u32,
707}
708
709#[repr(C)]
710#[derive(Debug, FromBytes, KnownLayout, Immutable)]
711pub struct fuse_setxattr_in {
712    pub size: u32,
713    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
714    // to an i32 when invoking the filesystem's setxattr method
715    pub flags: i32,
716    #[cfg(target_os = "macos")]
717    pub position: u32,
718    #[cfg(target_os = "macos")]
719    pub padding: u32,
720}
721
722#[repr(C)]
723#[derive(Debug, FromBytes, KnownLayout, Immutable)]
724pub struct fuse_getxattr_in {
725    pub size: u32,
726    pub padding: u32,
727    #[cfg(target_os = "macos")]
728    pub position: u32,
729    #[cfg(target_os = "macos")]
730    pub padding2: u32,
731}
732
733#[repr(C)]
734#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
735pub struct fuse_getxattr_out {
736    pub size: u32,
737    pub padding: u32,
738}
739
740#[repr(C)]
741#[derive(Debug, FromBytes, KnownLayout, Immutable)]
742pub struct fuse_lk_in {
743    pub fh: u64,
744    pub owner: u64,
745    pub lk: fuse_file_lock,
746    pub lk_flags: u32,
747    pub padding: u32,
748}
749
750#[repr(C)]
751#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
752pub struct fuse_lk_out {
753    pub lk: fuse_file_lock,
754}
755
756#[repr(C)]
757#[derive(Debug, FromBytes, KnownLayout, Immutable)]
758pub struct fuse_access_in {
759    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is then cast
760    // to an i32 when invoking the filesystem's access method
761    pub mask: i32,
762    pub padding: u32,
763}
764
765#[repr(C)]
766#[derive(Debug, FromBytes, KnownLayout, Immutable)]
767pub struct fuse_init_in {
768    pub major: u32,
769    pub minor: u32,
770    pub max_readahead: u32,
771    pub flags: u32,
772    #[cfg(feature = "abi-7-36")]
773    pub flags2: u32,
774    #[cfg(feature = "abi-7-36")]
775    pub unused: [u32; 11],
776}
777
778#[repr(C)]
779#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
780pub struct fuse_init_out {
781    pub major: u32,
782    pub minor: u32,
783    pub max_readahead: u32,
784    pub flags: u32,
785    pub max_background: u16,
786    pub congestion_threshold: u16,
787    pub max_write: u32,
788    #[cfg(feature = "abi-7-23")]
789    pub time_gran: u32,
790    #[cfg(all(feature = "abi-7-23", not(feature = "abi-7-28")))]
791    pub reserved: [u32; 9],
792    #[cfg(feature = "abi-7-28")]
793    pub max_pages: u16,
794    #[cfg(feature = "abi-7-28")]
795    pub unused2: u16,
796    #[cfg(all(feature = "abi-7-28", not(feature = "abi-7-36")))]
797    pub reserved: [u32; 8],
798    #[cfg(feature = "abi-7-36")]
799    pub flags2: u32,
800    #[cfg(all(feature = "abi-7-36", not(feature = "abi-7-40")))]
801    pub reserved: [u32; 7],
802    #[cfg(feature = "abi-7-40")]
803    pub max_stack_depth: u32,
804    #[cfg(feature = "abi-7-40")]
805    pub reserved: [u32; 6],
806}
807
808#[repr(C)]
809#[derive(Debug, FromBytes, KnownLayout, Immutable)]
810pub struct cuse_init_in {
811    pub major: u32,
812    pub minor: u32,
813    pub unused: u32,
814    pub flags: u32,
815}
816
817#[repr(C)]
818#[derive(Debug, KnownLayout, Immutable)]
819pub struct cuse_init_out {
820    pub major: u32,
821    pub minor: u32,
822    pub unused: u32,
823    pub flags: u32,
824    pub max_read: u32,
825    pub max_write: u32,
826    pub dev_major: u32, // chardev major
827    pub dev_minor: u32, // chardev minor
828    pub spare: [u32; 10],
829}
830
831#[repr(C)]
832#[derive(Debug, FromBytes, KnownLayout, Immutable)]
833pub struct fuse_interrupt_in {
834    pub unique: u64,
835}
836
837#[repr(C)]
838#[derive(Debug, FromBytes, KnownLayout, Immutable)]
839pub struct fuse_bmap_in {
840    pub block: u64,
841    pub blocksize: u32,
842    pub padding: u32,
843}
844
845#[repr(C)]
846#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
847pub struct fuse_bmap_out {
848    pub block: u64,
849}
850
851#[repr(C)]
852#[derive(Debug, FromBytes, KnownLayout, Immutable)]
853pub struct fuse_ioctl_in {
854    pub fh: u64,
855    pub flags: u32,
856    pub cmd: u32,
857    pub arg: u64, // TODO: this is currently unused, but is defined as a void* in libfuse
858    pub in_size: u32,
859    pub out_size: u32,
860}
861
862#[repr(C)]
863#[derive(Debug, KnownLayout, Immutable)]
864pub struct fuse_ioctl_iovec {
865    pub base: u64,
866    pub len: u64,
867}
868
869#[repr(C)]
870#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
871pub struct fuse_ioctl_out {
872    pub result: i32,
873    pub flags: u32,
874    pub in_iovs: u32,
875    pub out_iovs: u32,
876}
877
878#[repr(C)]
879#[derive(Debug, FromBytes, KnownLayout, Immutable)]
880pub struct fuse_poll_in {
881    pub fh: u64,
882    pub kh: u64,
883    pub flags: u32,
884    #[cfg(not(feature = "abi-7-21"))]
885    pub padding: u32,
886    #[cfg(feature = "abi-7-21")]
887    pub events: u32,
888}
889
890#[repr(C)]
891#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
892pub struct fuse_poll_out {
893    pub revents: u32,
894    pub padding: u32,
895}
896
897#[repr(C)]
898#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
899pub struct fuse_notify_poll_wakeup_out {
900    pub kh: u64,
901}
902
903#[cfg(feature = "abi-7-19")]
904#[repr(C)]
905#[derive(Debug, FromBytes, KnownLayout, Immutable)]
906pub struct fuse_fallocate_in {
907    pub fh: u64,
908    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
909    pub offset: i64,
910    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
911    pub length: i64,
912    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is treated as signed
913    pub mode: i32,
914    pub padding: u32,
915}
916
917#[repr(C)]
918#[derive(Debug, FromBytes, KnownLayout, Immutable)]
919pub struct fuse_in_header {
920    pub len: u32,
921    pub opcode: u32,
922    pub unique: u64,
923    pub nodeid: u64,
924    pub uid: u32,
925    pub gid: u32,
926    pub pid: u32,
927    pub padding: u32,
928}
929
930#[repr(C)]
931#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
932pub struct fuse_out_header {
933    pub len: u32,
934    pub error: i32,
935    pub unique: u64,
936}
937
938#[repr(C)]
939#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
940pub struct fuse_dirent {
941    pub ino: u64,
942    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
943    pub off: i64,
944    pub namelen: u32,
945    pub typ: u32,
946    // followed by name of namelen bytes
947}
948
949#[repr(C)]
950#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
951pub struct fuse_direntplus {
952    pub entry_out: fuse_entry_out,
953    pub dirent: fuse_dirent,
954}
955
956#[repr(C)]
957#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
958pub struct fuse_notify_inval_inode_out {
959    pub ino: u64,
960    pub off: i64,
961    pub len: i64,
962}
963
964#[repr(C)]
965#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
966pub struct fuse_notify_inval_entry_out {
967    pub parent: u64,
968    pub namelen: u32,
969    pub padding: u32,
970}
971
972#[repr(C)]
973#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
974pub struct fuse_notify_delete_out {
975    pub parent: u64,
976    pub child: u64,
977    pub namelen: u32,
978    pub padding: u32,
979}
980
981#[repr(C)]
982#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
983pub struct fuse_notify_store_out {
984    pub nodeid: u64,
985    pub offset: u64,
986    pub size: u32,
987    pub padding: u32,
988}
989
990#[repr(C)]
991#[derive(Debug, KnownLayout, Immutable)]
992pub struct fuse_notify_retrieve_out {
993    pub notify_unique: u64,
994    pub nodeid: u64,
995    pub offset: u64,
996    pub size: u32,
997    pub padding: u32,
998}
999
1000#[repr(C)]
1001#[derive(Debug, FromBytes, KnownLayout, Immutable)]
1002pub struct fuse_notify_retrieve_in {
1003    // matches the size of fuse_write_in
1004    pub dummy1: u64,
1005    pub offset: u64,
1006    pub size: u32,
1007    pub dummy2: u32,
1008    pub dummy3: u64,
1009    pub dummy4: u64,
1010}
1011
1012#[repr(C)]
1013#[derive(Debug, FromBytes, KnownLayout, Immutable)]
1014pub struct fuse_lseek_in {
1015    pub fh: u64,
1016    pub offset: i64,
1017    // NOTE: this field is defined as u32 in fuse_kernel.h in libfuse. However, it is treated as signed
1018    pub whence: i32,
1019    pub padding: u32,
1020}
1021
1022#[repr(C)]
1023#[derive(Debug, IntoBytes, KnownLayout, Immutable)]
1024pub struct fuse_lseek_out {
1025    pub offset: i64,
1026}
1027
1028#[repr(C)]
1029#[derive(Debug, FromBytes, KnownLayout, Immutable)]
1030pub struct fuse_copy_file_range_in {
1031    pub fh_in: u64,
1032    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
1033    pub off_in: i64,
1034    pub nodeid_out: u64,
1035    pub fh_out: u64,
1036    // NOTE: this field is defined as u64 in fuse_kernel.h in libfuse. However, it is treated as signed
1037    pub off_out: i64,
1038    pub len: u64,
1039    pub flags: u64,
1040}