1use std::fmt;
4
5use clippy_utilities::Cast;
6use tracing::debug;
7
8use super::context::ProtoVersion;
9use super::de::{DeserializeError, Deserializer};
10#[cfg(feature = "abi-7-19")]
11use super::protocol::FuseFAllocateIn;
12#[cfg(feature = "abi-7-23")]
13use super::protocol::FuseRename2In;
14use super::protocol::{
15 FuseAccessIn, FuseBMapIn, FuseCopyFileRangeIn, FuseCreateIn, FuseFSyncIn, FuseFlushIn,
16 FuseForgetIn, FuseGetXAttrIn, FuseInHeader, FuseInitIn, FuseInterruptIn, FuseLSeekIn,
17 FuseLinkIn, FuseLockIn, FuseMkDirIn, FuseMkNodIn, FuseOpCode, FuseOpenIn, FuseReadIn,
18 FuseReleaseIn, FuseRenameIn, FuseSetAttrIn, FuseSetXAttrIn, FuseWriteIn,
19};
20#[cfg(feature = "abi-7-16")]
21use super::protocol::{FuseBatchForgetIn, FuseForgetOne};
22#[cfg(feature = "abi-7-11")]
23use super::protocol::{FuseIoCtlIn, FusePollIn};
24
25#[derive(Debug)]
27pub enum Operation<'a> {
28 Lookup {
30 name: &'a str,
32 },
33 Forget {
35 arg: &'a FuseForgetIn,
37 },
38 GetAttr,
40 SetAttr {
42 arg: &'a FuseSetAttrIn,
44 },
45 ReadLink,
47 SymLink {
49 name: &'a str,
51 link: &'a str,
53 },
54 MkNod {
56 arg: &'a FuseMkNodIn,
58 name: &'a str,
60 },
61 MkDir {
63 arg: &'a FuseMkDirIn,
65 name: &'a str,
67 },
68 Unlink {
70 name: &'a str,
72 },
73 RmDir {
75 name: &'a str,
77 },
78 Rename {
80 arg: &'a FuseRenameIn,
82 oldname: &'a str,
84 newname: &'a str,
86 },
87 Link {
89 arg: &'a FuseLinkIn,
91 name: &'a str,
93 },
94 Open {
96 arg: &'a FuseOpenIn,
98 },
99 Read {
101 arg: &'a FuseReadIn,
103 },
104 Write {
106 arg: &'a FuseWriteIn,
108 data: &'a [u8],
110 },
111 StatFs,
113 Release {
115 arg: &'a FuseReleaseIn,
117 },
118 FSync {
120 arg: &'a FuseFSyncIn,
122 },
123 SetXAttr {
125 arg: &'a FuseSetXAttrIn,
127 name: &'a str,
129 value: &'a [u8],
131 },
132 GetXAttr {
134 arg: &'a FuseGetXAttrIn,
136 name: &'a str,
138 },
139 ListXAttr {
141 arg: &'a FuseGetXAttrIn,
143 },
144 RemoveXAttr {
146 name: &'a str,
148 },
149 Flush {
151 arg: &'a FuseFlushIn,
153 },
154 Init {
156 arg: &'a FuseInitIn,
158 },
159 OpenDir {
161 arg: &'a FuseOpenIn,
163 },
164 ReadDir {
166 arg: &'a FuseReadIn,
168 },
169 ReleaseDir {
171 arg: &'a FuseReleaseIn,
173 },
174 FSyncDir {
176 arg: &'a FuseFSyncIn,
178 },
179 GetLk {
181 arg: &'a FuseLockIn,
183 },
184 SetLk {
186 arg: &'a FuseLockIn,
188 },
189 SetLkW {
191 arg: &'a FuseLockIn,
193 },
194 Access {
196 arg: &'a FuseAccessIn,
198 },
199 Create {
201 arg: &'a FuseCreateIn,
203 name: &'a str,
205 },
206 Interrupt {
208 arg: &'a FuseInterruptIn,
210 },
211 BMap {
213 arg: &'a FuseBMapIn,
215 },
216 Destroy,
218 #[cfg(feature = "abi-7-11")]
220 IoCtl {
221 arg: &'a FuseIoCtlIn,
223 data: &'a [u8],
225 },
226 #[cfg(feature = "abi-7-11")]
228 Poll {
229 arg: &'a FusePollIn,
231 },
232 #[cfg(feature = "abi-7-15")]
234 NotifyReply {
235 data: &'a [u8],
237 },
238 #[cfg(feature = "abi-7-16")]
240 BatchForget {
241 arg: &'a FuseBatchForgetIn,
243 nodes: &'a [FuseForgetOne],
245 },
246 #[cfg(feature = "abi-7-19")]
248 FAllocate {
249 arg: &'a FuseFAllocateIn,
251 },
252 #[cfg(feature = "abi-7-21")]
254 ReadDirPlus {
255 arg: &'a FuseReadIn,
257 },
258 #[cfg(feature = "abi-7-23")]
266 Rename2 {
267 arg: &'a FuseRename2In,
269 oldname: &'a str,
271 newname: &'a str,
273 },
274 LSeek {
277 arg: &'a FuseLSeekIn,
279 },
280 CopyFileRange {
283 arg: &'a FuseCopyFileRangeIn,
285 },
286 #[cfg(feature = "abi-7-11")]
288 CuseInit {
289 arg: &'a FuseInitIn,
291 },
292}
293
294impl<'a> Operation<'a> {
295 #[allow(clippy::too_many_lines)]
297 fn parse(
298 n: u32,
299 data: &mut Deserializer<'a>,
300 #[allow(unused_variables)] proto_version: ProtoVersion,
301 ) -> Result<Self, DeserializeError> {
302 let opcode = match n {
303 1 => FuseOpCode::FUSE_LOOKUP,
304 2 => FuseOpCode::FUSE_FORGET,
305 3 => FuseOpCode::FUSE_GETATTR,
306 4 => FuseOpCode::FUSE_SETATTR,
307 5 => FuseOpCode::FUSE_READLINK,
308 6 => FuseOpCode::FUSE_SYMLINK,
309 8 => FuseOpCode::FUSE_MKNOD,
310 9 => FuseOpCode::FUSE_MKDIR,
311 10 => FuseOpCode::FUSE_UNLINK,
312 11 => FuseOpCode::FUSE_RMDIR,
313 12 => FuseOpCode::FUSE_RENAME,
314 13 => FuseOpCode::FUSE_LINK,
315 14 => FuseOpCode::FUSE_OPEN,
316 15 => FuseOpCode::FUSE_READ,
317 16 => FuseOpCode::FUSE_WRITE,
318 17 => FuseOpCode::FUSE_STATFS,
319 18 => FuseOpCode::FUSE_RELEASE,
320 20 => FuseOpCode::FUSE_FSYNC,
321 21 => FuseOpCode::FUSE_SETXATTR,
322 22 => FuseOpCode::FUSE_GETXATTR,
323 23 => FuseOpCode::FUSE_LISTXATTR,
324 24 => FuseOpCode::FUSE_REMOVEXATTR,
325 25 => FuseOpCode::FUSE_FLUSH,
326 26 => FuseOpCode::FUSE_INIT,
327 27 => FuseOpCode::FUSE_OPENDIR,
328 28 => FuseOpCode::FUSE_READDIR,
329 29 => FuseOpCode::FUSE_RELEASEDIR,
330 30 => FuseOpCode::FUSE_FSYNCDIR,
331 31 => FuseOpCode::FUSE_GETLK,
332 32 => FuseOpCode::FUSE_SETLK,
333 33 => FuseOpCode::FUSE_SETLKW,
334 34 => FuseOpCode::FUSE_ACCESS,
335 35 => FuseOpCode::FUSE_CREATE,
336 36 => FuseOpCode::FUSE_INTERRUPT,
337 37 => FuseOpCode::FUSE_BMAP,
338 38 => FuseOpCode::FUSE_DESTROY,
339 #[cfg(feature = "abi-7-11")]
340 39 => FuseOpCode::FUSE_IOCTL,
341 #[cfg(feature = "abi-7-11")]
342 40 => FuseOpCode::FUSE_POLL,
343 #[cfg(feature = "abi-7-15")]
344 41 => FuseOpCode::FUSE_NOTIFY_REPLY,
345 #[cfg(feature = "abi-7-16")]
346 42 => FuseOpCode::FUSE_BATCH_FORGET,
347 #[cfg(feature = "abi-7-19")]
348 43 => FuseOpCode::FUSE_FALLOCATE,
349 #[cfg(feature = "abi-7-21")]
350 44 => FuseOpCode::FUSE_READDIRPLUS,
351 #[cfg(feature = "abi-7-23")]
352 45 => FuseOpCode::FUSE_RENAME2,
353 46 => FuseOpCode::FUSE_LSEEK,
355 47 => FuseOpCode::FUSE_COPY_FILE_RANGE,
357 #[cfg(feature = "abi-7-11")]
358 4096 => FuseOpCode::CUSE_INIT,
359
360 code => return Err(DeserializeError::UnknownOpCode { code, unique: None }),
361 };
362
363 Ok(match opcode {
364 FuseOpCode::FUSE_LOOKUP => Operation::Lookup {
365 name: data.fetch_str()?,
366 },
367 FuseOpCode::FUSE_FORGET => Operation::Forget {
368 arg: data.fetch_ref()?,
369 },
370 FuseOpCode::FUSE_GETATTR => Operation::GetAttr,
371 FuseOpCode::FUSE_SETATTR => Operation::SetAttr {
372 arg: data.fetch_ref()?,
373 },
374 FuseOpCode::FUSE_READLINK => Operation::ReadLink,
375 FuseOpCode::FUSE_SYMLINK => Operation::SymLink {
376 name: data.fetch_str()?,
377 link: data.fetch_str()?,
378 },
379 FuseOpCode::FUSE_MKNOD => Operation::MkNod {
380 arg: data.fetch_ref()?,
381 name: data.fetch_str()?,
382 },
383 FuseOpCode::FUSE_MKDIR => Operation::MkDir {
384 arg: data.fetch_ref()?,
385 name: data.fetch_str()?,
386 },
387 FuseOpCode::FUSE_UNLINK => Operation::Unlink {
388 name: data.fetch_str()?,
389 },
390 FuseOpCode::FUSE_RMDIR => Operation::RmDir {
391 name: data.fetch_str()?,
392 },
393 FuseOpCode::FUSE_RENAME => Operation::Rename {
394 arg: data.fetch_ref()?,
395 oldname: data.fetch_str()?,
396 newname: data.fetch_str()?,
397 },
398 FuseOpCode::FUSE_LINK => Operation::Link {
399 arg: data.fetch_ref()?,
400 name: data.fetch_str()?,
401 },
402 FuseOpCode::FUSE_OPEN => Operation::Open {
403 arg: data.fetch_ref()?,
404 },
405 FuseOpCode::FUSE_READ => Operation::Read {
406 arg: data.fetch_ref()?,
407 },
408 FuseOpCode::FUSE_WRITE => Operation::Write {
409 arg: data.fetch_ref()?,
410 data: data.fetch_all_bytes(),
411 },
412 FuseOpCode::FUSE_STATFS => Operation::StatFs,
413 FuseOpCode::FUSE_RELEASE => Operation::Release {
414 arg: data.fetch_ref()?,
415 },
416 FuseOpCode::FUSE_FSYNC => Operation::FSync {
417 arg: data.fetch_ref()?,
418 },
419 FuseOpCode::FUSE_SETXATTR => Operation::SetXAttr {
420 arg: data.fetch_ref()?,
421 name: data.fetch_str()?,
422 value: data.fetch_all_bytes(),
423 },
424 FuseOpCode::FUSE_GETXATTR => Operation::GetXAttr {
425 arg: data.fetch_ref()?,
426 name: data.fetch_str()?,
427 },
428 FuseOpCode::FUSE_LISTXATTR => Operation::ListXAttr {
429 arg: data.fetch_ref()?,
430 },
431 FuseOpCode::FUSE_REMOVEXATTR => Operation::RemoveXAttr {
432 name: data.fetch_str()?,
433 },
434 FuseOpCode::FUSE_FLUSH => Operation::Flush {
435 arg: data.fetch_ref()?,
436 },
437 FuseOpCode::FUSE_INIT => Operation::Init {
438 arg: data.fetch_ref()?,
439 },
440 FuseOpCode::FUSE_OPENDIR => Operation::OpenDir {
441 arg: data.fetch_ref()?,
442 },
443 FuseOpCode::FUSE_READDIR => Operation::ReadDir {
444 arg: data.fetch_ref()?,
445 },
446 FuseOpCode::FUSE_RELEASEDIR => Operation::ReleaseDir {
447 arg: data.fetch_ref()?,
448 },
449 FuseOpCode::FUSE_FSYNCDIR => Operation::FSyncDir {
450 arg: data.fetch_ref()?,
451 },
452 FuseOpCode::FUSE_GETLK => Operation::GetLk {
453 arg: data.fetch_ref()?,
454 },
455 FuseOpCode::FUSE_SETLK => Operation::SetLk {
456 arg: data.fetch_ref()?,
457 },
458 FuseOpCode::FUSE_SETLKW => Operation::SetLkW {
459 arg: data.fetch_ref()?,
460 },
461 FuseOpCode::FUSE_ACCESS => Operation::Access {
462 arg: data.fetch_ref()?,
463 },
464 FuseOpCode::FUSE_CREATE => Operation::Create {
465 arg: data.fetch_ref()?,
466 name: data.fetch_str()?,
467 },
468 FuseOpCode::FUSE_INTERRUPT => Operation::Interrupt {
469 arg: data.fetch_ref()?,
470 },
471 FuseOpCode::FUSE_BMAP => Operation::BMap {
472 arg: data.fetch_ref()?,
473 },
474 FuseOpCode::FUSE_DESTROY => Operation::Destroy,
475 #[cfg(feature = "abi-7-11")]
476 FuseOpCode::FUSE_IOCTL => Operation::IoCtl {
477 arg: data.fetch_ref()?,
478 data: data.fetch_all_bytes(),
479 },
480 #[cfg(feature = "abi-7-11")]
481 FuseOpCode::FUSE_POLL => Operation::Poll {
482 arg: data.fetch_ref()?,
483 },
484 #[cfg(feature = "abi-7-15")]
485 FuseOpCode::FUSE_NOTIFY_REPLY => Operation::NotifyReply {
486 data: data.fetch_all_bytes(),
487 },
488 #[cfg(feature = "abi-7-16")]
489 FuseOpCode::FUSE_BATCH_FORGET => Operation::BatchForget {
490 arg: data.fetch_ref()?,
491 nodes: data.fetch_all_as_slice()?,
492 },
493 #[cfg(feature = "abi-7-19")]
494 FuseOpCode::FUSE_FALLOCATE => Operation::FAllocate {
495 arg: data.fetch_ref()?,
496 },
497 #[cfg(feature = "abi-7-21")]
498 FuseOpCode::FUSE_READDIRPLUS => Operation::ReadDirPlus {
499 arg: data.fetch_ref()?,
500 },
501 #[cfg(feature = "abi-7-23")]
502 FuseOpCode::FUSE_RENAME2 => Operation::Rename2 {
503 arg: data.fetch_ref()?,
504 oldname: data.fetch_str()?,
505 newname: data.fetch_str()?,
506 },
507 FuseOpCode::FUSE_LSEEK => Operation::LSeek {
509 arg: data.fetch_ref()?,
510 },
511 FuseOpCode::FUSE_COPY_FILE_RANGE => Operation::CopyFileRange {
513 arg: data.fetch_ref()?,
514 },
515 #[cfg(feature = "abi-7-11")]
516 FuseOpCode::CUSE_INIT => Operation::CuseInit {
517 arg: data.fetch_ref()?,
518 },
519 })
520 }
521}
522
523impl fmt::Display for Operation<'_> {
524 #[allow(clippy::too_many_lines)]
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 match *self {
528 Operation::Lookup { name } => write!(f, "LOOKUP name={name:?}"),
529 Operation::Forget { arg } => write!(f, "FORGET nlookup={}", arg.nlookup),
530 Operation::GetAttr => write!(f, "GETATTR"),
531 Operation::SetAttr { arg } => write!(f, "SETATTR valid={:#x}", arg.valid),
532 Operation::ReadLink => write!(f, "READLINK"),
533 Operation::SymLink { name, link } => {
534 write!(f, "SYMLINK name={name:?}, link={link:?}")
535 }
536 Operation::MkNod { arg, name } => write!(
537 f,
538 "MKNOD name={:?}, mode={:#05o}, rdev={}",
539 name, arg.mode, arg.rdev
540 ),
541 Operation::MkDir { arg, name } => {
542 write!(f, "MKDIR name={:?}, mode={:#05o}", name, arg.mode)
543 }
544 Operation::Unlink { name } => write!(f, "UNLINK name={name:?}"),
545 Operation::RmDir { name } => write!(f, "RMDIR name={name:?}"),
546 Operation::Rename {
547 arg,
548 oldname,
549 newname,
550 } => write!(
551 f,
552 "RENAME name={:?}, newdir={:#018x}, newname={:?}",
553 oldname, arg.newdir, newname
554 ),
555 Operation::Link { arg, name } => {
556 write!(f, "LINK name={:?}, oldnodeid={:#018x}", name, arg.oldnodeid)
557 }
558 Operation::Open { arg } => write!(f, "OPEN flags={:#x}", arg.flags),
559 Operation::Read { arg } => write!(
560 f,
561 "READ fh={}, offset={}, size={}",
562 arg.fh, arg.offset, arg.size
563 ),
564 Operation::Write { arg, .. } => write!(
565 f,
566 "WRITE fh={}, offset={}, size={}, write flags={:#x}",
567 arg.fh, arg.offset, arg.size, arg.write_flags
568 ),
569 Operation::StatFs => write!(f, "STATFS"),
570 Operation::Release { arg } => write!(
571 f,
572 "RELEASE fh={}, flags={:#x}, release flags={:#x}, lock owner={}",
573 arg.fh, arg.flags, arg.release_flags, arg.lock_owner
574 ),
575 Operation::FSync { arg } => {
576 write!(f, "FSYNC fh={}, fsync flags={:#x}", arg.fh, arg.fsync_flags)
577 }
578 Operation::SetXAttr { arg, name, .. } => write!(
579 f,
580 "SETXATTR name={:?}, size={}, flags={:#x}",
581 name, arg.size, arg.flags
582 ),
583 Operation::GetXAttr { arg, name } => {
584 write!(f, "GETXATTR name={:?}, size={}", name, arg.size)
585 }
586 Operation::ListXAttr { arg } => write!(f, "LISTXATTR size={}", arg.size),
587 Operation::RemoveXAttr { name } => write!(f, "REMOVEXATTR name={name:?}"),
588 Operation::Flush { arg } => {
589 write!(f, "FLUSH fh={}, lock owner={}", arg.fh, arg.lock_owner)
590 }
591 Operation::Init { arg } => write!(
592 f,
593 "INIT kernel ABI={}.{}, flags={:#x}, max readahead={}",
594 arg.major, arg.minor, arg.flags, arg.max_readahead
595 ),
596 Operation::OpenDir { arg } => write!(f, "OPENDIR flags={:#x}", arg.flags),
597 Operation::ReadDir { arg } => write!(
598 f,
599 "READDIR fh={}, offset={}, size={}",
600 arg.fh, arg.offset, arg.size
601 ),
602 Operation::ReleaseDir { arg } => write!(
603 f,
604 "RELEASEDIR fh={}, flags={:#x}, release flags={:#x}, lock owner={}",
605 arg.fh, arg.flags, arg.release_flags, arg.lock_owner
606 ),
607 Operation::FSyncDir { arg } => write!(
608 f,
609 "FSYNCDIR fh={}, fsync flags={:#x}",
610 arg.fh, arg.fsync_flags
611 ),
612 Operation::GetLk { arg } => write!(f, "GETLK fh={}, lock owner={}", arg.fh, arg.owner),
613 Operation::SetLk { arg } => write!(f, "SETLK fh={}, lock owner={}", arg.fh, arg.owner),
614 Operation::SetLkW { arg } => {
615 write!(f, "SETLKW fh={}, lock owner={}", arg.fh, arg.owner)
616 }
617 Operation::Access { arg } => write!(f, "ACCESS mask={:#05o}", arg.mask),
618 Operation::Create { arg, name } => write!(
619 f,
620 "CREATE name={:?}, mode={:#05o}, flags={:#x}",
621 name, arg.mode, arg.flags,
622 ),
623 Operation::Interrupt { arg } => write!(f, "INTERRUPT unique={}", arg.unique),
624 Operation::BMap { arg } => {
625 write!(f, "BMAP blocksize={}, ids={}", arg.blocksize, arg.block)
626 }
627 Operation::Destroy => write!(f, "DESTROY"),
628
629 #[cfg(feature = "abi-7-11")]
630 Operation::IoCtl { arg, data } => write!(
631 f,
632 "IOCTL fh={}, flags {:#x}, cmd={}, arg={}, data={:?}",
633 arg.fh, arg.flags, arg.cmd, arg.arg, data,
634 ),
635 #[cfg(feature = "abi-7-11")]
636 Operation::Poll { arg } => {
637 write!(
638 f,
639 "POLL fh={}, kh={}, flags={:#x} ",
640 arg.fh, arg.kh, arg.flags
641 )
642 }
643 #[cfg(feature = "abi-7-15")]
644 Operation::NotifyReply { data } => write!(f, "NOTIFY REPLY data={data:?}"),
645 #[cfg(feature = "abi-7-16")]
646 Operation::BatchForget { arg, nodes } => {
647 write!(f, "BATCH FORGOT count={}, nodes={:?}", arg.count, nodes)
648 }
649 #[cfg(feature = "abi-7-19")]
650 Operation::FAllocate { arg } => write!(
651 f,
652 "FALLOCATE fh={}, offset={}, length={}, mode={:#05o}",
653 arg.fh, arg.offset, arg.length, arg.mode,
654 ),
655 #[cfg(feature = "abi-7-21")]
656 Operation::ReadDirPlus { arg } => write!(
657 f,
658 "READDIRPLUS fh={}, offset={}, size={}",
659 arg.fh, arg.offset, arg.size,
660 ),
661 #[cfg(feature = "abi-7-23")]
662 Operation::Rename2 {
663 arg,
664 oldname,
665 newname,
666 } => write!(
667 f,
668 "RENAME2 name={:?}, newdir={:#018x}, newname={:?}, flags={:#x}",
669 oldname, arg.newdir, newname, arg.flags,
670 ),
671 Operation::LSeek { arg } => write!(
673 f,
674 "LSEEK fh={}, offset={}, whence={}",
675 arg.fh, arg.offset, arg.whence,
676 ),
677 Operation::CopyFileRange { arg } => write!(
679 f,
680 "COPYFILERANGE src fh={}, dst fh={}, flags={:#?}",
681 arg.fh_in, arg.fh_out, arg.flags,
682 ),
683 #[cfg(feature = "abi-7-11")]
684 Operation::CuseInit { arg } => write!(
685 f,
686 "CUSE INIT kernel ABI={}.{}, flags={:#x}, max readahead={}",
687 arg.major, arg.minor, arg.flags, arg.max_readahead,
688 ),
689 }
690 }
691}
692
693#[derive(Debug)]
695pub struct Request<'a> {
696 header: &'a FuseInHeader,
698 operation: Operation<'a>,
700}
701
702impl fmt::Display for Request<'_> {
703 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704 write!(
705 f,
706 "fuse={} ino={} operation={}",
707 self.header.unique, self.header.nodeid, self.operation,
708 )
709 }
710}
711
712impl<'a> Request<'a> {
713 pub fn new(bytes: &'a [u8], proto_version: ProtoVersion) -> Result<Self, DeserializeError> {
715 let data_len = bytes.len();
716 let mut de = Deserializer::new(bytes);
717 let header = de.fetch_ref::<FuseInHeader>()?;
719 debug_assert!(
721 data_len >= header.len.cast(), "failed to assert {} >= {}",
723 data_len,
724 header.len,
725 );
726 let operation = Operation::parse(header.opcode, &mut de, proto_version).map_err(|e| {
728 if let DeserializeError::UnknownOpCode { code, .. } = e {
729 DeserializeError::UnknownOpCode {
730 code,
731 unique: Some(header.unique),
732 }
733 } else {
734 e
735 }
736 })?;
737 if de.remaining_len() > 0 {
738 debug!(
739 "request bytes is not completely consumed: \
740 bytes.len() = {}, header = {:?}, de.remaining_len() = {}, de = {:?}",
741 bytes.len(),
742 header,
743 de.remaining_len(),
744 de
745 );
746 }
747
748 Ok(Self { header, operation })
749 }
750
751 #[inline]
758 #[must_use]
759 pub const fn unique(&self) -> u64 {
760 self.header.unique
761 }
762
763 #[inline]
765 #[must_use]
766 pub const fn nodeid(&self) -> u64 {
767 self.header.nodeid
768 }
769
770 #[allow(dead_code)]
772 #[inline]
773 #[must_use]
774 pub const fn uid(&self) -> u32 {
775 self.header.uid
776 }
777
778 #[allow(dead_code)]
780 #[inline]
781 #[must_use]
782 pub const fn gid(&self) -> u32 {
783 self.header.gid
784 }
785
786 #[allow(dead_code)]
788 #[inline]
789 #[must_use]
790 pub const fn pid(&self) -> u32 {
791 self.header.pid
792 }
793
794 #[allow(dead_code)]
796 #[inline]
797 #[must_use]
798 pub const fn len(&self) -> u32 {
799 self.header.len
800 }
801
802 #[allow(dead_code)]
804 #[inline]
805 #[must_use]
806 pub const fn is_empty(&self) -> bool {
807 self.header.len == 0
808 }
809
810 #[inline]
812 #[must_use]
813 pub const fn operation(&self) -> &Operation<'_> {
814 &self.operation
815 }
816}