From ebcb7f682a37a2b2866c3730fd6f1d0dd44f9f8a Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sat, 17 Jan 2026 03:06:41 +0000 Subject: [PATCH] Use NodeId in public API --- examples/async_hello.rs | 24 +- examples/hello.rs | 32 +-- examples/ioctl.rs | 38 +-- examples/notify_inval_entry.rs | 44 ++-- examples/notify_inval_inode.rs | 53 ++-- examples/passthrough.rs | 38 +-- examples/poll.rs | 49 ++-- examples/simple.rs | 451 +++++++++++++++++---------------- src/experimental.rs | 28 +- src/lib.rs | 115 +++++---- src/ll/fuse_abi.rs | 2 - src/ll/notify.rs | 15 +- src/ll/reply.rs | 8 +- src/ll/request.rs | 24 +- src/notify.rs | 7 +- src/reply.rs | 28 +- src/request.rs | 119 ++++----- 17 files changed, 560 insertions(+), 515 deletions(-) diff --git a/examples/async_hello.rs b/examples/async_hello.rs index f8c55fe9..9a62bad8 100644 --- a/examples/async_hello.rs +++ b/examples/async_hello.rs @@ -3,7 +3,7 @@ use fuser::experimental::{ AsyncFilesystem, DirEntListBuilder, GetAttrResponse, LookupResponse, RequestContext, TokioAdapter, }; -use fuser::{FileAttr, FileType, MountOption, experimental}; +use fuser::{FileAttr, FileType, INodeNo, MountOption, experimental}; use libc::ENOENT; use std::ffi::OsStr; use std::time::{Duration, UNIX_EPOCH}; @@ -11,7 +11,7 @@ use std::time::{Duration, UNIX_EPOCH}; const TTL: Duration = Duration::from_secs(1); // 1 second const HELLO_DIR_ATTR: FileAttr = FileAttr { - ino: 1, + ino: INodeNo::ROOT, size: 0, blocks: 0, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -31,7 +31,7 @@ const HELLO_DIR_ATTR: FileAttr = FileAttr { const HELLO_TXT_CONTENT: &str = "Hello World!\n"; const HELLO_TXT_ATTR: FileAttr = FileAttr { - ino: 2, + ino: INodeNo(2), size: 13, blocks: 1, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -55,10 +55,10 @@ impl AsyncFilesystem for HelloFS { async fn lookup( &self, _context: &RequestContext, - parent: u64, + parent: INodeNo, name: &OsStr, ) -> experimental::Result { - if parent == 1 && name.to_str() == Some("hello.txt") { + if parent == INodeNo::ROOT && name.to_str() == Some("hello.txt") { Ok(LookupResponse::new(TTL, HELLO_TXT_ATTR, 0)) } else { Err(ENOENT) @@ -68,10 +68,10 @@ impl AsyncFilesystem for HelloFS { async fn getattr( &self, _context: &RequestContext, - ino: u64, + ino: INodeNo, _file_handle: Option, ) -> experimental::Result { - match ino { + match ino.0 { 1 => Ok(GetAttrResponse::new(TTL, HELLO_DIR_ATTR)), 2 => Ok(GetAttrResponse::new(TTL, HELLO_TXT_ATTR)), _ => Err(ENOENT), @@ -81,7 +81,7 @@ impl AsyncFilesystem for HelloFS { async fn read( &self, _context: &RequestContext, - ino: u64, + ino: INodeNo, _file_handle: u64, offset: i64, _size: u32, @@ -89,7 +89,7 @@ impl AsyncFilesystem for HelloFS { _lock: Option, out_data: &mut Vec, ) -> experimental::Result<()> { - if ino == 2 { + if ino.0 == 2 { out_data.extend_from_slice(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]); Ok(()) } else { @@ -100,12 +100,12 @@ impl AsyncFilesystem for HelloFS { async fn readdir( &self, _context: &RequestContext, - ino: u64, + ino: INodeNo, _file_handle: u64, offset: i64, mut builder: DirEntListBuilder<'_>, ) -> experimental::Result<()> { - if ino != 1 { + if ino != INodeNo::ROOT { return Err(ENOENT); } @@ -117,7 +117,7 @@ impl AsyncFilesystem for HelloFS { for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) { // i + 1 means the index of the next entry - if builder.add(entry.0, (i + 1) as i64, entry.1, entry.2) { + if builder.add(INodeNo(entry.0), (i + 1) as i64, entry.1, entry.2) { break; } } diff --git a/examples/hello.rs b/examples/hello.rs index 19bc60af..51ec68d1 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -1,7 +1,7 @@ use clap::{Arg, ArgAction, Command, crate_version}; use fuser::{ - FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, - Request, + FileAttr, FileType, Filesystem, INodeNo, MountOption, ReplyAttr, ReplyData, ReplyDirectory, + ReplyEntry, Request, }; use libc::ENOENT; use std::ffi::OsStr; @@ -10,7 +10,7 @@ use std::time::{Duration, UNIX_EPOCH}; const TTL: Duration = Duration::from_secs(1); // 1 second const HELLO_DIR_ATTR: FileAttr = FileAttr { - ino: 1, + ino: INodeNo::ROOT, size: 0, blocks: 0, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -30,7 +30,7 @@ const HELLO_DIR_ATTR: FileAttr = FileAttr { const HELLO_TXT_CONTENT: &str = "Hello World!\n"; const HELLO_TXT_ATTR: FileAttr = FileAttr { - ino: 2, + ino: INodeNo(2), size: 13, blocks: 1, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -50,16 +50,16 @@ const HELLO_TXT_ATTR: FileAttr = FileAttr { struct HelloFS; impl Filesystem for HelloFS { - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - if parent == 1 && name.to_str() == Some("hello.txt") { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if u64::from(parent) == 1 && name.to_str() == Some("hello.txt") { reply.entry(&TTL, &HELLO_TXT_ATTR, 0); } else { reply.error(ENOENT); } } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: ReplyAttr) { - match ino { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { + match u64::from(ino) { 1 => reply.attr(&TTL, &HELLO_DIR_ATTR), 2 => reply.attr(&TTL, &HELLO_TXT_ATTR), _ => reply.error(ENOENT), @@ -68,16 +68,16 @@ impl Filesystem for HelloFS { fn read( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, _size: u32, _flags: i32, - _lock: Option, + _lock_owner: Option, reply: ReplyData, ) { - if ino == 2 { + if u64::from(ino) == 2 { reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]); } else { reply.error(ENOENT); @@ -86,13 +86,13 @@ impl Filesystem for HelloFS { fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - if ino != 1 { + if u64::from(ino) != 1 { reply.error(ENOENT); return; } @@ -105,7 +105,7 @@ impl Filesystem for HelloFS { for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) { // i + 1 means the index of the next entry - if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) { + if reply.add(INodeNo(entry.0), (i + 1) as i64, entry.1, entry.2) { break; } } diff --git a/examples/ioctl.rs b/examples/ioctl.rs index cfa27065..0619be52 100644 --- a/examples/ioctl.rs +++ b/examples/ioctl.rs @@ -4,8 +4,8 @@ use clap::{Arg, ArgAction, Command, crate_version}; use fuser::{ - FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, - Request, + FileAttr, FileType, Filesystem, INodeNo, MountOption, ReplyAttr, ReplyData, ReplyDirectory, + ReplyEntry, ReplyIoctl, Request, }; use libc::{EINVAL, ENOENT}; use log::debug; @@ -29,7 +29,7 @@ impl FiocFS { let gid = nix::unistd::getgid().into(); let root_attr = FileAttr { - ino: 1, + ino: INodeNo::ROOT, size: 0, blocks: 0, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -47,7 +47,7 @@ impl FiocFS { }; let fioc_file_attr = FileAttr { - ino: 2, + ino: INodeNo(2), size: 0, blocks: 1, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -73,16 +73,16 @@ impl FiocFS { } impl Filesystem for FiocFS { - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - if parent == 1 && name.to_str() == Some("fioc") { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if parent == INodeNo::ROOT && name.to_str() == Some("fioc") { reply.entry(&TTL, &self.fioc_file_attr, 0); } else { reply.error(ENOENT); } } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: ReplyAttr) { - match ino { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { + match ino.0 { 1 => reply.attr(&TTL, &self.root_attr), 2 => reply.attr(&TTL, &self.fioc_file_attr), _ => reply.error(ENOENT), @@ -91,16 +91,16 @@ impl Filesystem for FiocFS { fn read( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, _size: u32, _flags: i32, - _lock: Option, + _lock_owner: Option, reply: ReplyData, ) { - if ino == 2 { + if ino == INodeNo(2) { reply.data(&self.content[offset as usize..]); } else { reply.error(ENOENT); @@ -109,13 +109,13 @@ impl Filesystem for FiocFS { fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - if ino != 1 { + if ino != INodeNo::ROOT { reply.error(ENOENT); return; } @@ -128,7 +128,7 @@ impl Filesystem for FiocFS { for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) { // i + 1 means the index of the next entry - if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) { + if reply.add(INodeNo(entry.0), (i + 1) as i64, entry.1, entry.2) { break; } } @@ -138,15 +138,15 @@ impl Filesystem for FiocFS { fn ioctl( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, _fh: u64, _flags: u32, cmd: u32, in_data: &[u8], _out_size: u32, - reply: fuser::ReplyIoctl, + reply: ReplyIoctl, ) { - if ino != 2 { + if ino != INodeNo(2) { reply.error(EINVAL); return; } diff --git a/examples/notify_inval_entry.rs b/examples/notify_inval_entry.rs index cd017e26..c8e95ee6 100644 --- a/examples/notify_inval_entry.rs +++ b/examples/notify_inval_entry.rs @@ -22,8 +22,8 @@ use libc::{ENOBUFS, ENOENT, ENOTDIR}; use clap::Parser; use fuser::{ - FUSE_ROOT_ID, FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyDirectory, - ReplyEntry, Request, + FileAttr, FileType, Filesystem, INodeNo, MountOption, ReplyAttr, ReplyDirectory, ReplyEntry, + Request, }; struct ClockFS<'a> { @@ -40,9 +40,9 @@ impl ClockFS<'_> { n.clone() } - fn stat(ino: u64) -> Option { - let (kind, perm) = match ino { - FUSE_ROOT_ID => (FileType::Directory, 0o755), + fn stat(ino: INodeNo) -> Option { + let (kind, perm) = match ino.0 { + 1 => (FileType::Directory, 0o755), Self::FILE_INO => (FileType::RegularFile, 0o000), _ => return None, }; @@ -68,26 +68,30 @@ impl ClockFS<'_> { } impl Filesystem for ClockFS<'_> { - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - if parent != FUSE_ROOT_ID || name != AsRef::::as_ref(&self.get_filename()) { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if parent != INodeNo::ROOT || name != AsRef::::as_ref(&self.get_filename()) { reply.error(ENOENT); return; } self.lookup_cnt.fetch_add(1, SeqCst); - reply.entry(&self.timeout, &ClockFS::stat(ClockFS::FILE_INO).unwrap(), 0); + reply.entry( + &self.timeout, + &ClockFS::stat(INodeNo(ClockFS::FILE_INO)).unwrap(), + 0, + ); } - fn forget(&mut self, _req: &Request, ino: u64, nlookup: u64) { - if ino == ClockFS::FILE_INO { - let prev = self.lookup_cnt.fetch_sub(nlookup, SeqCst); - assert!(prev >= nlookup); + fn forget(&mut self, _req: &Request<'_>, ino: INodeNo, _nlookup: u64) { + if ino.0 == ClockFS::FILE_INO { + let prev = self.lookup_cnt.fetch_sub(_nlookup, SeqCst); + assert!(prev >= _nlookup); } else { - assert!(ino == FUSE_ROOT_ID); + assert!(ino == INodeNo::ROOT); } } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: ReplyAttr) { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { match ClockFS::stat(ino) { Some(a) => reply.attr(&self.timeout, &a), None => reply.error(ENOENT), @@ -96,20 +100,20 @@ impl Filesystem for ClockFS<'_> { fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - if ino != FUSE_ROOT_ID { + if ino != INodeNo::ROOT { reply.error(ENOTDIR); return; } if offset == 0 && reply.add( - ClockFS::FILE_INO, + INodeNo(ClockFS::FILE_INO), offset + 1, FileType::RegularFile, self.get_filename(), @@ -172,8 +176,8 @@ fn main() { drop(fname); if !opts.no_notify && lookup_cnt.load(SeqCst) != 0 { if opts.only_expire { - // fuser::notify_expire_entry(_SOME_HANDLE_, FUSE_ROOT_ID, &oldname); - } else if let Err(e) = notifier.inval_entry(FUSE_ROOT_ID, oldname.as_ref()) { + // fuser::notify_expire_entry(_SOME_HANDLE_, INodeNo::ROOT, &oldname); + } else if let Err(e) = notifier.inval_entry(INodeNo::ROOT, oldname.as_ref()) { eprintln!("Warning: failed to invalidate entry '{oldname}': {e}"); } } diff --git a/examples/notify_inval_inode.rs b/examples/notify_inval_inode.rs index 3b8940c6..c0e6657d 100644 --- a/examples/notify_inval_inode.rs +++ b/examples/notify_inval_inode.rs @@ -22,7 +22,7 @@ use libc::{EACCES, EINVAL, EISDIR, ENOBUFS, ENOENT, ENOTDIR}; use clap::Parser; use fuser::{ - FUSE_ROOT_ID, FileAttr, FileType, Filesystem, MountOption, OpenAccMode, OpenFlags, ReplyAttr, + FileAttr, FileType, Filesystem, INodeNo, MountOption, OpenAccMode, OpenFlags, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, ReplyOpen, Request, consts, }; @@ -35,9 +35,9 @@ impl ClockFS<'_> { const FILE_INO: u64 = 2; const FILE_NAME: &'static str = "current_time"; - fn stat(&self, ino: u64) -> Option { - let (kind, perm, size) = match ino { - FUSE_ROOT_ID => (FileType::Directory, 0o755, 0), + fn stat(&self, ino: INodeNo) -> Option { + let (kind, perm, size) = match ino.0 { + 1 => (FileType::Directory, 0o755, 0), Self::FILE_INO => ( FileType::RegularFile, 0o444, @@ -67,26 +67,30 @@ impl ClockFS<'_> { } impl Filesystem for ClockFS<'_> { - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - if parent != FUSE_ROOT_ID || name != AsRef::::as_ref(&Self::FILE_NAME) { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if parent != INodeNo::ROOT || name != AsRef::::as_ref(&Self::FILE_NAME) { reply.error(ENOENT); return; } self.lookup_cnt.fetch_add(1, SeqCst); - reply.entry(&Duration::MAX, &self.stat(ClockFS::FILE_INO).unwrap(), 0); + reply.entry( + &Duration::MAX, + &self.stat(INodeNo(ClockFS::FILE_INO)).unwrap(), + 0, + ); } - fn forget(&mut self, _req: &Request, ino: u64, nlookup: u64) { - if ino == ClockFS::FILE_INO { - let prev = self.lookup_cnt.fetch_sub(nlookup, SeqCst); - assert!(prev >= nlookup); + fn forget(&mut self, _req: &Request<'_>, ino: INodeNo, _nlookup: u64) { + if ino == INodeNo(ClockFS::FILE_INO) { + let prev = self.lookup_cnt.fetch_sub(_nlookup, SeqCst); + assert!(prev >= _nlookup); } else { - assert!(ino == FUSE_ROOT_ID); + assert!(ino == INodeNo::ROOT); } } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: ReplyAttr) { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { match self.stat(ino) { Some(a) => reply.attr(&Duration::MAX, &a), None => reply.error(ENOENT), @@ -95,20 +99,20 @@ impl Filesystem for ClockFS<'_> { fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - if ino != FUSE_ROOT_ID { + if ino != INodeNo::ROOT { reply.error(ENOTDIR); return; } if offset == 0 && reply.add( - ClockFS::FILE_INO, + INodeNo(ClockFS::FILE_INO), offset + 1, FileType::RegularFile, Self::FILE_NAME, @@ -120,23 +124,24 @@ impl Filesystem for ClockFS<'_> { } } - fn open(&mut self, _req: &Request, ino: u64, flags: OpenFlags, reply: ReplyOpen) { - if ino == FUSE_ROOT_ID { + fn open(&mut self, _req: &Request<'_>, ino: INodeNo, flags: OpenFlags, reply: ReplyOpen) { + if ino == INodeNo::ROOT { reply.error(EISDIR); } else if flags.acc_mode() != OpenAccMode::O_RDONLY { reply.error(EACCES); - } else if ino != Self::FILE_INO { + } else if ino.0 != Self::FILE_INO { eprintln!("Got open for nonexistent inode {ino}"); reply.error(ENOENT); } else { - reply.opened(ino, consts::FOPEN_KEEP_CACHE); + // TODO: we are supposed to pass file handle here, not ino. + reply.opened(ino.0, consts::FOPEN_KEEP_CACHE); } } fn read( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, size: u32, @@ -144,7 +149,7 @@ impl Filesystem for ClockFS<'_> { _lock_owner: Option, reply: ReplyData, ) { - assert!(ino == Self::FILE_INO); + assert!(ino == INodeNo(Self::FILE_INO)); if offset < 0 { reply.error(EINVAL); return; diff --git a/examples/passthrough.rs b/examples/passthrough.rs index 95cec433..44328a66 100644 --- a/examples/passthrough.rs +++ b/examples/passthrough.rs @@ -4,8 +4,8 @@ use clap::{Arg, ArgAction, Command, crate_version}; use fuser::{ - BackingId, FileAttr, FileType, Filesystem, InitFlags, KernelConfig, MountOption, OpenFlags, - ReplyAttr, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, Request, + BackingId, FileAttr, FileType, Filesystem, INodeNo, InitFlags, KernelConfig, MountOption, + OpenFlags, ReplyAttr, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, Request, }; use libc::ENOENT; use std::collections::HashMap; @@ -34,7 +34,7 @@ const TTL: Duration = Duration::from_secs(1); // 1 second #[derive(Debug, Default)] struct BackingCache { by_handle: HashMap>, - by_inode: HashMap>, + by_inode: HashMap>, next_fh: u64, } @@ -50,7 +50,7 @@ impl BackingCache { /// returned file handle should be `put()` when you're done with it. fn get_or( &mut self, - ino: u64, + ino: INodeNo, callback: impl Fn() -> std::io::Result, ) -> std::io::Result<(u64, Rc)> { let fh = self.next_fh(); @@ -93,7 +93,7 @@ impl PassthroughFs { let gid = nix::unistd::getgid().into(); let root_attr = FileAttr { - ino: 1, + ino: INodeNo::ROOT, size: 0, blocks: 0, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -111,7 +111,7 @@ impl PassthroughFs { }; let passthrough_file_attr = FileAttr { - ino: 2, + ino: INodeNo(2), size: 123_456, blocks: 1, atime: UNIX_EPOCH, // 1970-01-01 00:00:00 @@ -149,24 +149,24 @@ impl Filesystem for PassthroughFs { Ok(()) } - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { - if parent == 1 && name.to_str() == Some("passthrough") { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if parent == INodeNo::ROOT && name.to_str() == Some("passthrough") { reply.entry(&TTL, &self.passthrough_file_attr, 0); } else { reply.error(ENOENT); } } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: ReplyAttr) { - match ino { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { + match ino.0 { 1 => reply.attr(&TTL, &self.root_attr), 2 => reply.attr(&TTL, &self.passthrough_file_attr), _ => reply.error(ENOENT), } } - fn open(&mut self, _req: &Request, ino: u64, _flags: OpenFlags, reply: ReplyOpen) { - if ino != 2 { + fn open(&mut self, _req: &Request<'_>, ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) { + if ino != INodeNo(2) { reply.error(ENOENT); return; } @@ -186,26 +186,26 @@ impl Filesystem for PassthroughFs { fn release( &mut self, _req: &Request<'_>, - _ino: u64, - fh: u64, + _ino: INodeNo, + _fh: u64, _flags: i32, _lock_owner: Option, _flush: bool, reply: ReplyEmpty, ) { - self.backing_cache.put(fh); + self.backing_cache.put(_fh); reply.ok(); } fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - if ino != 1 { + if ino != INodeNo::ROOT { reply.error(ENOENT); return; } @@ -218,7 +218,7 @@ impl Filesystem for PassthroughFs { for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) { // i + 1 means the index of the next entry - if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) { + if reply.add(INodeNo(entry.0), (i + 1) as i64, entry.1, entry.2) { break; } } diff --git a/examples/poll.rs b/examples/poll.rs index b3c86dd9..27e0ba83 100644 --- a/examples/poll.rs +++ b/examples/poll.rs @@ -22,7 +22,8 @@ use std::{ use libc::{EACCES, EBADF, EBUSY, EINVAL, ENOENT, ENOTDIR}; use fuser::{ - FUSE_ROOT_ID, FileAttr, FileType, MountOption, OpenAccMode, OpenFlags, PollHandle, Request, + FileAttr, FileType, INodeNo, MountOption, OpenAccMode, OpenFlags, PollHandle, ReplyAttr, + ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, Request, consts::{FOPEN_DIRECT_IO, FOPEN_NONSEEKABLE, FUSE_POLL_SCHEDULE_NOTIFY}, }; @@ -41,13 +42,13 @@ struct FSelFS { } impl FSelData { - fn idx_to_ino(idx: u8) -> u64 { + fn idx_to_ino(idx: u8) -> INodeNo { let idx: u64 = idx.into(); - FUSE_ROOT_ID + idx + 1 + INodeNo(INodeNo::ROOT.0 + idx + 1) } - fn ino_to_idx(ino: u64) -> u8 { - (ino - (FUSE_ROOT_ID + 1)) + fn ino_to_idx(ino: INodeNo) -> u8 { + (ino.0 - (INodeNo::ROOT.0 + 1)) .try_into() .expect("out-of-range inode number") } @@ -81,8 +82,8 @@ impl FSelFS { } impl fuser::Filesystem for FSelFS { - fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: fuser::ReplyEntry) { - if parent != FUSE_ROOT_ID || name.len() != 1 { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { + if parent != INodeNo::ROOT || name.len() != 1 { reply.error(ENOENT); return; } @@ -101,10 +102,10 @@ impl fuser::Filesystem for FSelFS { reply.entry(&Duration::ZERO, &self.get_data().filestat(idx), 0); } - fn getattr(&mut self, _req: &Request, ino: u64, _fh: Option, reply: fuser::ReplyAttr) { - if ino == FUSE_ROOT_ID { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { + if ino == INodeNo::ROOT { let a = FileAttr { - ino: FUSE_ROOT_ID, + ino: INodeNo::ROOT, size: 0, blocks: 0, atime: UNIX_EPOCH, @@ -133,13 +134,13 @@ impl fuser::Filesystem for FSelFS { fn readdir( &mut self, - _req: &Request, - ino: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, - mut reply: fuser::ReplyDirectory, + mut reply: ReplyDirectory, ) { - if ino != FUSE_ROOT_ID { + if ino != INodeNo::ROOT { reply.error(ENOTDIR); return; } @@ -169,7 +170,7 @@ impl fuser::Filesystem for FSelFS { reply.ok(); } - fn open(&mut self, _req: &Request, ino: u64, flags: OpenFlags, reply: fuser::ReplyOpen) { + fn open(&mut self, _req: &Request<'_>, ino: INodeNo, flags: OpenFlags, reply: ReplyOpen) { let idx = FSelData::ino_to_idx(ino); if idx >= NUMFILES { reply.error(ENOENT); @@ -197,15 +198,15 @@ impl fuser::Filesystem for FSelFS { fn release( &mut self, - _req: &Request, - _ino: u64, - fh: u64, + _req: &Request<'_>, + _ino: INodeNo, + _fh: u64, _flags: i32, _lock_owner: Option, _flush: bool, - reply: fuser::ReplyEmpty, + reply: ReplyEmpty, ) { - let idx = fh; + let idx = _fh; if idx >= NUMFILES.into() { reply.error(EBADF); return; @@ -216,14 +217,14 @@ impl fuser::Filesystem for FSelFS { fn read( &mut self, - _req: &Request, - _ino: u64, + _req: &Request<'_>, + _ino: INodeNo, fh: u64, _offset: i64, size: u32, _flags: i32, _lock_owner: Option, - reply: fuser::ReplyData, + reply: ReplyData, ) { let Ok(idx): Result = fh.try_into() else { reply.error(EINVAL); @@ -249,7 +250,7 @@ impl fuser::Filesystem for FSelFS { fn poll( &mut self, _req: &Request, - _ino: u64, + _ino: INodeNo, fh: u64, ph: PollHandle, _events: u32, diff --git a/examples/simple.rs b/examples/simple.rs index 12932142..277620ec 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -7,9 +7,9 @@ use fuser::consts::FOPEN_DIRECT_IO; // use fuser::consts::FUSE_WRITE_KILL_PRIV; use fuser::TimeOrNow::Now; use fuser::{ - FUSE_ROOT_ID, Filesystem, InitFlags, KernelConfig, MountOption, OpenAccMode, OpenFlags, - ReplyAttr, ReplyCreate, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, - ReplyStatfs, ReplyWrite, ReplyXattr, Request, TimeOrNow, + Filesystem, INodeNo, InitFlags, KernelConfig, MountOption, OpenAccMode, OpenFlags, ReplyAttr, + ReplyCreate, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, ReplyStatfs, + ReplyWrite, ReplyXattr, Request, TimeOrNow, }; #[cfg(feature = "abi-7-26")] use log::info; @@ -43,9 +43,7 @@ const FILE_HANDLE_WRITE_BIT: u64 = 1 << 62; const FMODE_EXEC: i32 = 0x20; -type Inode = u64; - -type DirectoryDescriptor = BTreeMap, (Inode, FileKind)>; +type DirectoryDescriptor = BTreeMap, (u64, FileKind)>; #[derive(Serialize, Deserialize, Copy, Clone, PartialEq)] enum FileKind { @@ -199,7 +197,7 @@ fn time_from_system_time(system_time: &SystemTime) -> (i64, u32) { #[derive(Serialize, Deserialize)] struct InodeAttributes { - pub inode: Inode, + pub inode: u64, pub open_file_handles: u64, // Ref count of open file handles to this inode pub size: u64, pub last_accessed: (i64, u32), @@ -217,7 +215,7 @@ struct InodeAttributes { impl From for fuser::FileAttr { fn from(attrs: InodeAttributes) -> Self { fuser::FileAttr { - ino: attrs.inode, + ino: INodeNo(attrs.inode), size: attrs.size, blocks: attrs.size.div_ceil(u64::from(BLOCK_SIZE)), atime: system_time_from_time(attrs.last_accessed.0, attrs.last_accessed.1), @@ -282,11 +280,11 @@ impl SimpleFS { } } - fn allocate_next_inode(&self) -> Inode { + fn allocate_next_inode(&self) -> INodeNo { let path = Path::new(&self.data_dir).join("superblock"); let current_inode = match File::open(&path) { - Ok(file) => bincode::deserialize_from(file).unwrap(), - _ => fuser::FUSE_ROOT_ID, + Ok(file) => INodeNo(bincode::deserialize_from(file).unwrap()), + _ => INodeNo::ROOT, }; let file = OpenOptions::new() @@ -295,9 +293,9 @@ impl SimpleFS { .truncate(true) .open(&path) .unwrap(); - bincode::serialize_into(file, &(current_inode + 1)).unwrap(); + bincode::serialize_into(file, &(current_inode.0 + 1)).unwrap(); - current_inode + 1 + INodeNo(current_inode.0 + 1) } fn allocate_next_file_handle(&self, read: bool, write: bool) -> u64 { @@ -322,13 +320,13 @@ impl SimpleFS { (file_handle & FILE_HANDLE_WRITE_BIT) != 0 } - fn content_path(&self, inode: Inode) -> PathBuf { + fn content_path(&self, inode: INodeNo) -> PathBuf { Path::new(&self.data_dir) .join("contents") .join(inode.to_string()) } - fn get_directory_content(&self, inode: Inode) -> Result { + fn get_directory_content(&self, inode: INodeNo) -> Result { let path = Path::new(&self.data_dir) .join("contents") .join(inode.to_string()); @@ -338,7 +336,7 @@ impl SimpleFS { } } - fn write_directory_content(&self, inode: Inode, entries: &DirectoryDescriptor) { + fn write_directory_content(&self, inode: INodeNo, entries: &DirectoryDescriptor) { let path = Path::new(&self.data_dir) .join("contents") .join(inode.to_string()); @@ -351,7 +349,7 @@ impl SimpleFS { bincode::serialize_into(file, &entries).unwrap(); } - fn get_inode(&self, inode: Inode) -> Result { + fn get_inode(&self, inode: INodeNo) -> Result { let path = Path::new(&self.data_dir) .join("inodes") .join(inode.to_string()); @@ -395,7 +393,7 @@ impl SimpleFS { fn truncate( &self, - inode: Inode, + inode: INodeNo, new_length: u64, uid: u32, gid: u32, @@ -426,10 +424,10 @@ impl SimpleFS { Ok(attrs) } - fn lookup_name(&self, parent: u64, name: &OsStr) -> Result { + fn lookup_name(&self, parent: INodeNo, name: &OsStr) -> Result { let entries = self.get_directory_content(parent)?; if let Some((inode, _)) = entries.get(name.as_bytes()) { - return self.get_inode(*inode); + return self.get_inode(INodeNo(*inode)); } return Err(libc::ENOENT); } @@ -437,9 +435,9 @@ impl SimpleFS { fn insert_link( &self, req: &Request, - parent: u64, + parent: INodeNo, name: &OsStr, - inode: u64, + inode: INodeNo, kind: FileKind, ) -> Result<(), c_int> { if self.lookup_name(parent, name).is_ok() { @@ -463,7 +461,7 @@ impl SimpleFS { self.write_inode(&parent_attrs); let mut entries = self.get_directory_content(parent).unwrap(); - entries.insert(name.as_bytes().to_vec(), (inode, kind)); + entries.insert(name.as_bytes().to_vec(), (inode.0, kind)); self.write_directory_content(parent, &entries); Ok(()) @@ -484,10 +482,10 @@ impl Filesystem for SimpleFS { fs::create_dir_all(Path::new(&self.data_dir).join("inodes")).unwrap(); fs::create_dir_all(Path::new(&self.data_dir).join("contents")).unwrap(); - if self.get_inode(FUSE_ROOT_ID).is_err() { + if self.get_inode(INodeNo::ROOT).is_err() { // Initialize with empty filesystem let root = InodeAttributes { - inode: FUSE_ROOT_ID, + inode: INodeNo::ROOT.0, open_file_handles: 0, size: 0, last_accessed: time_now(), @@ -502,13 +500,13 @@ impl Filesystem for SimpleFS { }; self.write_inode(&root); let mut entries = BTreeMap::new(); - entries.insert(b".".to_vec(), (FUSE_ROOT_ID, FileKind::Directory)); - self.write_directory_content(FUSE_ROOT_ID, &entries); + entries.insert(b".".to_vec(), (INodeNo::ROOT.0, FileKind::Directory)); + self.write_directory_content(INodeNo::ROOT, &entries); } Ok(()) } - fn lookup(&mut self, req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { if name.len() > MAX_NAME_LENGTH as usize { reply.error(libc::ENAMETOOLONG); return; @@ -518,8 +516,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::X_OK, ) { reply.error(libc::EACCES); @@ -532,10 +530,10 @@ impl Filesystem for SimpleFS { } } - fn forget(&mut self, _req: &Request, _ino: u64, _nlookup: u64) {} + fn forget(&mut self, _req: &Request<'_>, _ino: INodeNo, _nlookup: u64) {} - fn getattr(&mut self, _req: &Request, inode: u64, _fh: Option, reply: ReplyAttr) { - match self.get_inode(inode) { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, _fh: Option, reply: ReplyAttr) { + match self.get_inode(ino) { Ok(attrs) => reply.attr(&Duration::new(0, 0), &attrs.into()), Err(error_code) => reply.error(error_code), } @@ -543,14 +541,14 @@ impl Filesystem for SimpleFS { fn setattr( &mut self, - req: &Request, - inode: u64, + _req: &Request<'_>, + ino: INodeNo, mode: Option, uid: Option, gid: Option, size: Option, - atime: Option, - mtime: Option, + _atime: Option, + _mtime: Option, _ctime: Option, fh: Option, _crtime: Option, @@ -559,7 +557,7 @@ impl Filesystem for SimpleFS { _flags: Option, reply: ReplyAttr, ) { - let mut attrs = match self.get_inode(inode) { + let mut attrs = match self.get_inode(ino) { Ok(attrs) => attrs, Err(error_code) => { reply.error(error_code); @@ -568,11 +566,11 @@ impl Filesystem for SimpleFS { }; if let Some(mode) = mode { - debug!("chmod() called with {inode:?}, {mode:o}"); + debug!("chmod() called with {ino:?}, {mode:o}"); #[cfg(target_os = "freebsd")] { // FreeBSD: sticky bit only valid on directories; otherwise EFTYPE - if req.uid() != 0 + if _req.uid() != 0 && (mode as u16 & libc::S_ISVTX as u16) != 0 && attrs.kind != FileKind::Directory { @@ -580,13 +578,13 @@ impl Filesystem for SimpleFS { return; } } - if req.uid() != 0 && req.uid() != attrs.uid { + if _req.uid() != 0 && _req.uid() != attrs.uid { reply.error(libc::EPERM); return; } - if req.uid() != 0 - && req.gid() != attrs.gid - && !get_groups(req.pid()).contains(&attrs.gid) + if _req.uid() != 0 + && _req.gid() != attrs.gid + && !get_groups(_req.pid()).contains(&attrs.gid) { // If SGID is set and the file belongs to a group that the caller is not part of // then the SGID bit is suppose to be cleared during chmod @@ -601,25 +599,25 @@ impl Filesystem for SimpleFS { } if uid.is_some() || gid.is_some() { - debug!("chown() called with {inode:?} {uid:?} {gid:?}"); + debug!("chown() called with {ino:?} {uid:?} {gid:?}"); if let Some(gid) = gid { // Non-root users can only change gid to a group they're in - if req.uid() != 0 && !get_groups(req.pid()).contains(&gid) { + if _req.uid() != 0 && !get_groups(_req.pid()).contains(&gid) { reply.error(libc::EPERM); return; } } if let Some(uid) = uid { - if req.uid() != 0 + if _req.uid() != 0 // but no-op changes by the owner are not an error - && !(uid == attrs.uid && req.uid() == attrs.uid) + && !(uid == attrs.uid && _req.uid() == attrs.uid) { reply.error(libc::EPERM); return; } } // Only owner may change the group - if gid.is_some() && req.uid() != 0 && req.uid() != attrs.uid { + if gid.is_some() && _req.uid() != 0 && _req.uid() != attrs.uid { reply.error(libc::EPERM); return; } @@ -637,7 +635,7 @@ impl Filesystem for SimpleFS { if let Some(gid) = gid { attrs.gid = gid; // Clear SETGID unless user is root - if req.uid() != 0 { + if _req.uid() != 0 { attrs.mode &= !libc::S_ISGID as u16; } } @@ -648,14 +646,14 @@ impl Filesystem for SimpleFS { } if let Some(size) = size { - debug!("truncate() called with {inode:?} {size:?}"); + debug!("truncate() called with {ino:?} {size:?}"); if let Some(handle) = fh { // If the file handle is available, check access locally. // This is important as it preserves the semantic that a file handle opened // with W_OK will never fail to truncate, even if the file has been subsequently // chmod'ed if Self::check_file_handle_write(handle) { - if let Err(error_code) = self.truncate(inode, size, 0, 0) { + if let Err(error_code) = self.truncate(ino, size, 0, 0) { reply.error(error_code); return; } @@ -663,28 +661,28 @@ impl Filesystem for SimpleFS { reply.error(libc::EACCES); return; } - } else if let Err(error_code) = self.truncate(inode, size, req.uid(), req.gid()) { + } else if let Err(error_code) = self.truncate(ino, size, _req.uid(), _req.gid()) { reply.error(error_code); return; } } let now = time_now(); - if let Some(atime) = atime { - debug!("utimens() called with {inode:?}, atime={atime:?}"); + if let Some(atime) = _atime { + debug!("utimens() called with {ino:?}, atime={atime:?}"); - if attrs.uid != req.uid() && req.uid() != 0 && atime != Now { + if attrs.uid != _req.uid() && _req.uid() != 0 && atime != Now { reply.error(libc::EPERM); return; } - if attrs.uid != req.uid() + if attrs.uid != _req.uid() && !check_access( attrs.uid, attrs.gid, attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { @@ -699,21 +697,21 @@ impl Filesystem for SimpleFS { attrs.last_metadata_changed = now; self.write_inode(&attrs); } - if let Some(mtime) = mtime { - debug!("utimens() called with {inode:?}, mtime={mtime:?}"); + if let Some(mtime) = _mtime { + debug!("utimens() called with {ino:?}, mtime={mtime:?}"); - if attrs.uid != req.uid() && req.uid() != 0 && mtime != Now { + if attrs.uid != _req.uid() && _req.uid() != 0 && mtime != Now { reply.error(libc::EPERM); return; } - if attrs.uid != req.uid() + if attrs.uid != _req.uid() && !check_access( attrs.uid, attrs.gid, attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { @@ -729,14 +727,14 @@ impl Filesystem for SimpleFS { self.write_inode(&attrs); } - let attrs = self.get_inode(inode).unwrap(); + let attrs = self.get_inode(ino).unwrap(); reply.attr(&Duration::new(0, 0), &attrs.into()); return; } - fn readlink(&mut self, _req: &Request, inode: u64, reply: ReplyData) { - debug!("readlink() called on {inode:?}"); - let path = self.content_path(inode); + fn readlink(&mut self, _req: &Request<'_>, ino: INodeNo, reply: ReplyData) { + debug!("readlink() called on {ino:?}"); + let path = self.content_path(ino); match File::open(path) { Ok(mut file) => { let file_size = file.metadata().unwrap().len(); @@ -752,8 +750,8 @@ impl Filesystem for SimpleFS { fn mknod( &mut self, - req: &Request, - parent: u64, + _req: &Request<'_>, + parent: INodeNo, name: &OsStr, mut mode: u32, _umask: u32, @@ -791,8 +789,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -802,7 +800,7 @@ impl Filesystem for SimpleFS { parent_attrs.last_metadata_changed = time_now(); self.write_inode(&parent_attrs); - if req.uid() != 0 { + if _req.uid() != 0 { mode &= !(libc::S_ISUID | libc::S_ISGID) as u32; } @@ -810,7 +808,7 @@ impl Filesystem for SimpleFS { { let kind = as_file_kind(mode); // FreeBSD: sticky bit only valid on directories; otherwise EFTYPE - if req.uid() != 0 + if _req.uid() != 0 && (mode as u16 & libc::S_ISVTX as u16) != 0 && kind != FileKind::Directory { @@ -821,7 +819,7 @@ impl Filesystem for SimpleFS { let inode = self.allocate_next_inode(); let attrs = InodeAttributes { - inode, + inode: inode.0, open_file_handles: 0, size: 0, last_accessed: time_now(), @@ -830,8 +828,8 @@ impl Filesystem for SimpleFS { kind: as_file_kind(mode), mode: self.creation_mode(mode), hardlinks: 1, - uid: req.uid(), - gid: creation_gid(&parent_attrs, req.gid()), + uid: _req.uid(), + gid: creation_gid(&parent_attrs, _req.gid()), xattrs: BTreeMap::default(), }; self.write_inode(&attrs); @@ -839,13 +837,13 @@ impl Filesystem for SimpleFS { if as_file_kind(mode) == FileKind::Directory { let mut entries = BTreeMap::new(); - entries.insert(b".".to_vec(), (inode, FileKind::Directory)); - entries.insert(b"..".to_vec(), (parent, FileKind::Directory)); + entries.insert(b".".to_vec(), (inode.0, FileKind::Directory)); + entries.insert(b"..".to_vec(), (parent.0, FileKind::Directory)); self.write_directory_content(inode, &entries); } let mut entries = self.get_directory_content(parent).unwrap(); - entries.insert(name.as_bytes().to_vec(), (inode, attrs.kind)); + entries.insert(name.as_bytes().to_vec(), (inode.0, attrs.kind)); self.write_directory_content(parent, &entries); // TODO: implement flags @@ -854,8 +852,8 @@ impl Filesystem for SimpleFS { fn mkdir( &mut self, - req: &Request, - parent: u64, + _req: &Request<'_>, + parent: INodeNo, name: &OsStr, mut mode: u32, _umask: u32, @@ -879,8 +877,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -890,7 +888,7 @@ impl Filesystem for SimpleFS { parent_attrs.last_metadata_changed = time_now(); self.write_inode(&parent_attrs); - if req.uid() != 0 { + if _req.uid() != 0 { mode &= !(libc::S_ISUID | libc::S_ISGID) as u32; } if parent_attrs.mode & libc::S_ISGID as u16 != 0 { @@ -899,7 +897,7 @@ impl Filesystem for SimpleFS { let inode = self.allocate_next_inode(); let attrs = InodeAttributes { - inode, + inode: inode.0, open_file_handles: 0, size: u64::from(BLOCK_SIZE), last_accessed: time_now(), @@ -908,25 +906,25 @@ impl Filesystem for SimpleFS { kind: FileKind::Directory, mode: self.creation_mode(mode), hardlinks: 2, // Directories start with link count of 2, since they have a self link - uid: req.uid(), - gid: creation_gid(&parent_attrs, req.gid()), + uid: _req.uid(), + gid: creation_gid(&parent_attrs, _req.gid()), xattrs: BTreeMap::default(), }; self.write_inode(&attrs); let mut entries = BTreeMap::new(); - entries.insert(b".".to_vec(), (inode, FileKind::Directory)); - entries.insert(b"..".to_vec(), (parent, FileKind::Directory)); + entries.insert(b".".to_vec(), (inode.0, FileKind::Directory)); + entries.insert(b"..".to_vec(), (parent.0, FileKind::Directory)); self.write_directory_content(inode, &entries); let mut entries = self.get_directory_content(parent).unwrap(); - entries.insert(name.as_bytes().to_vec(), (inode, FileKind::Directory)); + entries.insert(name.as_bytes().to_vec(), (inode.0, FileKind::Directory)); self.write_directory_content(parent, &entries); reply.entry(&Duration::new(0, 0), &attrs.into(), 0); } - fn unlink(&mut self, req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) { + fn unlink(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) { debug!("unlink() called with {parent:?} {name:?}"); let mut attrs = match self.lookup_name(parent, name) { Ok(attrs) => attrs, @@ -948,15 +946,15 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); return; } - let uid = req.uid(); + let uid = _req.uid(); // "Sticky bit" handling if parent_attrs.mode & libc::S_ISVTX as u16 != 0 && uid != 0 @@ -983,7 +981,7 @@ impl Filesystem for SimpleFS { reply.ok(); } - fn rmdir(&mut self, req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) { + fn rmdir(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) { debug!("rmdir() called with {parent:?} {name:?}"); let mut attrs = match self.lookup_name(parent, name) { Ok(attrs) => attrs, @@ -1002,7 +1000,12 @@ impl Filesystem for SimpleFS { }; // Directories always have a self and parent link - if self.get_directory_content(attrs.inode).unwrap().len() > 2 { + if self + .get_directory_content(INodeNo(attrs.inode)) + .unwrap() + .len() + > 2 + { reply.error(libc::ENOTEMPTY); return; } @@ -1010,8 +1013,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -1020,9 +1023,9 @@ impl Filesystem for SimpleFS { // "Sticky bit" handling if parent_attrs.mode & libc::S_ISVTX as u16 != 0 - && req.uid() != 0 - && req.uid() != parent_attrs.uid - && req.uid() != attrs.uid + && _req.uid() != 0 + && _req.uid() != parent_attrs.uid + && _req.uid() != attrs.uid { reply.error(libc::EACCES); return; @@ -1046,8 +1049,8 @@ impl Filesystem for SimpleFS { fn symlink( &mut self, - req: &Request, - parent: u64, + _req: &Request<'_>, + parent: INodeNo, link_name: &OsStr, target: &Path, reply: ReplyEntry, @@ -1065,8 +1068,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -1078,7 +1081,7 @@ impl Filesystem for SimpleFS { let inode = self.allocate_next_inode(); let attrs = InodeAttributes { - inode, + inode: inode.0, open_file_handles: 0, size: target.as_os_str().as_bytes().len() as u64, last_accessed: time_now(), @@ -1087,12 +1090,12 @@ impl Filesystem for SimpleFS { kind: FileKind::Symlink, mode: 0o777, hardlinks: 1, - uid: req.uid(), - gid: creation_gid(&parent_attrs, req.gid()), + uid: _req.uid(), + gid: creation_gid(&parent_attrs, _req.gid()), xattrs: BTreeMap::default(), }; - if let Err(error_code) = self.insert_link(req, parent, link_name, inode, FileKind::Symlink) + if let Err(error_code) = self.insert_link(_req, parent, link_name, inode, FileKind::Symlink) { reply.error(error_code); return; @@ -1113,17 +1116,17 @@ impl Filesystem for SimpleFS { fn rename( &mut self, - req: &Request, - parent: u64, + _req: &Request<'_>, + parent: INodeNo, name: &OsStr, - new_parent: u64, - new_name: &OsStr, + newparent: INodeNo, + newname: &OsStr, flags: u32, reply: ReplyEmpty, ) { debug!( "rename() called with: source {parent:?} {name:?}, \ - destination {new_parent:?} {new_name:?}, flags {flags:#b}", + destination {newparent:?} {newname:?}, flags {flags:#b}", ); let mut inode_attrs = match self.lookup_name(parent, name) { Ok(attrs) => attrs, @@ -1145,8 +1148,8 @@ impl Filesystem for SimpleFS { parent_attrs.uid, parent_attrs.gid, parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -1155,15 +1158,15 @@ impl Filesystem for SimpleFS { // "Sticky bit" handling if parent_attrs.mode & libc::S_ISVTX as u16 != 0 - && req.uid() != 0 - && req.uid() != parent_attrs.uid - && req.uid() != inode_attrs.uid + && _req.uid() != 0 + && _req.uid() != parent_attrs.uid + && _req.uid() != inode_attrs.uid { reply.error(libc::EACCES); return; } - let mut new_parent_attrs = match self.get_inode(new_parent) { + let mut new_parent_attrs = match self.get_inode(newparent) { Ok(attrs) => attrs, Err(error_code) => { reply.error(error_code); @@ -1175,8 +1178,8 @@ impl Filesystem for SimpleFS { new_parent_attrs.uid, new_parent_attrs.gid, new_parent_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { reply.error(libc::EACCES); @@ -1185,10 +1188,10 @@ impl Filesystem for SimpleFS { // "Sticky bit" handling in new_parent if new_parent_attrs.mode & libc::S_ISVTX as u16 != 0 { - if let Ok(existing_attrs) = self.lookup_name(new_parent, new_name) { - if req.uid() != 0 - && req.uid() != new_parent_attrs.uid - && req.uid() != existing_attrs.uid + if let Ok(existing_attrs) = self.lookup_name(newparent, newname) { + if _req.uid() != 0 + && _req.uid() != new_parent_attrs.uid + && _req.uid() != existing_attrs.uid { reply.error(libc::EACCES); return; @@ -1198,7 +1201,7 @@ impl Filesystem for SimpleFS { #[cfg(target_os = "linux")] if flags & libc::RENAME_EXCHANGE as u32 != 0 { - let mut new_inode_attrs = match self.lookup_name(new_parent, new_name) { + let mut new_inode_attrs = match self.lookup_name(newparent, newname) { Ok(attrs) => attrs, Err(error_code) => { reply.error(error_code); @@ -1206,12 +1209,12 @@ impl Filesystem for SimpleFS { } }; - let mut entries = self.get_directory_content(new_parent).unwrap(); + let mut entries = self.get_directory_content(newparent).unwrap(); entries.insert( - new_name.as_bytes().to_vec(), + newname.as_bytes().to_vec(), (inode_attrs.inode, inode_attrs.kind), ); - self.write_directory_content(new_parent, &entries); + self.write_directory_content(newparent, &entries); let mut entries = self.get_directory_content(parent).unwrap(); entries.insert( @@ -1232,14 +1235,18 @@ impl Filesystem for SimpleFS { self.write_inode(&new_inode_attrs); if inode_attrs.kind == FileKind::Directory { - let mut entries = self.get_directory_content(inode_attrs.inode).unwrap(); - entries.insert(b"..".to_vec(), (new_parent, FileKind::Directory)); - self.write_directory_content(inode_attrs.inode, &entries); + let mut entries = self + .get_directory_content(INodeNo(inode_attrs.inode)) + .unwrap(); + entries.insert(b"..".to_vec(), (newparent.0, FileKind::Directory)); + self.write_directory_content(INodeNo(inode_attrs.inode), &entries); } if new_inode_attrs.kind == FileKind::Directory { - let mut entries = self.get_directory_content(new_inode_attrs.inode).unwrap(); - entries.insert(b"..".to_vec(), (parent, FileKind::Directory)); - self.write_directory_content(new_inode_attrs.inode, &entries); + let mut entries = self + .get_directory_content(INodeNo(new_inode_attrs.inode)) + .unwrap(); + entries.insert(b"..".to_vec(), (parent.0, FileKind::Directory)); + self.write_directory_content(INodeNo(new_inode_attrs.inode), &entries); } reply.ok(); @@ -1247,10 +1254,10 @@ impl Filesystem for SimpleFS { } // Only overwrite an existing directory if it's empty - if let Ok(new_name_attrs) = self.lookup_name(new_parent, new_name) { + if let Ok(new_name_attrs) = self.lookup_name(newparent, newname) { if new_name_attrs.kind == FileKind::Directory && self - .get_directory_content(new_name_attrs.inode) + .get_directory_content(INodeNo(new_name_attrs.inode)) .unwrap() .len() > 2 @@ -1263,13 +1270,13 @@ impl Filesystem for SimpleFS { // Only move an existing directory to a new parent, if we have write access to it, // because that will change the ".." link in it if inode_attrs.kind == FileKind::Directory - && parent != new_parent + && parent != newparent && !check_access( inode_attrs.uid, inode_attrs.gid, inode_attrs.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), libc::W_OK, ) { @@ -1278,10 +1285,10 @@ impl Filesystem for SimpleFS { } // If target already exists decrement its hardlink count - if let Ok(mut existing_inode_attrs) = self.lookup_name(new_parent, new_name) { - let mut entries = self.get_directory_content(new_parent).unwrap(); - entries.remove(new_name.as_bytes()); - self.write_directory_content(new_parent, &entries); + if let Ok(mut existing_inode_attrs) = self.lookup_name(newparent, newname) { + let mut entries = self.get_directory_content(newparent).unwrap(); + entries.remove(newname.as_bytes()); + self.write_directory_content(newparent, &entries); if existing_inode_attrs.kind == FileKind::Directory { existing_inode_attrs.hardlinks = 0; @@ -1297,12 +1304,12 @@ impl Filesystem for SimpleFS { entries.remove(name.as_bytes()); self.write_directory_content(parent, &entries); - let mut entries = self.get_directory_content(new_parent).unwrap(); + let mut entries = self.get_directory_content(newparent).unwrap(); entries.insert( - new_name.as_bytes().to_vec(), + newname.as_bytes().to_vec(), (inode_attrs.inode, inode_attrs.kind), ); - self.write_directory_content(new_parent, &entries); + self.write_directory_content(newparent, &entries); parent_attrs.last_metadata_changed = time_now(); parent_attrs.last_modified = time_now(); @@ -1314,9 +1321,11 @@ impl Filesystem for SimpleFS { self.write_inode(&inode_attrs); if inode_attrs.kind == FileKind::Directory { - let mut entries = self.get_directory_content(inode_attrs.inode).unwrap(); - entries.insert(b"..".to_vec(), (new_parent, FileKind::Directory)); - self.write_directory_content(inode_attrs.inode, &entries); + let mut entries = self + .get_directory_content(INodeNo(inode_attrs.inode)) + .unwrap(); + entries.insert(b"..".to_vec(), (newparent.0, FileKind::Directory)); + self.write_directory_content(INodeNo(inode_attrs.inode), &entries); } reply.ok(); @@ -1324,21 +1333,21 @@ impl Filesystem for SimpleFS { fn link( &mut self, - req: &Request, - inode: u64, - new_parent: u64, - new_name: &OsStr, + _req: &Request<'_>, + ino: INodeNo, + newparent: INodeNo, + newname: &OsStr, reply: ReplyEntry, ) { - debug!("link() called for {inode}, {new_parent}, {new_name:?}"); - let mut attrs = match self.get_inode(inode) { + debug!("link() called for {ino}, {newparent}, {newname:?}"); + let mut attrs = match self.get_inode(ino) { Ok(attrs) => attrs, Err(error_code) => { reply.error(error_code); return; } }; - if let Err(error_code) = self.insert_link(req, new_parent, new_name, inode, attrs.kind) { + if let Err(error_code) = self.insert_link(_req, newparent, newname, ino, attrs.kind) { reply.error(error_code); } else { attrs.hardlinks += 1; @@ -1348,8 +1357,8 @@ impl Filesystem for SimpleFS { } } - fn open(&mut self, req: &Request, inode: u64, flags: OpenFlags, reply: ReplyOpen) { - debug!("open() called for {inode:?}"); + fn open(&mut self, _req: &Request<'_>, _ino: INodeNo, flags: OpenFlags, reply: ReplyOpen) { + debug!("open() called for {_ino:?}"); let (access_mask, read, write) = match flags.acc_mode() { OpenAccMode::O_RDONLY => { // Behavior is undefined, but most filesystems return EACCES @@ -1368,14 +1377,14 @@ impl Filesystem for SimpleFS { OpenAccMode::O_RDWR => (libc::R_OK | libc::W_OK, true, true), }; - match self.get_inode(inode) { + match self.get_inode(_ino) { Ok(mut attr) => { if check_access( attr.uid, attr.gid, attr.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), access_mask, ) { attr.open_file_handles += 1; @@ -1393,8 +1402,8 @@ impl Filesystem for SimpleFS { fn read( &mut self, - _req: &Request, - inode: u64, + _req: &Request<'_>, + ino: INodeNo, fh: u64, offset: i64, size: u32, @@ -1402,14 +1411,14 @@ impl Filesystem for SimpleFS { _lock_owner: Option, reply: ReplyData, ) { - debug!("read() called on {inode:?} offset={offset:?} size={size:?}"); + debug!("read() called on {ino:?} offset={offset:?} size={size:?}"); assert!(offset >= 0); if !Self::check_file_handle_read(fh) { reply.error(libc::EACCES); return; } - let path = self.content_path(inode); + let path = self.content_path(ino); match File::open(path) { Ok(file) => { let file_size = file.metadata().unwrap().len(); @@ -1428,30 +1437,30 @@ impl Filesystem for SimpleFS { fn write( &mut self, - _req: &Request, - inode: u64, + _req: &Request<'_>, + ino: INodeNo, fh: u64, offset: i64, data: &[u8], _write_flags: u32, - #[allow(unused_variables)] flags: i32, + _flags: i32, _lock_owner: Option, reply: ReplyWrite, ) { - debug!("write() called with {:?} size={:?}", inode, data.len()); + debug!("write() called with {:?} size={:?}", ino, data.len()); assert!(offset >= 0); if !Self::check_file_handle_write(fh) { reply.error(libc::EACCES); return; } - let path = self.content_path(inode); + let path = self.content_path(ino); match OpenOptions::new().write(true).open(path) { Ok(mut file) => { file.seek(SeekFrom::Start(offset as u64)).unwrap(); file.write_all(data).unwrap(); - let mut attrs = self.get_inode(inode).unwrap(); + let mut attrs = self.get_inode(ino).unwrap(); attrs.last_metadata_changed = time_now(); attrs.last_modified = time_now(); if data.len() + offset as usize > attrs.size as usize { @@ -1477,25 +1486,25 @@ impl Filesystem for SimpleFS { fn release( &mut self, _req: &Request<'_>, - inode: u64, + _ino: INodeNo, _fh: u64, _flags: i32, _lock_owner: Option, _flush: bool, reply: ReplyEmpty, ) { - if let Ok(mut attrs) = self.get_inode(inode) { + if let Ok(mut attrs) = self.get_inode(_ino) { attrs.open_file_handles -= 1; } reply.ok(); } - fn opendir(&mut self, req: &Request, inode: u64, flags: i32, reply: ReplyOpen) { - debug!("opendir() called on {inode:?}"); - let (access_mask, read, write) = match flags & libc::O_ACCMODE { + fn opendir(&mut self, _req: &Request<'_>, _ino: INodeNo, _flags: i32, reply: ReplyOpen) { + debug!("opendir() called on {_ino:?}"); + let (access_mask, read, write) = match _flags & libc::O_ACCMODE { libc::O_RDONLY => { // Behavior is undefined, but most filesystems return EACCES - if flags & libc::O_TRUNC != 0 { + if _flags & libc::O_TRUNC != 0 { reply.error(libc::EACCES); return; } @@ -1510,14 +1519,14 @@ impl Filesystem for SimpleFS { } }; - match self.get_inode(inode) { + match self.get_inode(_ino) { Ok(mut attr) => { if check_access( attr.uid, attr.gid, attr.mode, - req.uid(), - req.gid(), + _req.uid(), + _req.gid(), access_mask, ) { attr.open_file_handles += 1; @@ -1535,15 +1544,15 @@ impl Filesystem for SimpleFS { fn readdir( &mut self, - _req: &Request, - inode: u64, + _req: &Request<'_>, + ino: INodeNo, _fh: u64, offset: i64, mut reply: ReplyDirectory, ) { - debug!("readdir() called with {inode:?}"); + debug!("readdir() called with {ino:?}"); assert!(offset >= 0); - let entries = match self.get_directory_content(inode) { + let entries = match self.get_directory_content(ino) { Ok(entries) => entries, Err(error_code) => { reply.error(error_code); @@ -1555,7 +1564,7 @@ impl Filesystem for SimpleFS { let (name, (inode, file_type)) = entry; let buffer_full: bool = reply.add( - *inode, + INodeNo(*inode), offset + index as i64 + 1, (*file_type).into(), OsStr::from_bytes(name), @@ -1572,18 +1581,18 @@ impl Filesystem for SimpleFS { fn releasedir( &mut self, _req: &Request<'_>, - inode: u64, + _ino: INodeNo, _fh: u64, _flags: i32, reply: ReplyEmpty, ) { - if let Ok(mut attrs) = self.get_inode(inode) { + if let Ok(mut attrs) = self.get_inode(_ino) { attrs.open_file_handles -= 1; } reply.ok(); } - fn statfs(&mut self, _req: &Request, _ino: u64, reply: ReplyStatfs) { + fn statfs(&mut self, _req: &Request<'_>, _ino: INodeNo, reply: ReplyStatfs) { warn!("statfs() implementation is a stub"); // TODO: real implementation of this reply.statfs( @@ -1600,21 +1609,23 @@ impl Filesystem for SimpleFS { fn setxattr( &mut self, - request: &Request<'_>, - inode: u64, - key: &OsStr, - value: &[u8], + _req: &Request<'_>, + ino: INodeNo, + name: &OsStr, + _value: &[u8], _flags: i32, _position: u32, reply: ReplyEmpty, ) { - if let Ok(mut attrs) = self.get_inode(inode) { - if let Err(error) = xattr_access_check(key.as_bytes(), libc::W_OK, &attrs, request) { + if let Ok(mut attrs) = self.get_inode(ino) { + if let Err(error) = xattr_access_check(name.as_bytes(), libc::W_OK, &attrs, _req) { reply.error(error); return; } - attrs.xattrs.insert(key.as_bytes().to_vec(), value.to_vec()); + attrs + .xattrs + .insert(name.as_bytes().to_vec(), _value.to_vec()); attrs.last_metadata_changed = time_now(); self.write_inode(&attrs); reply.ok(); @@ -1626,7 +1637,7 @@ impl Filesystem for SimpleFS { fn getxattr( &mut self, request: &Request<'_>, - inode: u64, + inode: INodeNo, key: &OsStr, size: u32, reply: ReplyXattr, @@ -1656,8 +1667,8 @@ impl Filesystem for SimpleFS { } } - fn listxattr(&mut self, _req: &Request<'_>, inode: u64, size: u32, reply: ReplyXattr) { - if let Ok(attrs) = self.get_inode(inode) { + fn listxattr(&mut self, _req: &Request<'_>, ino: INodeNo, size: u32, reply: ReplyXattr) { + if let Ok(attrs) = self.get_inode(ino) { let mut bytes = vec![]; // Convert to concatenated null-terminated strings for key in attrs.xattrs.keys() { @@ -1676,7 +1687,13 @@ impl Filesystem for SimpleFS { } } - fn removexattr(&mut self, request: &Request<'_>, inode: u64, key: &OsStr, reply: ReplyEmpty) { + fn removexattr( + &mut self, + request: &Request<'_>, + inode: INodeNo, + key: &OsStr, + reply: ReplyEmpty, + ) { if let Ok(mut attrs) = self.get_inode(inode) { if let Err(error) = xattr_access_check(key.as_bytes(), libc::W_OK, &attrs, request) { reply.error(error); @@ -1698,11 +1715,11 @@ impl Filesystem for SimpleFS { } } - fn access(&mut self, req: &Request, inode: u64, mask: i32, reply: ReplyEmpty) { - debug!("access() called with {inode:?} {mask:?}"); - match self.get_inode(inode) { + fn access(&mut self, _req: &Request<'_>, ino: INodeNo, mask: i32, reply: ReplyEmpty) { + debug!("access() called with {ino:?} {mask:?}"); + match self.get_inode(ino) { Ok(attr) => { - if check_access(attr.uid, attr.gid, attr.mode, req.uid(), req.gid(), mask) { + if check_access(attr.uid, attr.gid, attr.mode, _req.uid(), _req.gid(), mask) { reply.ok(); } else { reply.error(libc::EACCES); @@ -1715,7 +1732,7 @@ impl Filesystem for SimpleFS { fn create( &mut self, req: &Request, - parent: u64, + parent: INodeNo, name: &OsStr, mut mode: u32, _umask: u32, @@ -1781,7 +1798,7 @@ impl Filesystem for SimpleFS { let inode = self.allocate_next_inode(); let attrs = InodeAttributes { - inode, + inode: inode.0, open_file_handles: 1, size: 0, last_accessed: time_now(), @@ -1799,13 +1816,13 @@ impl Filesystem for SimpleFS { if as_file_kind(mode) == FileKind::Directory { let mut entries = BTreeMap::new(); - entries.insert(b".".to_vec(), (inode, FileKind::Directory)); - entries.insert(b"..".to_vec(), (parent, FileKind::Directory)); + entries.insert(b".".to_vec(), (inode.0, FileKind::Directory)); + entries.insert(b"..".to_vec(), (parent.0, FileKind::Directory)); self.write_directory_content(inode, &entries); } let mut entries = self.get_directory_content(parent).unwrap(); - entries.insert(name.as_bytes().to_vec(), (inode, attrs.kind)); + entries.insert(name.as_bytes().to_vec(), (inode.0, attrs.kind)); self.write_directory_content(parent, &entries); // TODO: implement flags @@ -1822,21 +1839,21 @@ impl Filesystem for SimpleFS { fn fallocate( &mut self, _req: &Request<'_>, - inode: u64, + ino: INodeNo, _fh: u64, offset: i64, length: i64, mode: i32, reply: ReplyEmpty, ) { - let path = self.content_path(inode); + let path = self.content_path(ino); match OpenOptions::new().write(true).open(path) { Ok(file) => { unsafe { libc::fallocate64(file.into_raw_fd(), mode, offset, length); } if mode & libc::FALLOC_FL_KEEP_SIZE == 0 { - let mut attrs = self.get_inode(inode).unwrap(); + let mut attrs = self.get_inode(ino).unwrap(); attrs.last_metadata_changed = time_now(); attrs.last_modified = time_now(); if (offset + length) as u64 > attrs.size { @@ -1855,10 +1872,10 @@ impl Filesystem for SimpleFS { fn copy_file_range( &mut self, _req: &Request<'_>, - src_inode: u64, + src_inode: INodeNo, src_fh: u64, src_offset: i64, - dest_inode: u64, + dest_inode: INodeNo, dest_fh: u64, dest_offset: i64, size: u64, diff --git a/src/experimental.rs b/src/experimental.rs index aa512a3a..a009d9de 100644 --- a/src/experimental.rs +++ b/src/experimental.rs @@ -1,8 +1,8 @@ #![allow(missing_docs, missing_debug_implementations)] use crate::{ - FileAttr, FileType, Filesystem, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, Request, - RequestId, + FileAttr, FileType, Filesystem, INodeNo, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, + Request, RequestId, }; use std::ffi::OsStr; use std::time::Duration; @@ -63,7 +63,13 @@ impl DirEntListBuilder<'_> { /// A transparent offset value can be provided for each entry. The kernel uses these /// value to request the next entries in further readdir calls #[must_use] - pub fn add>(&mut self, ino: u64, offset: i64, kind: FileType, name: T) -> bool { + pub fn add>( + &mut self, + ino: INodeNo, + offset: i64, + kind: FileType, + name: T, + ) -> bool { self.entries.add(ino, offset, kind, name) } } @@ -122,7 +128,7 @@ impl TokioAdapter { } impl Filesystem for TokioAdapter { - fn lookup(&mut self, req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) { + fn lookup(&mut self, req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { match self .runtime .block_on(self.inner.lookup(&req.into(), parent, name)) @@ -136,7 +142,7 @@ impl Filesystem for TokioAdapter { } } - fn getattr(&mut self, req: &Request<'_>, ino: u64, fh: Option, reply: ReplyAttr) { + fn getattr(&mut self, req: &Request<'_>, ino: INodeNo, fh: Option, reply: ReplyAttr) { match self .runtime .block_on(self.inner.getattr(&req.into(), ino, fh)) @@ -149,7 +155,7 @@ impl Filesystem for TokioAdapter { fn read( &mut self, req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, size: u32, @@ -176,7 +182,7 @@ impl Filesystem for TokioAdapter { fn readdir( &mut self, req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, mut reply: ReplyDirectory, @@ -200,21 +206,21 @@ pub trait AsyncFilesystem { async fn lookup( &self, context: &RequestContext, - parent: u64, + parent: INodeNo, name: &OsStr, ) -> Result; async fn getattr( &self, context: &RequestContext, - ino: u64, + ino: INodeNo, file_handle: Option, ) -> Result; async fn read( &self, context: &RequestContext, - ino: u64, + ino: INodeNo, file_handle: u64, offset: i64, size: u32, @@ -228,7 +234,7 @@ pub trait AsyncFilesystem { async fn readdir( &self, context: &RequestContext, - ino: u64, + ino: INodeNo, file_handle: u64, offset: i64, builder: DirEntListBuilder<'_>, diff --git a/src/lib.rs b/src/lib.rs index 472210c0..23f54b98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,9 +25,9 @@ use std::time::SystemTime; use std::{convert::AsRef, io::ErrorKind}; pub use crate::ll::RequestId; -pub use crate::ll::fuse_abi::FUSE_ROOT_ID; pub use crate::ll::fuse_abi::InitFlags; use crate::ll::fuse_abi::consts::*; +pub use crate::ll::request::INodeNo; pub use crate::ll::{TimeOrNow, fuse_abi::consts}; use crate::mnt::mount_options::check_option_conflicts; pub use crate::open_flags::OpenAccMode; @@ -123,7 +123,7 @@ pub enum FileType { #[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))] pub struct FileAttr { /// Inode number - pub ino: u64, + pub ino: INodeNo, /// Size in bytes pub size: u64, /// Allocated size in 512-byte blocks. May be smaller than the actual file size @@ -356,7 +356,7 @@ pub trait Filesystem { fn destroy(&mut self) {} /// Look up a directory entry by name and get its attributes. - fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) { + fn lookup(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEntry) { warn!("[Not Implemented] lookup(parent: {parent:#x?}, name {name:?})"); reply.error(ENOSYS); } @@ -368,18 +368,18 @@ pub trait Filesystem { /// each forget. The filesystem may ignore forget calls, if the inodes don't need to /// have a limited lifetime. On unmount it is not guaranteed, that all referenced /// inodes will receive a forget message. - fn forget(&mut self, _req: &Request<'_>, _ino: u64, _nlookup: u64) {} + fn forget(&mut self, _req: &Request<'_>, _ino: INodeNo, _nlookup: u64) {} /// Like forget, but take multiple forget requests at once for performance. The default /// implementation will fallback to forget. fn batch_forget(&mut self, req: &Request<'_>, nodes: &[fuse_forget_one]) { for node in nodes { - self.forget(req, node.nodeid, node.nlookup); + self.forget(req, INodeNo(node.nodeid), node.nlookup); } } /// Get file attributes. - fn getattr(&mut self, _req: &Request<'_>, ino: u64, fh: Option, reply: ReplyAttr) { + fn getattr(&mut self, _req: &Request<'_>, ino: INodeNo, fh: Option, reply: ReplyAttr) { warn!("[Not Implemented] getattr(ino: {ino:#x?}, fh: {fh:#x?})"); reply.error(ENOSYS); } @@ -388,7 +388,7 @@ pub trait Filesystem { fn setattr( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, mode: Option, uid: Option, gid: Option, @@ -411,7 +411,7 @@ pub trait Filesystem { } /// Read symbolic link. - fn readlink(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyData) { + fn readlink(&mut self, _req: &Request<'_>, ino: INodeNo, reply: ReplyData) { warn!("[Not Implemented] readlink(ino: {ino:#x?})"); reply.error(ENOSYS); } @@ -421,7 +421,7 @@ pub trait Filesystem { fn mknod( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, name: &OsStr, mode: u32, umask: u32, @@ -439,7 +439,7 @@ pub trait Filesystem { fn mkdir( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, name: &OsStr, mode: u32, umask: u32, @@ -452,13 +452,13 @@ pub trait Filesystem { } /// Remove a file. - fn unlink(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) { + fn unlink(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) { warn!("[Not Implemented] unlink(parent: {parent:#x?}, name: {name:?})",); reply.error(ENOSYS); } /// Remove a directory. - fn rmdir(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) { + fn rmdir(&mut self, _req: &Request<'_>, parent: INodeNo, name: &OsStr, reply: ReplyEmpty) { warn!("[Not Implemented] rmdir(parent: {parent:#x?}, name: {name:?})",); reply.error(ENOSYS); } @@ -467,7 +467,7 @@ pub trait Filesystem { fn symlink( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, link_name: &OsStr, target: &Path, reply: ReplyEntry, @@ -482,9 +482,9 @@ pub trait Filesystem { fn rename( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, name: &OsStr, - newparent: u64, + newparent: INodeNo, newname: &OsStr, flags: u32, reply: ReplyEmpty, @@ -500,8 +500,8 @@ pub trait Filesystem { fn link( &mut self, _req: &Request<'_>, - ino: u64, - newparent: u64, + ino: INodeNo, + newparent: INodeNo, newname: &OsStr, reply: ReplyEntry, ) { @@ -519,7 +519,7 @@ pub trait Filesystem { /// anything in fh. There are also some flags (`direct_io`, `keep_cache`) which the /// filesystem may set, to change the way the file is opened. See `fuse_file_info` /// structure in <`fuse_common.h`> for more details. - fn open(&mut self, _req: &Request<'_>, _ino: u64, _flags: OpenFlags, reply: ReplyOpen) { + fn open(&mut self, _req: &Request<'_>, _ino: INodeNo, _flags: OpenFlags, reply: ReplyOpen) { reply.opened(0, 0); } @@ -536,7 +536,7 @@ pub trait Filesystem { fn read( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, size: u32, @@ -566,7 +566,7 @@ pub trait Filesystem { fn write( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, data: &[u8], @@ -594,7 +594,14 @@ pub trait Filesystem { /// is not forced to flush pending writes. One reason to flush data, is if the /// filesystem wants to return write errors. If the filesystem supports file locking /// operations (`setlk`, `getlk`) it should remove all locks belonging to `lock_owner`. - fn flush(&mut self, _req: &Request<'_>, ino: u64, fh: u64, lock_owner: u64, reply: ReplyEmpty) { + fn flush( + &mut self, + _req: &Request<'_>, + ino: INodeNo, + fh: u64, + lock_owner: u64, + reply: ReplyEmpty, + ) { warn!("[Not Implemented] flush(ino: {ino:#x?}, fh: {fh}, lock_owner: {lock_owner:?})"); reply.error(ENOSYS); } @@ -610,7 +617,7 @@ pub trait Filesystem { fn release( &mut self, _req: &Request<'_>, - _ino: u64, + _ino: INodeNo, _fh: u64, _flags: i32, _lock_owner: Option, @@ -623,7 +630,14 @@ pub trait Filesystem { /// Synchronize file contents. /// If the datasync parameter is non-zero, then only the user data should be flushed, /// not the meta data. - fn fsync(&mut self, _req: &Request<'_>, ino: u64, fh: u64, datasync: bool, reply: ReplyEmpty) { + fn fsync( + &mut self, + _req: &Request<'_>, + ino: INodeNo, + fh: u64, + datasync: bool, + reply: ReplyEmpty, + ) { warn!("[Not Implemented] fsync(ino: {ino:#x?}, fh: {fh}, datasync: {datasync})"); reply.error(ENOSYS); } @@ -635,7 +649,7 @@ pub trait Filesystem { /// anything in fh, though that makes it impossible to implement standard conforming /// directory stream operations in case the contents of the directory can change /// between opendir and releasedir. - fn opendir(&mut self, _req: &Request<'_>, _ino: u64, _flags: i32, reply: ReplyOpen) { + fn opendir(&mut self, _req: &Request<'_>, _ino: INodeNo, _flags: i32, reply: ReplyOpen) { reply.opened(0, 0); } @@ -647,7 +661,7 @@ pub trait Filesystem { fn readdir( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, reply: ReplyDirectory, @@ -664,7 +678,7 @@ pub trait Filesystem { fn readdirplus( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, reply: ReplyDirectoryPlus, @@ -680,7 +694,7 @@ pub trait Filesystem { fn releasedir( &mut self, _req: &Request<'_>, - _ino: u64, + _ino: INodeNo, _fh: u64, _flags: i32, reply: ReplyEmpty, @@ -695,7 +709,7 @@ pub trait Filesystem { fn fsyncdir( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, datasync: bool, reply: ReplyEmpty, @@ -705,7 +719,7 @@ pub trait Filesystem { } /// Get file system statistics. - fn statfs(&mut self, _req: &Request<'_>, _ino: u64, reply: ReplyStatfs) { + fn statfs(&mut self, _req: &Request<'_>, _ino: INodeNo, reply: ReplyStatfs) { reply.statfs(0, 0, 0, 0, 0, 512, 255, 0); } @@ -713,7 +727,7 @@ pub trait Filesystem { fn setxattr( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, name: &OsStr, _value: &[u8], flags: i32, @@ -734,7 +748,7 @@ pub trait Filesystem { fn getxattr( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, name: &OsStr, size: u32, reply: ReplyXattr, @@ -747,13 +761,13 @@ pub trait Filesystem { /// If `size` is 0, the size of the value should be sent with `reply.size()`. /// If `size` is not 0, and the value fits, send it with `reply.data()`, or /// `reply.error(ERANGE)` if it doesn't. - fn listxattr(&mut self, _req: &Request<'_>, ino: u64, size: u32, reply: ReplyXattr) { + fn listxattr(&mut self, _req: &Request<'_>, ino: INodeNo, size: u32, reply: ReplyXattr) { warn!("[Not Implemented] listxattr(ino: {ino:#x?}, size: {size})"); reply.error(ENOSYS); } /// Remove an extended attribute. - fn removexattr(&mut self, _req: &Request<'_>, ino: u64, name: &OsStr, reply: ReplyEmpty) { + fn removexattr(&mut self, _req: &Request<'_>, ino: INodeNo, name: &OsStr, reply: ReplyEmpty) { warn!("[Not Implemented] removexattr(ino: {ino:#x?}, name: {name:?})"); reply.error(ENOSYS); } @@ -762,7 +776,7 @@ pub trait Filesystem { /// This will be called for the `access()` system call. If the `default_permissions` /// mount option is given, this method is not called. This method is not called /// under Linux kernel versions 2.4.x - fn access(&mut self, _req: &Request<'_>, ino: u64, mask: i32, reply: ReplyEmpty) { + fn access(&mut self, _req: &Request<'_>, ino: INodeNo, mask: i32, reply: ReplyEmpty) { warn!("[Not Implemented] access(ino: {ino:#x?}, mask: {mask})"); reply.error(ENOSYS); } @@ -780,7 +794,7 @@ pub trait Filesystem { fn create( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, name: &OsStr, mode: u32, umask: u32, @@ -798,7 +812,7 @@ pub trait Filesystem { fn getlk( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, lock_owner: u64, start: u64, @@ -824,7 +838,7 @@ pub trait Filesystem { fn setlk( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, lock_owner: u64, start: u64, @@ -844,7 +858,14 @@ pub trait Filesystem { /// Map block index within file to block index within device. /// Note: This makes sense only for block device backed filesystems mounted /// with the 'blkdev' option - fn bmap(&mut self, _req: &Request<'_>, ino: u64, blocksize: u32, idx: u64, reply: ReplyBmap) { + fn bmap( + &mut self, + _req: &Request<'_>, + ino: INodeNo, + blocksize: u32, + idx: u64, + reply: ReplyBmap, + ) { warn!("[Not Implemented] bmap(ino: {ino:#x?}, blocksize: {blocksize}, idx: {idx})",); reply.error(ENOSYS); } @@ -853,7 +874,7 @@ pub trait Filesystem { fn ioctl( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, flags: u32, cmd: u32, @@ -873,7 +894,7 @@ pub trait Filesystem { fn poll( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, ph: PollHandle, events: u32, @@ -891,7 +912,7 @@ pub trait Filesystem { fn fallocate( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, length: i64, @@ -909,7 +930,7 @@ pub trait Filesystem { fn lseek( &mut self, _req: &Request<'_>, - ino: u64, + ino: INodeNo, fh: u64, offset: i64, whence: i32, @@ -926,10 +947,10 @@ pub trait Filesystem { fn copy_file_range( &mut self, _req: &Request<'_>, - ino_in: u64, + ino_in: INodeNo, fh_in: u64, offset_in: i64, - ino_out: u64, + ino_out: INodeNo, fh_out: u64, offset_out: i64, len: u64, @@ -957,9 +978,9 @@ pub trait Filesystem { fn exchange( &mut self, _req: &Request<'_>, - parent: u64, + parent: INodeNo, name: &OsStr, - newparent: u64, + newparent: INodeNo, newname: &OsStr, options: u64, reply: ReplyEmpty, @@ -974,7 +995,7 @@ pub trait Filesystem { /// macOS only: Query extended times (`bkuptime` and `crtime`). Set `fuse_init_out.flags` /// during init to `FUSE_XTIMES` to enable #[cfg(target_os = "macos")] - fn getxtimes(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyXTimes) { + fn getxtimes(&mut self, _req: &Request<'_>, ino: INodeNo, reply: ReplyXTimes) { warn!("[Not Implemented] getxtimes(ino: {ino:#x?})"); reply.error(ENOSYS); } diff --git a/src/ll/fuse_abi.rs b/src/ll/fuse_abi.rs index 3ca7a578..54b524af 100644 --- a/src/ll/fuse_abi.rs +++ b/src/ll/fuse_abi.rs @@ -60,8 +60,6 @@ pub(crate) const FUSE_KERNEL_MINOR_VERSION: u32 = 36; #[cfg(feature = "abi-7-40")] pub(crate) const FUSE_KERNEL_MINOR_VERSION: u32 = 40; -pub const FUSE_ROOT_ID: u64 = 1; - #[repr(C)] #[derive(Debug, IntoBytes, Clone, Copy, KnownLayout, Immutable)] pub(crate) struct fuse_attr { diff --git a/src/ll/notify.rs b/src/ll/notify.rs index d33ed1af..38d2804e 100644 --- a/src/ll/notify.rs +++ b/src/ll/notify.rs @@ -3,11 +3,11 @@ use std::{convert::TryInto, io::IoSlice, num::TryFromIntError}; #[allow(unused)] use std::{ffi::OsStr, os::unix::ffi::OsStrExt}; +use super::fuse_abi as abi; +use crate::INodeNo; use smallvec::{SmallVec, smallvec}; use zerocopy::{Immutable, IntoBytes}; -use super::fuse_abi as abi; - const INLINE_DATA_THRESHOLD: usize = size_of::() * 4; type NotificationBuf = SmallVec<[u8; INLINE_DATA_THRESHOLD]>; @@ -58,9 +58,12 @@ impl<'a> Notification<'a> { Ok(f(&v)) } - pub(crate) fn new_inval_entry(parent: u64, name: &'a OsStr) -> Result { + pub(crate) fn new_inval_entry( + parent: INodeNo, + name: &'a OsStr, + ) -> Result { let r = abi::fuse_notify_inval_entry_out { - parent, + parent: parent.0, namelen: name.len().try_into()?, padding: 0, }; @@ -131,7 +134,7 @@ mod test { #[test] fn inval_entry() { - let n = Notification::new_inval_entry(0x42, OsStr::new("abc")) + let n = Notification::new_inval_entry(INodeNo(0x42), OsStr::new("abc")) .unwrap() .with_iovec( abi::fuse_notify_code::FUSE_NOTIFY_INVAL_ENTRY, @@ -179,7 +182,7 @@ mod test { #[test] fn delete() { - let n = Notification::new_inval_entry(0x42, OsStr::new("abc")) + let n = Notification::new_inval_entry(INodeNo(0x42), OsStr::new("abc")) .unwrap() .with_iovec(abi::fuse_notify_code::FUSE_NOTIFY_DELETE, ioslice_to_vec) .unwrap(); diff --git a/src/ll/reply.rs b/src/ll/reply.rs index c7ba7de2..084d793f 100644 --- a/src/ll/reply.rs +++ b/src/ll/reply.rs @@ -289,7 +289,7 @@ pub(crate) fn fuse_attr_from_attr(attr: &crate::FileAttr) -> abi::fuse_attr { let (crtime_secs, crtime_nanos) = time_from_system_time(&attr.crtime); abi::fuse_attr { - ino: attr.ino, + ino: attr.ino.0, size: attr.size, blocks: attr.blocks, atime: atime_secs, @@ -581,7 +581,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = crate::FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, @@ -638,7 +638,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = crate::FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, @@ -765,7 +765,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = crate::FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, diff --git a/src/ll/request.rs b/src/ll/request.rs index 157ffaf1..d1d64f05 100644 --- a/src/ll/request.rs +++ b/src/ll/request.rs @@ -5,15 +5,15 @@ use super::fuse_abi::{InvalidOpcodeError, fuse_in_header, fuse_opcode}; +use super::argument::ArgumentIterator; use super::fuse_abi as abi; use nix::unistd::{Gid, Pid, Uid}; #[cfg(feature = "serializable")] use serde::{Deserialize, Serialize}; +use std::fmt::Formatter; use std::{convert::TryFrom, fmt::Display, path::Path}; use std::{error, fmt}; -use super::argument::ArgumentIterator; - /// Error that may occur while reading and parsing a request from the kernel driver. #[derive(Debug)] pub(crate) enum RequestError { @@ -65,19 +65,27 @@ impl From for u64 { /// should decrement its own counter and if it reaches 0 then the inode number /// may be recycled and your filesystem implementation may clean up its /// internal data-structures relating to that inode. -/// -/// We implement conversion from [`INodeNo`] to [`u64`] but not vice-versa because -/// not all [`u64`]s are valid [`INodeNo`]s, but the reverse is true. So to produce -/// a [`INodeNo`] from a [`u64`] we must be explicit. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))] -pub(crate) struct INodeNo(pub(crate) u64); +pub struct INodeNo(pub u64); + +impl INodeNo { + /// Filesystem root inode number. + pub const ROOT: INodeNo = INodeNo(1); +} + impl From for u64 { fn from(fh: INodeNo) -> Self { fh.0 } } +impl Display for INodeNo { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + /// A newtype for file handles /// /// This corresponds to a single file description in a client program. These diff --git a/src/notify.rs b/src/notify.rs index e332cd36..0b952e42 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -4,12 +4,9 @@ use std::io; use std::{convert::TryInto, ffi::OsStr}; use crate::{ + INodeNo, channel::ChannelSender, ll::{fuse_abi::fuse_notify_code as notify_code, notify::Notification}, - - // What we're sending here aren't really replies, but they - // move in the same direction (userspace->kernel), so we can - // reuse ReplySender for it. reply::ReplySender, }; @@ -70,7 +67,7 @@ impl Notifier { /// # Errors /// Returns an error if the notification data is too large. /// Returns an error if the kernel rejects the notification. - pub fn inval_entry(&self, parent: u64, name: &OsStr) -> io::Result<()> { + pub fn inval_entry(&self, parent: INodeNo, name: &OsStr) -> io::Result<()> { let notif = Notification::new_inval_entry(parent, name).map_err(Self::too_big_err)?; self.send_inval(notify_code::FUSE_NOTIFY_INVAL_ENTRY, ¬if) } diff --git a/src/reply.rs b/src/reply.rs index fa9eb4e9..b82945ad 100644 --- a/src/reply.rs +++ b/src/reply.rs @@ -184,7 +184,7 @@ impl ReplyEntry { /// Reply to a request with the given entry pub fn entry(self, ttl: &Duration, attr: &FileAttr, generation: u64) { self.reply.send_ll(&ll::Response::new_entry( - ll::INodeNo(attr.ino), + attr.ino, ll::Generation(generation), &attr.into(), *ttl, @@ -565,14 +565,16 @@ impl ReplyDirectory { /// A transparent offset value can be provided for each entry. The kernel uses these /// value to request the next entries in further readdir calls #[must_use] - pub fn add>(&mut self, ino: u64, offset: i64, kind: FileType, name: T) -> bool { + pub fn add>( + &mut self, + ino: INodeNo, + offset: i64, + kind: FileType, + name: T, + ) -> bool { let name = name.as_ref(); - self.data.push(&DirEntry::new( - INodeNo(ino), - DirEntOffset(offset), - kind, - name, - )) + self.data + .push(&DirEntry::new(ino, DirEntOffset(offset), kind, name)) } /// Reply to a request with the filled directory buffer @@ -856,7 +858,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, @@ -911,7 +913,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, @@ -1032,7 +1034,7 @@ mod test { let time = UNIX_EPOCH + Duration::new(0x1234, 0x5678); let ttl = Duration::new(0x8765, 0x4321); let attr = FileAttr { - ino: 0x11, + ino: INodeNo(0x11), size: 0x22, blocks: 0x33, atime: time, @@ -1089,8 +1091,8 @@ mod test { ], }; let mut reply = ReplyDirectory::new(ll::RequestId(0xdeadbeef), sender, 4096); - assert!(!reply.add(0xaabb, 1, FileType::Directory, "hello")); - assert!(!reply.add(0xccdd, 2, FileType::RegularFile, "world.rs")); + assert!(!reply.add(INodeNo(0xaabb), 1, FileType::Directory, "hello")); + assert!(!reply.add(INodeNo(0xccdd), 2, FileType::RegularFile, "world.rs")); reply.ok(); } diff --git a/src/request.rs b/src/request.rs index 6a2bd23f..ecefb3b8 100644 --- a/src/request.rs +++ b/src/request.rs @@ -147,21 +147,17 @@ impl<'a> Request<'a> { } ll::Operation::Lookup(x) => { - se.filesystem.lookup( - self, - self.request.nodeid().into(), - x.name().as_ref(), - self.reply(), - ); + se.filesystem + .lookup(self, self.request.nodeid(), x.name().as_ref(), self.reply()); } ll::Operation::Forget(x) => { se.filesystem - .forget(self, self.request.nodeid().into(), x.nlookup()); // no reply + .forget(self, self.request.nodeid(), x.nlookup()); // no reply } ll::Operation::GetAttr(_attr) => { se.filesystem.getattr( self, - self.request.nodeid().into(), + self.request.nodeid(), _attr.file_handle().map(std::convert::Into::into), self.reply(), ); @@ -169,7 +165,7 @@ impl<'a> Request<'a> { ll::Operation::SetAttr(x) => { se.filesystem.setattr( self, - self.request.nodeid().into(), + self.request.nodeid(), x.mode(), x.uid(), x.gid(), @@ -187,12 +183,12 @@ impl<'a> Request<'a> { } ll::Operation::ReadLink(_) => { se.filesystem - .readlink(self, self.request.nodeid().into(), self.reply()); + .readlink(self, self.request.nodeid(), self.reply()); } ll::Operation::MkNod(x) => { se.filesystem.mknod( self, - self.request.nodeid().into(), + self.request.nodeid(), x.name().as_ref(), x.mode(), x.umask(), @@ -203,7 +199,7 @@ impl<'a> Request<'a> { ll::Operation::MkDir(x) => { se.filesystem.mkdir( self, - self.request.nodeid().into(), + self.request.nodeid(), x.name().as_ref(), x.mode(), x.umask(), @@ -211,25 +207,17 @@ impl<'a> Request<'a> { ); } ll::Operation::Unlink(x) => { - se.filesystem.unlink( - self, - self.request.nodeid().into(), - x.name().as_ref(), - self.reply(), - ); + se.filesystem + .unlink(self, self.request.nodeid(), x.name().as_ref(), self.reply()); } ll::Operation::RmDir(x) => { - se.filesystem.rmdir( - self, - self.request.nodeid().into(), - x.name().as_ref(), - self.reply(), - ); + se.filesystem + .rmdir(self, self.request.nodeid(), x.name().as_ref(), self.reply()); } ll::Operation::SymLink(x) => { se.filesystem.symlink( self, - self.request.nodeid().into(), + self.request.nodeid(), x.link_name().as_ref(), Path::new(x.target()), self.reply(), @@ -238,9 +226,9 @@ impl<'a> Request<'a> { ll::Operation::Rename(x) => { se.filesystem.rename( self, - self.request.nodeid().into(), + self.request.nodeid(), x.src().name.as_ref(), - x.dest().dir.into(), + x.dest().dir, x.dest().name.as_ref(), 0, self.reply(), @@ -249,20 +237,20 @@ impl<'a> Request<'a> { ll::Operation::Link(x) => { se.filesystem.link( self, - x.inode_no().into(), - self.request.nodeid().into(), + x.inode_no(), + self.request.nodeid(), x.dest().name.as_ref(), self.reply(), ); } ll::Operation::Open(x) => { se.filesystem - .open(self, self.request.nodeid().into(), x.flags(), self.reply()); + .open(self, self.request.nodeid(), x.flags(), self.reply()); } ll::Operation::Read(x) => { se.filesystem.read( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), x.size(), @@ -274,7 +262,7 @@ impl<'a> Request<'a> { ll::Operation::Write(x) => { se.filesystem.write( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), x.data(), @@ -287,7 +275,7 @@ impl<'a> Request<'a> { ll::Operation::Flush(x) => { se.filesystem.flush( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.lock_owner().into(), self.reply(), @@ -296,7 +284,7 @@ impl<'a> Request<'a> { ll::Operation::Release(x) => { se.filesystem.release( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.flags(), x.lock_owner().map(std::convert::Into::into), @@ -307,7 +295,7 @@ impl<'a> Request<'a> { ll::Operation::FSync(x) => { se.filesystem.fsync( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.fdatasync(), self.reply(), @@ -315,12 +303,12 @@ impl<'a> Request<'a> { } ll::Operation::OpenDir(x) => { se.filesystem - .opendir(self, self.request.nodeid().into(), x.flags(), self.reply()); + .opendir(self, self.request.nodeid(), x.flags(), self.reply()); } ll::Operation::ReadDir(x) => { se.filesystem.readdir( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), ReplyDirectory::new(self.request.unique(), self.ch.clone(), x.size() as usize), @@ -329,7 +317,7 @@ impl<'a> Request<'a> { ll::Operation::ReleaseDir(x) => { se.filesystem.releasedir( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.flags(), self.reply(), @@ -338,7 +326,7 @@ impl<'a> Request<'a> { ll::Operation::FSyncDir(x) => { se.filesystem.fsyncdir( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.fdatasync(), self.reply(), @@ -346,12 +334,12 @@ impl<'a> Request<'a> { } ll::Operation::StatFs(_) => { se.filesystem - .statfs(self, self.request.nodeid().into(), self.reply()); + .statfs(self, self.request.nodeid(), self.reply()); } ll::Operation::SetXAttr(x) => { se.filesystem.setxattr( self, - self.request.nodeid().into(), + self.request.nodeid(), x.name(), x.value(), x.flags(), @@ -362,7 +350,7 @@ impl<'a> Request<'a> { ll::Operation::GetXAttr(x) => { se.filesystem.getxattr( self, - self.request.nodeid().into(), + self.request.nodeid(), x.name(), x.size_u32(), self.reply(), @@ -370,24 +358,20 @@ impl<'a> Request<'a> { } ll::Operation::ListXAttr(x) => { se.filesystem - .listxattr(self, self.request.nodeid().into(), x.size(), self.reply()); + .listxattr(self, self.request.nodeid(), x.size(), self.reply()); } ll::Operation::RemoveXAttr(x) => { - se.filesystem.removexattr( - self, - self.request.nodeid().into(), - x.name(), - self.reply(), - ); + se.filesystem + .removexattr(self, self.request.nodeid(), x.name(), self.reply()); } ll::Operation::Access(x) => { se.filesystem - .access(self, self.request.nodeid().into(), x.mask(), self.reply()); + .access(self, self.request.nodeid(), x.mask(), self.reply()); } ll::Operation::Create(x) => { se.filesystem.create( self, - self.request.nodeid().into(), + self.request.nodeid(), x.name().as_ref(), x.mode(), x.umask(), @@ -398,7 +382,7 @@ impl<'a> Request<'a> { ll::Operation::GetLk(x) => { se.filesystem.getlk( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.lock_owner().into(), x.lock().range.0, @@ -411,7 +395,7 @@ impl<'a> Request<'a> { ll::Operation::SetLk(x) => { se.filesystem.setlk( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.lock_owner().into(), x.lock().range.0, @@ -425,7 +409,7 @@ impl<'a> Request<'a> { ll::Operation::SetLkW(x) => { se.filesystem.setlk( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.lock_owner().into(), x.lock().range.0, @@ -439,7 +423,7 @@ impl<'a> Request<'a> { ll::Operation::BMap(x) => { se.filesystem.bmap( self, - self.request.nodeid().into(), + self.request.nodeid(), x.block_size(), x.block(), self.reply(), @@ -452,7 +436,7 @@ impl<'a> Request<'a> { } se.filesystem.ioctl( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.flags(), x.command(), @@ -466,7 +450,7 @@ impl<'a> Request<'a> { se.filesystem.poll( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), ph, x.events(), @@ -484,7 +468,7 @@ impl<'a> Request<'a> { ll::Operation::FAllocate(x) => { se.filesystem.fallocate( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), x.len(), @@ -496,7 +480,7 @@ impl<'a> Request<'a> { ll::Operation::ReadDirPlus(x) => { se.filesystem.readdirplus( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), ReplyDirectoryPlus::new( @@ -510,9 +494,9 @@ impl<'a> Request<'a> { ll::Operation::Rename2(x) => { se.filesystem.rename( self, - x.from().dir.into(), + x.from().dir, x.from().name.as_ref(), - x.to().dir.into(), + x.to().dir, x.to().name.as_ref(), x.flags(), self.reply(), @@ -522,7 +506,7 @@ impl<'a> Request<'a> { ll::Operation::Lseek(x) => { se.filesystem.lseek( self, - self.request.nodeid().into(), + self.request.nodeid(), x.file_handle().into(), x.offset(), x.whence(), @@ -534,10 +518,10 @@ impl<'a> Request<'a> { let (i, o) = (x.src(), x.dest()); se.filesystem.copy_file_range( self, - i.inode.into(), + i.inode, i.file_handle.into(), i.offset, - o.inode.into(), + o.inode, o.file_handle.into(), o.offset, x.len(), @@ -551,16 +535,15 @@ impl<'a> Request<'a> { } #[cfg(target_os = "macos")] ll::Operation::GetXTimes(x) => { - se.filesystem - .getxtimes(self, x.nodeid().into(), self.reply()); + se.filesystem.getxtimes(self, x.nodeid(), self.reply()); } #[cfg(target_os = "macos")] ll::Operation::Exchange(x) => { se.filesystem.exchange( self, - x.from().dir.into(), + x.from().dir, x.from().name.as_ref(), - x.to().dir.into(), + x.to().dir, x.to().name.as_ref(), x.options(), self.reply(),