1#![allow(
10 clippy::cast_sign_loss,
11 clippy::cast_possible_wrap,
12 clippy::cast_possible_truncation
13)]
14
15use std::mem::size_of;
16
17pub const FUSE_KERNEL_VERSION: u32 = 7;
23
24pub const FUSE_KERNEL_MINOR_VERSION: u32 = 38;
26
27pub const FUSE_ROOT_ID: u64 = 1;
29
30pub const FUSE_ASYNC_READ: u32 = 1 << 0;
32pub const FUSE_POSIX_LOCKS: u32 = 1 << 1;
33pub const FUSE_FILE_OPS: u32 = 1 << 2;
34pub const FUSE_ATOMIC_O_TRUNC: u32 = 1 << 3;
35pub const FUSE_EXPORT_SUPPORT: u32 = 1 << 4;
36pub const FUSE_BIG_WRITES: u32 = 1 << 5;
37pub const FUSE_DONT_MASK: u32 = 1 << 6;
38pub const FUSE_SPLICE_WRITE: u32 = 1 << 7;
39pub const FUSE_SPLICE_MOVE: u32 = 1 << 8;
40pub const FUSE_SPLICE_READ: u32 = 1 << 9;
41pub const FUSE_FLOCK_LOCKS: u32 = 1 << 10;
42pub const FUSE_HAS_IOCTL_DIR: u32 = 1 << 11;
43pub const FUSE_AUTO_INVAL_DATA: u32 = 1 << 12;
44pub const FUSE_DO_READDIRPLUS: u32 = 1 << 13;
45pub const FUSE_READDIRPLUS_AUTO: u32 = 1 << 14;
46pub const FUSE_ASYNC_DIO: u32 = 1 << 15;
47pub const FUSE_WRITEBACK_CACHE: u32 = 1 << 16;
48pub const FUSE_NO_OPEN_SUPPORT: u32 = 1 << 17;
49pub const FUSE_PARALLEL_DIROPS: u32 = 1 << 18;
50pub const FUSE_HANDLE_KILLPRIV: u32 = 1 << 19;
51pub const FUSE_POSIX_ACL: u32 = 1 << 20;
52pub const FUSE_ABORT_ERROR: u32 = 1 << 21;
53pub const FUSE_MAX_PAGES: u32 = 1 << 22;
54pub const FUSE_CACHE_SYMLINKS: u32 = 1 << 23;
55pub const FUSE_NO_OPENDIR_SUPPORT: u32 = 1 << 24;
56pub const FUSE_EXPLICIT_INVAL_DATA: u32 = 1 << 25;
57
58pub const FATTR_MODE: u32 = 1 << 0;
60pub const FATTR_UID: u32 = 1 << 1;
61pub const FATTR_GID: u32 = 1 << 2;
62pub const FATTR_SIZE: u32 = 1 << 3;
63pub const FATTR_ATIME: u32 = 1 << 4;
64pub const FATTR_MTIME: u32 = 1 << 5;
65pub const FATTR_FH: u32 = 1 << 6;
66pub const FATTR_ATIME_NOW: u32 = 1 << 7;
67pub const FATTR_MTIME_NOW: u32 = 1 << 8;
68pub const FATTR_LOCKOWNER: u32 = 1 << 9;
69pub const FATTR_CTIME: u32 = 1 << 10;
70
71pub const FOPEN_DIRECT_IO: u32 = 1 << 0;
73pub const FOPEN_KEEP_CACHE: u32 = 1 << 1;
74pub const FOPEN_NONSEEKABLE: u32 = 1 << 2;
75pub const FOPEN_CACHE_DIR: u32 = 1 << 3;
76pub const FOPEN_STREAM: u32 = 1 << 4;
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84#[repr(u32)]
85pub enum FuseOpcode {
86 Lookup = 1,
87 Forget = 2,
88 Getattr = 3,
89 Setattr = 4,
90 Readlink = 5,
91 Symlink = 6,
92 Mknod = 8,
93 Mkdir = 9,
94 Unlink = 10,
95 Rmdir = 11,
96 Rename = 12,
97 Link = 13,
98 Open = 14,
99 Read = 15,
100 Write = 16,
101 Statfs = 17,
102 Release = 18,
103 Fsync = 20,
104 Setxattr = 21,
105 Getxattr = 22,
106 Listxattr = 23,
107 Removexattr = 24,
108 Flush = 25,
109 Init = 26,
110 Opendir = 27,
111 Readdir = 28,
112 Releasedir = 29,
113 Fsyncdir = 30,
114 Getlk = 31,
115 Setlk = 32,
116 Setlkw = 33,
117 Access = 34,
118 Create = 35,
119 Interrupt = 36,
120 Bmap = 37,
121 Destroy = 38,
122 Ioctl = 39,
123 Poll = 40,
124 NotifyReply = 41,
125 BatchForget = 42,
126 Fallocate = 43,
127 Readdirplus = 44,
128 Rename2 = 45,
129 Lseek = 46,
130 CopyFileRange = 47,
131 SetupMapping = 48,
132 RemoveMapping = 49,
133}
134
135#[derive(Debug, Clone, Copy)]
137#[repr(C)]
138pub struct FuseInHeader {
139 pub len: u32,
141 pub opcode: u32,
143 pub unique: u64,
145 pub nodeid: u64,
147 pub uid: u32,
149 pub gid: u32,
151 pub pid: u32,
153 pub padding: u32,
155}
156
157#[derive(Debug, Clone, Copy)]
159#[repr(C)]
160pub struct FuseOutHeader {
161 pub len: u32,
163 pub error: i32,
165 pub unique: u64,
167}
168
169#[derive(Debug, Clone, Copy, Default)]
171#[repr(C)]
172pub struct FuseAttr {
173 pub ino: u64,
174 pub size: u64,
175 pub blocks: u64,
176 pub atime: u64,
177 pub mtime: u64,
178 pub ctime: u64,
179 pub atimensec: u32,
180 pub mtimensec: u32,
181 pub ctimensec: u32,
182 pub mode: u32,
183 pub nlink: u32,
184 pub uid: u32,
185 pub gid: u32,
186 pub rdev: u32,
187 pub blksize: u32,
188 pub padding: u32,
189}
190
191#[derive(Debug, Clone, Copy, Default)]
193#[repr(C)]
194pub struct StatFs {
195 pub blocks: u64,
197 pub bfree: u64,
199 pub bavail: u64,
201 pub files: u64,
203 pub ffree: u64,
205 pub bsize: u32,
207 pub namelen: u32,
209 pub frsize: u32,
211}
212
213#[derive(Debug, Clone, Copy)]
219#[repr(C)]
220pub struct FuseInitIn {
221 pub major: u32,
223 pub minor: u32,
225 pub max_readahead: u32,
227 pub flags: u32,
229}
230
231#[derive(Debug, Clone, Copy)]
233#[repr(C)]
234pub struct FuseGetattrIn {
235 pub getattr_flags: u32,
237 pub dummy: u32,
239 pub fh: u64,
241}
242
243#[derive(Debug, Clone, Copy)]
245#[repr(C)]
246pub struct FuseSetattrIn {
247 pub valid: u32,
249 pub padding: u32,
251 pub fh: u64,
253 pub size: u64,
255 pub lock_owner: u64,
257 pub atime: u64,
259 pub mtime: u64,
261 pub ctime: u64,
263 pub atimensec: u32,
265 pub mtimensec: u32,
267 pub ctimensec: u32,
269 pub mode: u32,
271 pub unused4: u32,
273 pub uid: u32,
275 pub gid: u32,
277 pub unused5: u32,
279}
280
281#[derive(Debug, Clone, Copy)]
283#[repr(C)]
284pub struct FuseMknodIn {
285 pub mode: u32,
287 pub rdev: u32,
289 pub umask: u32,
291 pub padding: u32,
293}
294
295#[derive(Debug, Clone, Copy)]
297#[repr(C)]
298pub struct FuseMkdirIn {
299 pub mode: u32,
301 pub umask: u32,
303}
304
305#[derive(Debug, Clone, Copy)]
307#[repr(C)]
308pub struct FuseRenameIn {
309 pub newdir: u64,
311}
312
313#[derive(Debug, Clone, Copy)]
315#[repr(C)]
316pub struct FuseRename2In {
317 pub newdir: u64,
319 pub flags: u32,
321 pub padding: u32,
323}
324
325#[derive(Debug, Clone, Copy)]
327#[repr(C)]
328pub struct FuseLinkIn {
329 pub oldnodeid: u64,
331}
332
333#[derive(Debug, Clone, Copy)]
335#[repr(C)]
336pub struct FuseOpenIn {
337 pub flags: u32,
339 pub unused: u32,
341}
342
343#[derive(Debug, Clone, Copy)]
345#[repr(C)]
346pub struct FuseCreateIn {
347 pub flags: u32,
349 pub mode: u32,
351 pub umask: u32,
353 pub padding: u32,
355}
356
357#[derive(Debug, Clone, Copy)]
359#[repr(C)]
360pub struct FuseReadIn {
361 pub fh: u64,
363 pub offset: u64,
365 pub size: u32,
367 pub read_flags: u32,
369 pub lock_owner: u64,
371 pub flags: u32,
373 pub padding: u32,
375}
376
377#[derive(Debug, Clone, Copy)]
379#[repr(C)]
380pub struct FuseWriteIn {
381 pub fh: u64,
383 pub offset: u64,
385 pub size: u32,
387 pub write_flags: u32,
389 pub lock_owner: u64,
391 pub flags: u32,
393 pub padding: u32,
395}
396
397#[derive(Debug, Clone, Copy)]
399#[repr(C)]
400pub struct FuseReleaseIn {
401 pub fh: u64,
403 pub flags: u32,
405 pub release_flags: u32,
407 pub lock_owner: u64,
409}
410
411#[derive(Debug, Clone, Copy)]
413#[repr(C)]
414pub struct FuseFlushIn {
415 pub fh: u64,
417 pub unused: u32,
419 pub padding: u32,
421 pub lock_owner: u64,
423}
424
425#[derive(Debug, Clone, Copy)]
427#[repr(C)]
428pub struct FuseFsyncIn {
429 pub fh: u64,
431 pub fsync_flags: u32,
433 pub padding: u32,
435}
436
437#[derive(Debug, Clone, Copy)]
439#[repr(C)]
440pub struct FuseSetxattrIn {
441 pub size: u32,
443 pub flags: u32,
445}
446
447#[derive(Debug, Clone, Copy)]
449#[repr(C)]
450pub struct FuseGetxattrIn {
451 pub size: u32,
453 pub padding: u32,
455}
456
457#[derive(Debug, Clone, Copy)]
459#[repr(C)]
460pub struct FuseAccessIn {
461 pub mask: u32,
463 pub padding: u32,
465}
466
467#[derive(Debug, Clone, Copy)]
469#[repr(C)]
470pub struct FuseLseekIn {
471 pub fh: u64,
473 pub offset: u64,
475 pub whence: u32,
477 pub padding: u32,
479}
480
481#[derive(Debug, Clone, Copy)]
483#[repr(C)]
484pub struct FuseFallocateIn {
485 pub fh: u64,
487 pub offset: u64,
489 pub length: u64,
491 pub mode: u32,
493 pub padding: u32,
495}
496
497#[derive(Debug, Clone, Copy)]
499#[repr(C)]
500pub struct FuseForgetIn {
501 pub nlookup: u64,
503}
504
505#[derive(Debug, Clone, Copy)]
507#[repr(C)]
508pub struct FuseForgetOne {
509 pub nodeid: u64,
511 pub nlookup: u64,
513}
514
515#[derive(Debug, Clone, Copy)]
517#[repr(C)]
518pub struct FuseBatchForgetIn {
519 pub count: u32,
521 pub dummy: u32,
523}
524
525#[derive(Debug, Clone, Copy)]
531#[repr(C)]
532pub struct FuseInitOut {
533 pub major: u32,
535 pub minor: u32,
537 pub max_readahead: u32,
539 pub flags: u32,
541 pub max_background: u16,
543 pub congestion_threshold: u16,
545 pub max_write: u32,
547 pub time_gran: u32,
549 pub max_pages: u16,
551 pub padding: u16,
553 pub unused: [u32; 8],
555}
556
557impl Default for FuseInitOut {
558 fn default() -> Self {
559 Self {
560 major: FUSE_KERNEL_VERSION,
561 minor: FUSE_KERNEL_MINOR_VERSION,
562 max_readahead: 128 * 1024,
563 flags: FUSE_ASYNC_READ | FUSE_BIG_WRITES | FUSE_WRITEBACK_CACHE,
564 max_background: 16,
565 congestion_threshold: 12,
566 max_write: 128 * 1024,
567 time_gran: 1,
568 max_pages: 32,
569 padding: 0,
570 unused: [0; 8],
571 }
572 }
573}
574
575#[derive(Debug, Clone, Copy, Default)]
577#[repr(C)]
578pub struct FuseEntryOut {
579 pub nodeid: u64,
581 pub generation: u64,
583 pub entry_valid: u64,
585 pub attr_valid: u64,
587 pub entry_valid_nsec: u32,
589 pub attr_valid_nsec: u32,
591 pub attr: FuseAttr,
593}
594
595#[derive(Debug, Clone, Copy, Default)]
597#[repr(C)]
598pub struct FuseAttrOut {
599 pub attr_valid: u64,
601 pub attr_valid_nsec: u32,
603 pub dummy: u32,
605 pub attr: FuseAttr,
607}
608
609#[derive(Debug, Clone, Copy, Default)]
611#[repr(C)]
612pub struct FuseOpenOut {
613 pub fh: u64,
615 pub open_flags: u32,
617 pub padding: u32,
619}
620
621#[derive(Debug, Clone, Copy, Default)]
623#[repr(C)]
624pub struct FuseWriteOut {
625 pub size: u32,
627 pub padding: u32,
629}
630
631#[derive(Debug, Clone, Copy, Default)]
633#[repr(C)]
634pub struct FuseGetxattrOut {
635 pub size: u32,
637 pub padding: u32,
639}
640
641#[derive(Debug, Clone, Copy, Default)]
643#[repr(C)]
644pub struct FuseStatfsOut {
645 pub st: StatFs,
647}
648
649#[derive(Debug, Clone, Copy, Default)]
651#[repr(C)]
652pub struct FuseLseekOut {
653 pub offset: u64,
655}
656
657#[derive(Debug, Clone, Copy)]
659#[repr(C)]
660pub struct FuseDirent {
661 pub ino: u64,
663 pub off: u64,
665 pub namelen: u32,
667 pub typ: u32,
669 }
671
672impl FuseDirent {
673 #[must_use]
675 pub const fn size(namelen: usize) -> usize {
676 let base = size_of::<Self>() + namelen;
678 (base + 7) & !7
679 }
680}
681
682impl FuseOpcode {
687 #[must_use]
689 pub fn from_u32(value: u32) -> Option<Self> {
690 match value {
691 1 => Some(Self::Lookup),
692 2 => Some(Self::Forget),
693 3 => Some(Self::Getattr),
694 4 => Some(Self::Setattr),
695 5 => Some(Self::Readlink),
696 6 => Some(Self::Symlink),
697 8 => Some(Self::Mknod),
698 9 => Some(Self::Mkdir),
699 10 => Some(Self::Unlink),
700 11 => Some(Self::Rmdir),
701 12 => Some(Self::Rename),
702 13 => Some(Self::Link),
703 14 => Some(Self::Open),
704 15 => Some(Self::Read),
705 16 => Some(Self::Write),
706 17 => Some(Self::Statfs),
707 18 => Some(Self::Release),
708 20 => Some(Self::Fsync),
709 21 => Some(Self::Setxattr),
710 22 => Some(Self::Getxattr),
711 23 => Some(Self::Listxattr),
712 24 => Some(Self::Removexattr),
713 25 => Some(Self::Flush),
714 26 => Some(Self::Init),
715 27 => Some(Self::Opendir),
716 28 => Some(Self::Readdir),
717 29 => Some(Self::Releasedir),
718 30 => Some(Self::Fsyncdir),
719 31 => Some(Self::Getlk),
720 32 => Some(Self::Setlk),
721 33 => Some(Self::Setlkw),
722 34 => Some(Self::Access),
723 35 => Some(Self::Create),
724 36 => Some(Self::Interrupt),
725 37 => Some(Self::Bmap),
726 38 => Some(Self::Destroy),
727 39 => Some(Self::Ioctl),
728 40 => Some(Self::Poll),
729 41 => Some(Self::NotifyReply),
730 42 => Some(Self::BatchForget),
731 43 => Some(Self::Fallocate),
732 44 => Some(Self::Readdirplus),
733 45 => Some(Self::Rename2),
734 46 => Some(Self::Lseek),
735 47 => Some(Self::CopyFileRange),
736 48 => Some(Self::SetupMapping),
737 49 => Some(Self::RemoveMapping),
738 _ => None,
739 }
740 }
741}
742
743impl FuseInHeader {
748 pub const SIZE: usize = size_of::<Self>();
750}
751
752impl FuseOutHeader {
753 pub const SIZE: usize = size_of::<Self>();
755
756 #[must_use]
758 pub const fn success(unique: u64, len: u32) -> Self {
759 Self {
760 len,
761 error: 0,
762 unique,
763 }
764 }
765
766 #[must_use]
768 pub const fn error(unique: u64, errno: i32) -> Self {
769 Self {
770 len: Self::SIZE as u32,
771 error: -errno,
772 unique,
773 }
774 }
775}