1#![warn(
8 missing_docs,
9 missing_debug_implementations,
10 rust_2018_idioms,
11 unreachable_pub
12)]
13
14use std::cmp::max;
15use std::cmp::min;
16use std::convert::AsRef;
17use std::ffi::OsStr;
18use std::io;
19use std::os::unix::fs::FileTypeExt;
20use std::path::Path;
21use std::time::Duration;
22use std::time::SystemTime;
23
24use log::warn;
25#[cfg(target_os = "macos")]
26pub use reply::ReplyXTimes;
27#[cfg(feature = "serializable")]
28use serde::Deserialize;
29#[cfg(feature = "serializable")]
30use serde::Serialize;
31
32pub use crate::access_flags::AccessFlags;
33pub use crate::bsd_file_flags::BsdFileFlags;
34use crate::forget_one::ForgetOne;
35pub use crate::ll::Errno;
36pub use crate::ll::Generation;
37pub use crate::ll::RequestId;
38pub use crate::ll::TimeOrNow;
39pub use crate::ll::flags::copy_file_range_flags::CopyFileRangeFlags;
40pub use crate::ll::flags::fopen_flags::FopenFlags;
41pub use crate::ll::flags::init_flags::InitFlags;
42pub use crate::ll::flags::ioctl_flags::IoctlFlags;
43pub use crate::ll::flags::poll_flags::PollFlags;
44pub use crate::ll::flags::write_flags::WriteFlags;
45pub use crate::ll::fuse_abi::consts;
46pub use crate::ll::request::FileHandle;
47pub use crate::ll::request::INodeNo;
48pub use crate::ll::request::LockOwner;
49pub use crate::ll::request::Version;
50pub use crate::mnt::mount_options::Config;
51pub use crate::mnt::mount_options::MountOption;
52pub use crate::notify::Notifier;
53pub use crate::notify::PollHandle;
54pub use crate::notify::PollNotifier;
55pub use crate::open_flags::OpenAccMode;
56pub use crate::open_flags::OpenFlags;
57pub use crate::passthrough::BackingId;
58pub use crate::poll_events::PollEvents;
59pub use crate::rename_flags::RenameFlags;
60pub use crate::reply::ReplyAttr;
61pub use crate::reply::ReplyBmap;
62pub use crate::reply::ReplyCreate;
63pub use crate::reply::ReplyData;
64pub use crate::reply::ReplyDirectory;
65pub use crate::reply::ReplyDirectoryPlus;
66pub use crate::reply::ReplyEmpty;
67pub use crate::reply::ReplyEntry;
68pub use crate::reply::ReplyIoctl;
69pub use crate::reply::ReplyLock;
70pub use crate::reply::ReplyLseek;
71pub use crate::reply::ReplyOpen;
72pub use crate::reply::ReplyPoll;
73pub use crate::reply::ReplyStatfs;
74pub use crate::reply::ReplyWrite;
75pub use crate::reply::ReplyXattr;
76pub use crate::request_param::Request;
77pub use crate::session::BackgroundSession;
78use crate::session::MAX_WRITE_SIZE;
79pub use crate::session::Session;
80pub use crate::session::SessionACL;
81pub use crate::session::SessionUnmounter;
82
83mod access_flags;
84mod bsd_file_flags;
85mod channel;
86mod dev_fuse;
87#[cfg(feature = "experimental")]
89pub mod experimental;
90mod forget_one;
91mod ll;
92mod mnt;
93mod notify;
94mod open_flags;
95mod passthrough;
96mod poll_events;
97mod read_buf;
98mod rename_flags;
99mod reply;
100mod request;
101mod request_param;
102mod session;
103mod time;
104
105#[cfg(not(target_os = "macos"))]
107const INIT_FLAGS: InitFlags = InitFlags::FUSE_ASYNC_READ.union(InitFlags::FUSE_BIG_WRITES);
108#[cfg(target_os = "macos")]
113const INIT_FLAGS: InitFlags = InitFlags::FUSE_ASYNC_READ
114 .union(InitFlags::FUSE_CASE_INSENSITIVE)
115 .union(InitFlags::FUSE_VOL_RENAME)
116 .union(InitFlags::FUSE_XTIMES);
117fn default_init_flags(capabilities: InitFlags) -> InitFlags {
120 let mut flags = INIT_FLAGS;
121 if capabilities.contains(InitFlags::FUSE_MAX_PAGES) {
122 flags |= InitFlags::FUSE_MAX_PAGES;
123 }
124 flags
125}
126
127#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
129#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
130pub enum FileType {
131 NamedPipe,
133 CharDevice,
135 BlockDevice,
137 Directory,
139 RegularFile,
141 Symlink,
143 Socket,
145}
146
147impl FileType {
148 pub fn from_std(file_type: std::fs::FileType) -> Option<Self> {
150 if file_type.is_file() {
151 Some(FileType::RegularFile)
152 } else if file_type.is_dir() {
153 Some(FileType::Directory)
154 } else if file_type.is_symlink() {
155 Some(FileType::Symlink)
156 } else if file_type.is_fifo() {
157 Some(FileType::NamedPipe)
158 } else if file_type.is_socket() {
159 Some(FileType::Socket)
160 } else if file_type.is_char_device() {
161 Some(FileType::CharDevice)
162 } else if file_type.is_block_device() {
163 Some(FileType::BlockDevice)
164 } else {
165 None
166 }
167 }
168}
169
170#[derive(Clone, Copy, Debug, Eq, PartialEq)]
172#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
173pub struct FileAttr {
174 pub ino: INodeNo,
176 pub size: u64,
178 pub blocks: u64,
181 pub atime: SystemTime,
183 pub mtime: SystemTime,
185 pub ctime: SystemTime,
187 pub crtime: SystemTime,
189 pub kind: FileType,
191 pub perm: u16,
193 pub nlink: u32,
195 pub uid: u32,
197 pub gid: u32,
199 pub rdev: u32,
201 pub blksize: u32,
203 pub flags: u32,
205}
206
207#[derive(Debug)]
209pub struct KernelConfig {
210 capabilities: InitFlags,
211 requested: InitFlags,
212 max_readahead: u32,
213 max_max_readahead: u32,
214 max_background: u16,
215 congestion_threshold: Option<u16>,
216 max_write: u32,
217 time_gran: Duration,
218 max_stack_depth: u32,
219 kernel_abi: Version,
220}
221
222impl KernelConfig {
223 fn new(capabilities: InitFlags, max_readahead: u32, kernel_abi: Version) -> Self {
224 Self {
225 capabilities,
226 requested: default_init_flags(capabilities),
227 max_readahead,
228 max_max_readahead: max_readahead,
229 max_background: 16,
230 congestion_threshold: None,
231 max_write: MAX_WRITE_SIZE as u32,
233 time_gran: Duration::new(0, 1),
235 max_stack_depth: 0,
236 kernel_abi,
237 }
238 }
239
240 pub fn set_max_stack_depth(&mut self, value: u32) -> Result<u32, u32> {
255 const FILESYSTEM_MAX_STACK_DEPTH: u32 = 2;
257
258 if value > FILESYSTEM_MAX_STACK_DEPTH {
259 return Err(FILESYSTEM_MAX_STACK_DEPTH);
260 }
261
262 let previous = self.max_stack_depth;
263 self.max_stack_depth = value;
264 Ok(previous)
265 }
266
267 pub fn set_time_granularity(&mut self, value: Duration) -> Result<Duration, Duration> {
275 if value.as_nanos() == 0 {
276 return Err(Duration::new(0, 1));
277 }
278 if value.as_secs() > 1 || (value.as_secs() == 1 && value.subsec_nanos() > 0) {
279 return Err(Duration::new(1, 0));
280 }
281 let mut power_of_10 = 1;
282 while power_of_10 < value.as_nanos() {
283 if value.as_nanos() < power_of_10 * 10 {
284 return Err(Duration::new(0, power_of_10 as u32));
286 }
287 power_of_10 *= 10;
288 }
289 let previous = self.time_gran;
290 self.time_gran = value;
291 Ok(previous)
292 }
293
294 pub fn set_max_write(&mut self, value: u32) -> Result<u32, u32> {
300 if value == 0 {
301 return Err(1);
302 }
303 if value > MAX_WRITE_SIZE as u32 {
304 return Err(MAX_WRITE_SIZE as u32);
305 }
306 let previous = self.max_write;
307 self.max_write = value;
308 Ok(previous)
309 }
310
311 pub fn set_max_readahead(&mut self, value: u32) -> Result<u32, u32> {
317 if value == 0 {
318 return Err(1);
319 }
320 if value > self.max_max_readahead {
321 return Err(self.max_max_readahead);
322 }
323 let previous = self.max_readahead;
324 self.max_readahead = value;
325 Ok(previous)
326 }
327
328 pub fn capabilities(&self) -> InitFlags {
330 self.capabilities & !InitFlags::FUSE_INIT_EXT
331 }
332
333 pub fn kernel_abi(&self) -> Version {
335 self.kernel_abi
336 }
337
338 pub fn add_capabilities(&mut self, capabilities_to_add: InitFlags) -> Result<(), InitFlags> {
343 if !self.capabilities.contains(capabilities_to_add) {
344 let unsupported = capabilities_to_add & !self.capabilities;
345 return Err(unsupported);
346 }
347 self.requested |= capabilities_to_add;
348 Ok(())
349 }
350
351 pub fn set_max_background(&mut self, value: u16) -> Result<u16, u16> {
357 if value == 0 {
358 return Err(1);
359 }
360 let previous = self.max_background;
361 self.max_background = value;
362 Ok(previous)
363 }
364
365 pub fn set_congestion_threshold(&mut self, value: u16) -> Result<u16, u16> {
372 if value == 0 {
373 return Err(1);
374 }
375 let previous = self.congestion_threshold();
376 self.congestion_threshold = Some(value);
377 Ok(previous)
378 }
379
380 fn congestion_threshold(&self) -> u16 {
381 match self.congestion_threshold {
382 None => (u32::from(self.max_background) * 3 / 4) as u16,
384 Some(value) => min(value, self.max_background),
385 }
386 }
387
388 fn max_pages(&self) -> u16 {
389 ((max(self.max_write, self.max_readahead) - 1) / page_size::get() as u32) as u16 + 1
390 }
391}
392
393#[allow(clippy::too_many_arguments)]
400pub trait Filesystem: Send + Sync + 'static {
401 fn init(&mut self, _req: &Request, _config: &mut KernelConfig) -> io::Result<()> {
405 Ok(())
406 }
407
408 fn destroy(&mut self) {}
411
412 fn lookup(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEntry) {
414 warn!("[Not Implemented] lookup(parent: {parent:#x?}, name {name:?})");
415 reply.error(Errno::ENOSYS);
416 }
417
418 fn forget(&self, _req: &Request, _ino: INodeNo, _nlookup: u64) {}
426
427 fn batch_forget(&self, req: &Request, nodes: &[ForgetOne]) {
430 for node in nodes {
431 self.forget(req, node.nodeid(), node.nlookup());
432 }
433 }
434
435 fn getattr(&self, _req: &Request, ino: INodeNo, fh: Option<FileHandle>, reply: ReplyAttr) {
437 warn!("[Not Implemented] getattr(ino: {ino:#x?}, fh: {fh:#x?})");
438 reply.error(Errno::ENOSYS);
439 }
440
441 fn setattr(
443 &self,
444 _req: &Request,
445 ino: INodeNo,
446 mode: Option<u32>,
447 uid: Option<u32>,
448 gid: Option<u32>,
449 size: Option<u64>,
450 _atime: Option<TimeOrNow>,
451 _mtime: Option<TimeOrNow>,
452 _ctime: Option<SystemTime>,
453 fh: Option<FileHandle>,
454 _crtime: Option<SystemTime>,
455 _chgtime: Option<SystemTime>,
456 _bkuptime: Option<SystemTime>,
457 flags: Option<BsdFileFlags>,
458 reply: ReplyAttr,
459 ) {
460 warn!(
461 "[Not Implemented] setattr(ino: {ino:#x?}, mode: {mode:?}, uid: {uid:?}, \
462 gid: {gid:?}, size: {size:?}, fh: {fh:?}, flags: {flags:?})"
463 );
464 reply.error(Errno::ENOSYS);
465 }
466
467 fn readlink(&self, _req: &Request, ino: INodeNo, reply: ReplyData) {
469 warn!("[Not Implemented] readlink(ino: {ino:#x?})");
470 reply.error(Errno::ENOSYS);
471 }
472
473 fn mknod(
476 &self,
477 _req: &Request,
478 parent: INodeNo,
479 name: &OsStr,
480 mode: u32,
481 umask: u32,
482 rdev: u32,
483 reply: ReplyEntry,
484 ) {
485 warn!(
486 "[Not Implemented] mknod(parent: {parent:#x?}, name: {name:?}, \
487 mode: {mode}, umask: {umask:#x?}, rdev: {rdev})"
488 );
489 reply.error(Errno::ENOSYS);
490 }
491
492 fn mkdir(
494 &self,
495 _req: &Request,
496 parent: INodeNo,
497 name: &OsStr,
498 mode: u32,
499 umask: u32,
500 reply: ReplyEntry,
501 ) {
502 warn!(
503 "[Not Implemented] mkdir(parent: {parent:#x?}, name: {name:?}, mode: {mode}, umask: {umask:#x?})"
504 );
505 reply.error(Errno::ENOSYS);
506 }
507
508 fn unlink(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) {
510 warn!("[Not Implemented] unlink(parent: {parent:#x?}, name: {name:?})",);
511 reply.error(Errno::ENOSYS);
512 }
513
514 fn rmdir(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) {
516 warn!("[Not Implemented] rmdir(parent: {parent:#x?}, name: {name:?})",);
517 reply.error(Errno::ENOSYS);
518 }
519
520 fn symlink(
522 &self,
523 _req: &Request,
524 parent: INodeNo,
525 link_name: &OsStr,
526 target: &Path,
527 reply: ReplyEntry,
528 ) {
529 warn!(
530 "[Not Implemented] symlink(parent: {parent:#x?}, link_name: {link_name:?}, target: {target:?})",
531 );
532 reply.error(Errno::EPERM);
533 }
534
535 fn rename(
537 &self,
538 _req: &Request,
539 parent: INodeNo,
540 name: &OsStr,
541 newparent: INodeNo,
542 newname: &OsStr,
543 flags: RenameFlags,
544 reply: ReplyEmpty,
545 ) {
546 warn!(
547 "[Not Implemented] rename(parent: {parent:#x?}, name: {name:?}, \
548 newparent: {newparent:#x?}, newname: {newname:?}, flags: {flags})",
549 );
550 reply.error(Errno::ENOSYS);
551 }
552
553 fn link(
555 &self,
556 _req: &Request,
557 ino: INodeNo,
558 newparent: INodeNo,
559 newname: &OsStr,
560 reply: ReplyEntry,
561 ) {
562 warn!(
563 "[Not Implemented] link(ino: {ino:#x?}, newparent: {newparent:#x?}, newname: {newname:?})"
564 );
565 reply.error(Errno::EPERM);
566 }
567
568 fn open(&self, _req: &Request, _ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) {
577 reply.opened(FileHandle(0), FopenFlags::empty());
578 }
579
580 fn read(
591 &self,
592 _req: &Request,
593 ino: INodeNo,
594 fh: FileHandle,
595 offset: u64,
596 size: u32,
597 flags: OpenFlags,
598 lock_owner: Option<LockOwner>,
599 reply: ReplyData,
600 ) {
601 warn!(
602 "[Not Implemented] read(ino: {ino:#x?}, fh: {fh}, offset: {offset}, \
603 size: {size}, flags: {flags:#x?}, lock_owner: {lock_owner:?})"
604 );
605 reply.error(Errno::ENOSYS);
606 }
607
608 fn write(
621 &self,
622 _req: &Request,
623 ino: INodeNo,
624 fh: FileHandle,
625 offset: u64,
626 data: &[u8],
627 write_flags: WriteFlags,
628 flags: OpenFlags,
629 lock_owner: Option<LockOwner>,
630 reply: ReplyWrite,
631 ) {
632 warn!(
633 "[Not Implemented] write(ino: {ino:#x?}, fh: {fh}, offset: {offset}, \
634 data.len(): {}, write_flags: {write_flags:#x?}, flags: {flags:#x?}, \
635 lock_owner: {lock_owner:?})",
636 data.len()
637 );
638 reply.error(Errno::ENOSYS);
639 }
640
641 fn flush(
652 &self,
653 _req: &Request,
654 ino: INodeNo,
655 fh: FileHandle,
656 lock_owner: LockOwner,
657 reply: ReplyEmpty,
658 ) {
659 warn!("[Not Implemented] flush(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner:?})");
660 reply.error(Errno::ENOSYS);
661 }
662
663 fn release(
672 &self,
673 _req: &Request,
674 _ino: INodeNo,
675 _fh: FileHandle,
676 _flags: OpenFlags,
677 _lock_owner: Option<LockOwner>,
678 _flush: bool,
679 reply: ReplyEmpty,
680 ) {
681 reply.ok();
682 }
683
684 fn fsync(
688 &self,
689 _req: &Request,
690 ino: INodeNo,
691 fh: FileHandle,
692 datasync: bool,
693 reply: ReplyEmpty,
694 ) {
695 warn!("[Not Implemented] fsync(ino: {ino:#x?}, fh: {fh}, datasync: {datasync})");
696 reply.error(Errno::ENOSYS);
697 }
698
699 fn opendir(&self, _req: &Request, _ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) {
707 reply.opened(FileHandle(0), FopenFlags::empty());
708 }
709
710 fn readdir(
716 &self,
717 _req: &Request,
718 ino: INodeNo,
719 fh: FileHandle,
720 offset: u64,
721 reply: ReplyDirectory,
722 ) {
723 warn!("[Not Implemented] readdir(ino: {ino:#x?}, fh: {fh}, offset: {offset})");
724 reply.error(Errno::ENOSYS);
725 }
726
727 fn readdirplus(
733 &self,
734 _req: &Request,
735 ino: INodeNo,
736 fh: FileHandle,
737 offset: u64,
738 reply: ReplyDirectoryPlus,
739 ) {
740 warn!("[Not Implemented] readdirplus(ino: {ino:#x?}, fh: {fh}, offset: {offset})");
741 reply.error(Errno::ENOSYS);
742 }
743
744 fn releasedir(
749 &self,
750 _req: &Request,
751 _ino: INodeNo,
752 _fh: FileHandle,
753 _flags: OpenFlags,
754 reply: ReplyEmpty,
755 ) {
756 reply.ok();
757 }
758
759 fn fsyncdir(
764 &self,
765 _req: &Request,
766 ino: INodeNo,
767 fh: FileHandle,
768 datasync: bool,
769 reply: ReplyEmpty,
770 ) {
771 warn!("[Not Implemented] fsyncdir(ino: {ino:#x?}, fh: {fh}, datasync: {datasync})");
772 reply.error(Errno::ENOSYS);
773 }
774
775 fn statfs(&self, _req: &Request, _ino: INodeNo, reply: ReplyStatfs) {
777 reply.statfs(0, 0, 0, 0, 0, 512, 255, 0);
778 }
779
780 fn setxattr(
782 &self,
783 _req: &Request,
784 ino: INodeNo,
785 name: &OsStr,
786 _value: &[u8],
787 flags: i32,
788 position: u32,
789 reply: ReplyEmpty,
790 ) {
791 warn!(
792 "[Not Implemented] setxattr(ino: {ino:#x?}, name: {name:?}, \
793 flags: {flags:#x?}, position: {position})"
794 );
795 reply.error(Errno::ENOSYS);
796 }
797
798 fn getxattr(&self, _req: &Request, ino: INodeNo, name: &OsStr, size: u32, reply: ReplyXattr) {
803 warn!("[Not Implemented] getxattr(ino: {ino:#x?}, name: {name:?}, size: {size})");
804 reply.error(Errno::ENOSYS);
805 }
806
807 fn listxattr(&self, _req: &Request, ino: INodeNo, size: u32, reply: ReplyXattr) {
812 warn!("[Not Implemented] listxattr(ino: {ino:#x?}, size: {size})");
813 reply.error(Errno::ENOSYS);
814 }
815
816 fn removexattr(&self, _req: &Request, ino: INodeNo, name: &OsStr, reply: ReplyEmpty) {
818 warn!("[Not Implemented] removexattr(ino: {ino:#x?}, name: {name:?})");
819 reply.error(Errno::ENOSYS);
820 }
821
822 fn access(&self, _req: &Request, ino: INodeNo, mask: AccessFlags, reply: ReplyEmpty) {
827 warn!("[Not Implemented] access(ino: {ino:#x?}, mask: {mask})");
828 reply.error(Errno::ENOSYS);
829 }
830
831 fn create(
842 &self,
843 _req: &Request,
844 parent: INodeNo,
845 name: &OsStr,
846 mode: u32,
847 umask: u32,
848 flags: i32,
849 reply: ReplyCreate,
850 ) {
851 warn!(
852 "[Not Implemented] create(parent: {parent:#x?}, name: {name:?}, mode: {mode}, \
853 umask: {umask:#x?}, flags: {flags:#x?})"
854 );
855 reply.error(Errno::ENOSYS);
856 }
857
858 fn getlk(
860 &self,
861 _req: &Request,
862 ino: INodeNo,
863 fh: FileHandle,
864 lock_owner: LockOwner,
865 start: u64,
866 end: u64,
867 typ: i32,
868 pid: u32,
869 reply: ReplyLock,
870 ) {
871 warn!(
872 "[Not Implemented] getlk(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner}, \
873 start: {start}, end: {end}, typ: {typ}, pid: {pid})"
874 );
875 reply.error(Errno::ENOSYS);
876 }
877
878 fn setlk(
886 &self,
887 _req: &Request,
888 ino: INodeNo,
889 fh: FileHandle,
890 lock_owner: LockOwner,
891 start: u64,
892 end: u64,
893 typ: i32,
894 pid: u32,
895 sleep: bool,
896 reply: ReplyEmpty,
897 ) {
898 warn!(
899 "[Not Implemented] setlk(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner}, \
900 start: {start}, end: {end}, typ: {typ}, pid: {pid}, sleep: {sleep})"
901 );
902 reply.error(Errno::ENOSYS);
903 }
904
905 fn bmap(&self, _req: &Request, ino: INodeNo, blocksize: u32, idx: u64, reply: ReplyBmap) {
909 warn!("[Not Implemented] bmap(ino: {ino:#x?}, blocksize: {blocksize}, idx: {idx})",);
910 reply.error(Errno::ENOSYS);
911 }
912
913 fn ioctl(
915 &self,
916 _req: &Request,
917 ino: INodeNo,
918 fh: FileHandle,
919 flags: IoctlFlags,
920 cmd: u32,
921 in_data: &[u8],
922 out_size: u32,
923 reply: ReplyIoctl,
924 ) {
925 warn!(
926 "[Not Implemented] ioctl(ino: {ino:#x?}, fh: {fh}, flags: {flags}, \
927 cmd: {cmd}, in_data.len(): {}, out_size: {out_size})",
928 in_data.len()
929 );
930 reply.error(Errno::ENOSYS);
931 }
932
933 fn poll(
935 &self,
936 _req: &Request,
937 ino: INodeNo,
938 fh: FileHandle,
939 ph: PollNotifier,
940 events: PollEvents,
941 flags: PollFlags,
942 reply: ReplyPoll,
943 ) {
944 warn!(
945 "[Not Implemented] poll(ino: {ino:#x?}, fh: {fh}, \
946 ph: {ph:?}, events: {events}, flags: {flags})"
947 );
948 reply.error(Errno::ENOSYS);
949 }
950
951 fn fallocate(
953 &self,
954 _req: &Request,
955 ino: INodeNo,
956 fh: FileHandle,
957 offset: u64,
958 length: u64,
959 mode: i32,
960 reply: ReplyEmpty,
961 ) {
962 warn!(
963 "[Not Implemented] fallocate(ino: {ino:#x?}, fh: {fh}, \
964 offset: {offset}, length: {length}, mode: {mode})"
965 );
966 reply.error(Errno::ENOSYS);
967 }
968
969 fn lseek(
971 &self,
972 _req: &Request,
973 ino: INodeNo,
974 fh: FileHandle,
975 offset: i64,
976 whence: i32,
977 reply: ReplyLseek,
978 ) {
979 warn!(
980 "[Not Implemented] lseek(ino: {ino:#x?}, fh: {fh}, \
981 offset: {offset}, whence: {whence})"
982 );
983 reply.error(Errno::ENOSYS);
984 }
985
986 fn copy_file_range(
988 &self,
989 _req: &Request,
990 ino_in: INodeNo,
991 fh_in: FileHandle,
992 offset_in: u64,
993 ino_out: INodeNo,
994 fh_out: FileHandle,
995 offset_out: u64,
996 len: u64,
997 flags: CopyFileRangeFlags,
998 reply: ReplyWrite,
999 ) {
1000 warn!(
1001 "[Not Implemented] copy_file_range(ino_in: {ino_in:#x?}, fh_in: {fh_in}, \
1002 offset_in: {offset_in}, ino_out: {ino_out:#x?}, fh_out: {fh_out}, \
1003 offset_out: {offset_out}, len: {len}, flags: {flags:?})"
1004 );
1005 reply.error(Errno::ENOSYS);
1006 }
1007
1008 #[cfg(target_os = "macos")]
1011 fn setvolname(&self, _req: &Request, name: &OsStr, reply: ReplyEmpty) {
1012 warn!("[Not Implemented] setvolname(name: {name:?})");
1013 reply.error(Errno::ENOSYS);
1014 }
1015
1016 #[cfg(target_os = "macos")]
1018 fn exchange(
1019 &self,
1020 _req: &Request,
1021 parent: INodeNo,
1022 name: &OsStr,
1023 newparent: INodeNo,
1024 newname: &OsStr,
1025 options: u64,
1026 reply: ReplyEmpty,
1027 ) {
1028 warn!(
1029 "[Not Implemented] exchange(parent: {parent:#x?}, name: {name:?}, \
1030 newparent: {newparent:#x?}, newname: {newname:?}, options: {options})"
1031 );
1032 reply.error(Errno::ENOSYS);
1033 }
1034
1035 #[cfg(target_os = "macos")]
1038 fn getxtimes(&self, _req: &Request, ino: INodeNo, reply: ReplyXTimes) {
1039 warn!("[Not Implemented] getxtimes(ino: {ino:#x?})");
1040 reply.error(Errno::ENOSYS);
1041 }
1042}
1043
1044pub fn mount<FS: Filesystem, P: AsRef<Path>>(
1052 filesystem: FS,
1053 mountpoint: P,
1054 options: &Config,
1055) -> io::Result<()> {
1056 Session::new(filesystem, mountpoint.as_ref(), options).and_then(session::Session::run)
1057}
1058
1059pub fn spawn_mount<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef<Path>>(
1069 filesystem: FS,
1070 mountpoint: P,
1071 options: &Config,
1072) -> io::Result<BackgroundSession> {
1073 Session::new(filesystem, mountpoint.as_ref(), options).and_then(session::Session::spawn)
1074}