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;
52use crate::mnt::mount_options::check_option_conflicts;
53pub use crate::notify::Notifier;
54pub use crate::notify::PollHandle;
55pub use crate::notify::PollNotifier;
56pub use crate::open_flags::OpenAccMode;
57pub use crate::open_flags::OpenFlags;
58pub use crate::passthrough::BackingId;
59pub use crate::poll_events::PollEvents;
60pub use crate::rename_flags::RenameFlags;
61pub use crate::reply::ReplyAttr;
62pub use crate::reply::ReplyBmap;
63pub use crate::reply::ReplyCreate;
64pub use crate::reply::ReplyData;
65pub use crate::reply::ReplyDirectory;
66pub use crate::reply::ReplyDirectoryPlus;
67pub use crate::reply::ReplyEmpty;
68pub use crate::reply::ReplyEntry;
69pub use crate::reply::ReplyIoctl;
70pub use crate::reply::ReplyLock;
71pub use crate::reply::ReplyLseek;
72pub use crate::reply::ReplyOpen;
73pub use crate::reply::ReplyPoll;
74pub use crate::reply::ReplyStatfs;
75pub use crate::reply::ReplyWrite;
76pub use crate::reply::ReplyXattr;
77pub use crate::request_param::Request;
78pub use crate::session::BackgroundSession;
79use crate::session::MAX_WRITE_SIZE;
80pub use crate::session::Session;
81pub use crate::session::SessionACL;
82pub use crate::session::SessionUnmounter;
83
84mod access_flags;
85mod bsd_file_flags;
86mod channel;
87mod dev_fuse;
88#[cfg(feature = "experimental")]
90pub mod experimental;
91mod forget_one;
92mod ll;
93mod mnt;
94mod notify;
95mod open_flags;
96mod passthrough;
97mod poll_events;
98mod read_buf;
99mod rename_flags;
100mod reply;
101mod request;
102mod request_param;
103mod session;
104mod time;
105
106#[cfg(not(target_os = "macos"))]
108const INIT_FLAGS: InitFlags = InitFlags::FUSE_ASYNC_READ.union(InitFlags::FUSE_BIG_WRITES);
109#[cfg(target_os = "macos")]
114const INIT_FLAGS: InitFlags = InitFlags::FUSE_ASYNC_READ
115 .union(InitFlags::FUSE_CASE_INSENSITIVE)
116 .union(InitFlags::FUSE_VOL_RENAME)
117 .union(InitFlags::FUSE_XTIMES);
118fn default_init_flags(capabilities: InitFlags) -> InitFlags {
121 let mut flags = INIT_FLAGS;
122 if capabilities.contains(InitFlags::FUSE_MAX_PAGES) {
123 flags |= InitFlags::FUSE_MAX_PAGES;
124 }
125 flags
126}
127
128#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
130#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
131pub enum FileType {
132 NamedPipe,
134 CharDevice,
136 BlockDevice,
138 Directory,
140 RegularFile,
142 Symlink,
144 Socket,
146}
147
148impl FileType {
149 pub fn from_std(file_type: std::fs::FileType) -> Option<Self> {
151 if file_type.is_file() {
152 Some(FileType::RegularFile)
153 } else if file_type.is_dir() {
154 Some(FileType::Directory)
155 } else if file_type.is_symlink() {
156 Some(FileType::Symlink)
157 } else if file_type.is_fifo() {
158 Some(FileType::NamedPipe)
159 } else if file_type.is_socket() {
160 Some(FileType::Socket)
161 } else if file_type.is_char_device() {
162 Some(FileType::CharDevice)
163 } else if file_type.is_block_device() {
164 Some(FileType::BlockDevice)
165 } else {
166 None
167 }
168 }
169}
170
171#[derive(Clone, Copy, Debug, Eq, PartialEq)]
173#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
174pub struct FileAttr {
175 pub ino: INodeNo,
177 pub size: u64,
179 pub blocks: u64,
182 pub atime: SystemTime,
184 pub mtime: SystemTime,
186 pub ctime: SystemTime,
188 pub crtime: SystemTime,
190 pub kind: FileType,
192 pub perm: u16,
194 pub nlink: u32,
196 pub uid: u32,
198 pub gid: u32,
200 pub rdev: u32,
202 pub blksize: u32,
204 pub flags: u32,
206}
207
208#[derive(Debug)]
210pub struct KernelConfig {
211 capabilities: InitFlags,
212 requested: InitFlags,
213 max_readahead: u32,
214 max_max_readahead: u32,
215 max_background: u16,
216 congestion_threshold: Option<u16>,
217 max_write: u32,
218 time_gran: Duration,
219 max_stack_depth: u32,
220 kernel_abi: Version,
221}
222
223impl KernelConfig {
224 fn new(capabilities: InitFlags, max_readahead: u32, kernel_abi: Version) -> Self {
225 Self {
226 capabilities,
227 requested: default_init_flags(capabilities),
228 max_readahead,
229 max_max_readahead: max_readahead,
230 max_background: 16,
231 congestion_threshold: None,
232 max_write: MAX_WRITE_SIZE as u32,
234 time_gran: Duration::new(0, 1),
236 max_stack_depth: 0,
237 kernel_abi,
238 }
239 }
240
241 pub fn set_max_stack_depth(&mut self, value: u32) -> Result<u32, u32> {
256 const FILESYSTEM_MAX_STACK_DEPTH: u32 = 2;
258
259 if value > FILESYSTEM_MAX_STACK_DEPTH {
260 return Err(FILESYSTEM_MAX_STACK_DEPTH);
261 }
262
263 let previous = self.max_stack_depth;
264 self.max_stack_depth = value;
265 Ok(previous)
266 }
267
268 pub fn set_time_granularity(&mut self, value: Duration) -> Result<Duration, Duration> {
276 if value.as_nanos() == 0 {
277 return Err(Duration::new(0, 1));
278 }
279 if value.as_secs() > 1 || (value.as_secs() == 1 && value.subsec_nanos() > 0) {
280 return Err(Duration::new(1, 0));
281 }
282 let mut power_of_10 = 1;
283 while power_of_10 < value.as_nanos() {
284 if value.as_nanos() < power_of_10 * 10 {
285 return Err(Duration::new(0, power_of_10 as u32));
287 }
288 power_of_10 *= 10;
289 }
290 let previous = self.time_gran;
291 self.time_gran = value;
292 Ok(previous)
293 }
294
295 pub fn set_max_write(&mut self, value: u32) -> Result<u32, u32> {
301 if value == 0 {
302 return Err(1);
303 }
304 if value > MAX_WRITE_SIZE as u32 {
305 return Err(MAX_WRITE_SIZE as u32);
306 }
307 let previous = self.max_write;
308 self.max_write = value;
309 Ok(previous)
310 }
311
312 pub fn set_max_readahead(&mut self, value: u32) -> Result<u32, u32> {
318 if value == 0 {
319 return Err(1);
320 }
321 if value > self.max_max_readahead {
322 return Err(self.max_max_readahead);
323 }
324 let previous = self.max_readahead;
325 self.max_readahead = value;
326 Ok(previous)
327 }
328
329 pub fn capabilities(&self) -> InitFlags {
331 self.capabilities & !InitFlags::FUSE_INIT_EXT
332 }
333
334 pub fn kernel_abi(&self) -> Version {
336 self.kernel_abi
337 }
338
339 pub fn add_capabilities(&mut self, capabilities_to_add: InitFlags) -> Result<(), InitFlags> {
344 if !self.capabilities.contains(capabilities_to_add) {
345 let unsupported = capabilities_to_add & !self.capabilities;
346 return Err(unsupported);
347 }
348 self.requested |= capabilities_to_add;
349 Ok(())
350 }
351
352 pub fn set_max_background(&mut self, value: u16) -> Result<u16, u16> {
358 if value == 0 {
359 return Err(1);
360 }
361 let previous = self.max_background;
362 self.max_background = value;
363 Ok(previous)
364 }
365
366 pub fn set_congestion_threshold(&mut self, value: u16) -> Result<u16, u16> {
373 if value == 0 {
374 return Err(1);
375 }
376 let previous = self.congestion_threshold();
377 self.congestion_threshold = Some(value);
378 Ok(previous)
379 }
380
381 fn congestion_threshold(&self) -> u16 {
382 match self.congestion_threshold {
383 None => (u32::from(self.max_background) * 3 / 4) as u16,
385 Some(value) => min(value, self.max_background),
386 }
387 }
388
389 fn max_pages(&self) -> u16 {
390 ((max(self.max_write, self.max_readahead) - 1) / page_size::get() as u32) as u16 + 1
391 }
392}
393
394#[allow(clippy::too_many_arguments)]
401pub trait Filesystem: Send + Sync + 'static {
402 fn init(&mut self, _req: &Request, _config: &mut KernelConfig) -> io::Result<()> {
406 Ok(())
407 }
408
409 fn destroy(&mut self) {}
412
413 fn lookup(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEntry) {
415 warn!("[Not Implemented] lookup(parent: {parent:#x?}, name {name:?})");
416 reply.error(Errno::ENOSYS);
417 }
418
419 fn forget(&self, _req: &Request, _ino: INodeNo, _nlookup: u64) {}
427
428 fn batch_forget(&self, req: &Request, nodes: &[ForgetOne]) {
431 for node in nodes {
432 self.forget(req, node.nodeid(), node.nlookup());
433 }
434 }
435
436 fn getattr(&self, _req: &Request, ino: INodeNo, fh: Option<FileHandle>, reply: ReplyAttr) {
438 warn!("[Not Implemented] getattr(ino: {ino:#x?}, fh: {fh:#x?})");
439 reply.error(Errno::ENOSYS);
440 }
441
442 fn setattr(
444 &self,
445 _req: &Request,
446 ino: INodeNo,
447 mode: Option<u32>,
448 uid: Option<u32>,
449 gid: Option<u32>,
450 size: Option<u64>,
451 _atime: Option<TimeOrNow>,
452 _mtime: Option<TimeOrNow>,
453 _ctime: Option<SystemTime>,
454 fh: Option<FileHandle>,
455 _crtime: Option<SystemTime>,
456 _chgtime: Option<SystemTime>,
457 _bkuptime: Option<SystemTime>,
458 flags: Option<BsdFileFlags>,
459 reply: ReplyAttr,
460 ) {
461 warn!(
462 "[Not Implemented] setattr(ino: {ino:#x?}, mode: {mode:?}, uid: {uid:?}, \
463 gid: {gid:?}, size: {size:?}, fh: {fh:?}, flags: {flags:?})"
464 );
465 reply.error(Errno::ENOSYS);
466 }
467
468 fn readlink(&self, _req: &Request, ino: INodeNo, reply: ReplyData) {
470 warn!("[Not Implemented] readlink(ino: {ino:#x?})");
471 reply.error(Errno::ENOSYS);
472 }
473
474 fn mknod(
477 &self,
478 _req: &Request,
479 parent: INodeNo,
480 name: &OsStr,
481 mode: u32,
482 umask: u32,
483 rdev: u32,
484 reply: ReplyEntry,
485 ) {
486 warn!(
487 "[Not Implemented] mknod(parent: {parent:#x?}, name: {name:?}, \
488 mode: {mode}, umask: {umask:#x?}, rdev: {rdev})"
489 );
490 reply.error(Errno::ENOSYS);
491 }
492
493 fn mkdir(
495 &self,
496 _req: &Request,
497 parent: INodeNo,
498 name: &OsStr,
499 mode: u32,
500 umask: u32,
501 reply: ReplyEntry,
502 ) {
503 warn!(
504 "[Not Implemented] mkdir(parent: {parent:#x?}, name: {name:?}, mode: {mode}, umask: {umask:#x?})"
505 );
506 reply.error(Errno::ENOSYS);
507 }
508
509 fn unlink(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) {
511 warn!("[Not Implemented] unlink(parent: {parent:#x?}, name: {name:?})",);
512 reply.error(Errno::ENOSYS);
513 }
514
515 fn rmdir(&self, _req: &Request, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) {
517 warn!("[Not Implemented] rmdir(parent: {parent:#x?}, name: {name:?})",);
518 reply.error(Errno::ENOSYS);
519 }
520
521 fn symlink(
523 &self,
524 _req: &Request,
525 parent: INodeNo,
526 link_name: &OsStr,
527 target: &Path,
528 reply: ReplyEntry,
529 ) {
530 warn!(
531 "[Not Implemented] symlink(parent: {parent:#x?}, link_name: {link_name:?}, target: {target:?})",
532 );
533 reply.error(Errno::EPERM);
534 }
535
536 fn rename(
538 &self,
539 _req: &Request,
540 parent: INodeNo,
541 name: &OsStr,
542 newparent: INodeNo,
543 newname: &OsStr,
544 flags: RenameFlags,
545 reply: ReplyEmpty,
546 ) {
547 warn!(
548 "[Not Implemented] rename(parent: {parent:#x?}, name: {name:?}, \
549 newparent: {newparent:#x?}, newname: {newname:?}, flags: {flags})",
550 );
551 reply.error(Errno::ENOSYS);
552 }
553
554 fn link(
556 &self,
557 _req: &Request,
558 ino: INodeNo,
559 newparent: INodeNo,
560 newname: &OsStr,
561 reply: ReplyEntry,
562 ) {
563 warn!(
564 "[Not Implemented] link(ino: {ino:#x?}, newparent: {newparent:#x?}, newname: {newname:?})"
565 );
566 reply.error(Errno::EPERM);
567 }
568
569 fn open(&self, _req: &Request, _ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) {
578 reply.opened(FileHandle(0), FopenFlags::empty());
579 }
580
581 fn read(
592 &self,
593 _req: &Request,
594 ino: INodeNo,
595 fh: FileHandle,
596 offset: u64,
597 size: u32,
598 flags: OpenFlags,
599 lock_owner: Option<LockOwner>,
600 reply: ReplyData,
601 ) {
602 warn!(
603 "[Not Implemented] read(ino: {ino:#x?}, fh: {fh}, offset: {offset}, \
604 size: {size}, flags: {flags:#x?}, lock_owner: {lock_owner:?})"
605 );
606 reply.error(Errno::ENOSYS);
607 }
608
609 fn write(
622 &self,
623 _req: &Request,
624 ino: INodeNo,
625 fh: FileHandle,
626 offset: u64,
627 data: &[u8],
628 write_flags: WriteFlags,
629 flags: OpenFlags,
630 lock_owner: Option<LockOwner>,
631 reply: ReplyWrite,
632 ) {
633 warn!(
634 "[Not Implemented] write(ino: {ino:#x?}, fh: {fh}, offset: {offset}, \
635 data.len(): {}, write_flags: {write_flags:#x?}, flags: {flags:#x?}, \
636 lock_owner: {lock_owner:?})",
637 data.len()
638 );
639 reply.error(Errno::ENOSYS);
640 }
641
642 fn flush(
653 &self,
654 _req: &Request,
655 ino: INodeNo,
656 fh: FileHandle,
657 lock_owner: LockOwner,
658 reply: ReplyEmpty,
659 ) {
660 warn!("[Not Implemented] flush(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner:?})");
661 reply.error(Errno::ENOSYS);
662 }
663
664 fn release(
673 &self,
674 _req: &Request,
675 _ino: INodeNo,
676 _fh: FileHandle,
677 _flags: OpenFlags,
678 _lock_owner: Option<LockOwner>,
679 _flush: bool,
680 reply: ReplyEmpty,
681 ) {
682 reply.ok();
683 }
684
685 fn fsync(
689 &self,
690 _req: &Request,
691 ino: INodeNo,
692 fh: FileHandle,
693 datasync: bool,
694 reply: ReplyEmpty,
695 ) {
696 warn!("[Not Implemented] fsync(ino: {ino:#x?}, fh: {fh}, datasync: {datasync})");
697 reply.error(Errno::ENOSYS);
698 }
699
700 fn opendir(&self, _req: &Request, _ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) {
708 reply.opened(FileHandle(0), FopenFlags::empty());
709 }
710
711 fn readdir(
717 &self,
718 _req: &Request,
719 ino: INodeNo,
720 fh: FileHandle,
721 offset: u64,
722 reply: ReplyDirectory,
723 ) {
724 warn!("[Not Implemented] readdir(ino: {ino:#x?}, fh: {fh}, offset: {offset})");
725 reply.error(Errno::ENOSYS);
726 }
727
728 fn readdirplus(
734 &self,
735 _req: &Request,
736 ino: INodeNo,
737 fh: FileHandle,
738 offset: u64,
739 reply: ReplyDirectoryPlus,
740 ) {
741 warn!("[Not Implemented] readdirplus(ino: {ino:#x?}, fh: {fh}, offset: {offset})");
742 reply.error(Errno::ENOSYS);
743 }
744
745 fn releasedir(
750 &self,
751 _req: &Request,
752 _ino: INodeNo,
753 _fh: FileHandle,
754 _flags: OpenFlags,
755 reply: ReplyEmpty,
756 ) {
757 reply.ok();
758 }
759
760 fn fsyncdir(
765 &self,
766 _req: &Request,
767 ino: INodeNo,
768 fh: FileHandle,
769 datasync: bool,
770 reply: ReplyEmpty,
771 ) {
772 warn!("[Not Implemented] fsyncdir(ino: {ino:#x?}, fh: {fh}, datasync: {datasync})");
773 reply.error(Errno::ENOSYS);
774 }
775
776 fn statfs(&self, _req: &Request, _ino: INodeNo, reply: ReplyStatfs) {
778 reply.statfs(0, 0, 0, 0, 0, 512, 255, 0);
779 }
780
781 fn setxattr(
783 &self,
784 _req: &Request,
785 ino: INodeNo,
786 name: &OsStr,
787 _value: &[u8],
788 flags: i32,
789 position: u32,
790 reply: ReplyEmpty,
791 ) {
792 warn!(
793 "[Not Implemented] setxattr(ino: {ino:#x?}, name: {name:?}, \
794 flags: {flags:#x?}, position: {position})"
795 );
796 reply.error(Errno::ENOSYS);
797 }
798
799 fn getxattr(&self, _req: &Request, ino: INodeNo, name: &OsStr, size: u32, reply: ReplyXattr) {
804 warn!("[Not Implemented] getxattr(ino: {ino:#x?}, name: {name:?}, size: {size})");
805 reply.error(Errno::ENOSYS);
806 }
807
808 fn listxattr(&self, _req: &Request, ino: INodeNo, size: u32, reply: ReplyXattr) {
813 warn!("[Not Implemented] listxattr(ino: {ino:#x?}, size: {size})");
814 reply.error(Errno::ENOSYS);
815 }
816
817 fn removexattr(&self, _req: &Request, ino: INodeNo, name: &OsStr, reply: ReplyEmpty) {
819 warn!("[Not Implemented] removexattr(ino: {ino:#x?}, name: {name:?})");
820 reply.error(Errno::ENOSYS);
821 }
822
823 fn access(&self, _req: &Request, ino: INodeNo, mask: AccessFlags, reply: ReplyEmpty) {
828 warn!("[Not Implemented] access(ino: {ino:#x?}, mask: {mask})");
829 reply.error(Errno::ENOSYS);
830 }
831
832 fn create(
843 &self,
844 _req: &Request,
845 parent: INodeNo,
846 name: &OsStr,
847 mode: u32,
848 umask: u32,
849 flags: i32,
850 reply: ReplyCreate,
851 ) {
852 warn!(
853 "[Not Implemented] create(parent: {parent:#x?}, name: {name:?}, mode: {mode}, \
854 umask: {umask:#x?}, flags: {flags:#x?})"
855 );
856 reply.error(Errno::ENOSYS);
857 }
858
859 fn getlk(
861 &self,
862 _req: &Request,
863 ino: INodeNo,
864 fh: FileHandle,
865 lock_owner: LockOwner,
866 start: u64,
867 end: u64,
868 typ: i32,
869 pid: u32,
870 reply: ReplyLock,
871 ) {
872 warn!(
873 "[Not Implemented] getlk(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner}, \
874 start: {start}, end: {end}, typ: {typ}, pid: {pid})"
875 );
876 reply.error(Errno::ENOSYS);
877 }
878
879 fn setlk(
887 &self,
888 _req: &Request,
889 ino: INodeNo,
890 fh: FileHandle,
891 lock_owner: LockOwner,
892 start: u64,
893 end: u64,
894 typ: i32,
895 pid: u32,
896 sleep: bool,
897 reply: ReplyEmpty,
898 ) {
899 warn!(
900 "[Not Implemented] setlk(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner}, \
901 start: {start}, end: {end}, typ: {typ}, pid: {pid}, sleep: {sleep})"
902 );
903 reply.error(Errno::ENOSYS);
904 }
905
906 fn bmap(&self, _req: &Request, ino: INodeNo, blocksize: u32, idx: u64, reply: ReplyBmap) {
910 warn!("[Not Implemented] bmap(ino: {ino:#x?}, blocksize: {blocksize}, idx: {idx})",);
911 reply.error(Errno::ENOSYS);
912 }
913
914 fn ioctl(
916 &self,
917 _req: &Request,
918 ino: INodeNo,
919 fh: FileHandle,
920 flags: IoctlFlags,
921 cmd: u32,
922 in_data: &[u8],
923 out_size: u32,
924 reply: ReplyIoctl,
925 ) {
926 warn!(
927 "[Not Implemented] ioctl(ino: {ino:#x?}, fh: {fh}, flags: {flags}, \
928 cmd: {cmd}, in_data.len(): {}, out_size: {out_size})",
929 in_data.len()
930 );
931 reply.error(Errno::ENOSYS);
932 }
933
934 fn poll(
936 &self,
937 _req: &Request,
938 ino: INodeNo,
939 fh: FileHandle,
940 ph: PollNotifier,
941 events: PollEvents,
942 flags: PollFlags,
943 reply: ReplyPoll,
944 ) {
945 warn!(
946 "[Not Implemented] poll(ino: {ino:#x?}, fh: {fh}, \
947 ph: {ph:?}, events: {events}, flags: {flags})"
948 );
949 reply.error(Errno::ENOSYS);
950 }
951
952 fn fallocate(
954 &self,
955 _req: &Request,
956 ino: INodeNo,
957 fh: FileHandle,
958 offset: u64,
959 length: u64,
960 mode: i32,
961 reply: ReplyEmpty,
962 ) {
963 warn!(
964 "[Not Implemented] fallocate(ino: {ino:#x?}, fh: {fh}, \
965 offset: {offset}, length: {length}, mode: {mode})"
966 );
967 reply.error(Errno::ENOSYS);
968 }
969
970 fn lseek(
972 &self,
973 _req: &Request,
974 ino: INodeNo,
975 fh: FileHandle,
976 offset: i64,
977 whence: i32,
978 reply: ReplyLseek,
979 ) {
980 warn!(
981 "[Not Implemented] lseek(ino: {ino:#x?}, fh: {fh}, \
982 offset: {offset}, whence: {whence})"
983 );
984 reply.error(Errno::ENOSYS);
985 }
986
987 fn copy_file_range(
989 &self,
990 _req: &Request,
991 ino_in: INodeNo,
992 fh_in: FileHandle,
993 offset_in: u64,
994 ino_out: INodeNo,
995 fh_out: FileHandle,
996 offset_out: u64,
997 len: u64,
998 flags: CopyFileRangeFlags,
999 reply: ReplyWrite,
1000 ) {
1001 warn!(
1002 "[Not Implemented] copy_file_range(ino_in: {ino_in:#x?}, fh_in: {fh_in}, \
1003 offset_in: {offset_in}, ino_out: {ino_out:#x?}, fh_out: {fh_out}, \
1004 offset_out: {offset_out}, len: {len}, flags: {flags:?})"
1005 );
1006 reply.error(Errno::ENOSYS);
1007 }
1008
1009 #[cfg(target_os = "macos")]
1012 fn setvolname(&self, _req: &Request, name: &OsStr, reply: ReplyEmpty) {
1013 warn!("[Not Implemented] setvolname(name: {name:?})");
1014 reply.error(Errno::ENOSYS);
1015 }
1016
1017 #[cfg(target_os = "macos")]
1019 fn exchange(
1020 &self,
1021 _req: &Request,
1022 parent: INodeNo,
1023 name: &OsStr,
1024 newparent: INodeNo,
1025 newname: &OsStr,
1026 options: u64,
1027 reply: ReplyEmpty,
1028 ) {
1029 warn!(
1030 "[Not Implemented] exchange(parent: {parent:#x?}, name: {name:?}, \
1031 newparent: {newparent:#x?}, newname: {newname:?}, options: {options})"
1032 );
1033 reply.error(Errno::ENOSYS);
1034 }
1035
1036 #[cfg(target_os = "macos")]
1039 fn getxtimes(&self, _req: &Request, ino: INodeNo, reply: ReplyXTimes) {
1040 warn!("[Not Implemented] getxtimes(ino: {ino:#x?})");
1041 reply.error(Errno::ENOSYS);
1042 }
1043}
1044
1045pub fn mount2<FS: Filesystem, P: AsRef<Path>>(
1053 filesystem: FS,
1054 mountpoint: P,
1055 options: &Config,
1056) -> io::Result<()> {
1057 check_option_conflicts(options)?;
1058 Session::new(filesystem, mountpoint.as_ref(), options).and_then(|se| se.run())
1059}
1060
1061pub fn spawn_mount2<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef<Path>>(
1071 filesystem: FS,
1072 mountpoint: P,
1073 options: &Config,
1074) -> io::Result<BackgroundSession> {
1075 check_option_conflicts(options)?;
1076 Session::new(filesystem, mountpoint.as_ref(), options).and_then(session::Session::spawn)
1077}