diff --git a/examples/ioctl.rs b/examples/ioctl.rs index 3ca9562e..94f4cc51 100644 --- a/examples/ioctl.rs +++ b/examples/ioctl.rs @@ -14,6 +14,9 @@ use std::time::{Duration, UNIX_EPOCH}; const TTL: Duration = Duration::from_secs(1); // 1 second +const FIOC_GET_SIZE: u64 = nix::request_code_read!('E', 0, std::mem::size_of::()); +const FIOC_SET_SIZE: u64 = nix::request_code_write!('E', 1, std::mem::size_of::()); + struct FiocFS { content: Vec, root_attr: FileAttr, @@ -98,7 +101,7 @@ impl Filesystem for FiocFS { reply: ReplyData, ) { if ino == 2 { - reply.data(&self.content[offset as usize..]) + reply.data(&self.content[offset as usize..]); } else { reply.error(ENOENT); } @@ -148,9 +151,6 @@ impl Filesystem for FiocFS { return; } - const FIOC_GET_SIZE: u64 = nix::request_code_read!('E', 0, std::mem::size_of::()); - const FIOC_SET_SIZE: u64 = nix::request_code_write!('E', 1, std::mem::size_of::()); - match cmd.into() { FIOC_GET_SIZE => { let size_bytes = self.content.len().to_ne_bytes(); diff --git a/examples/notify_inval_inode.rs b/examples/notify_inval_inode.rs index 369562f3..d7ab155c 100644 --- a/examples/notify_inval_inode.rs +++ b/examples/notify_inval_inode.rs @@ -156,7 +156,7 @@ impl Filesystem for ClockFS<'_> { reply.error(EINVAL); return; }; - let Ok(end) = (offset + size as i64).min(dlen).try_into() else { + let Ok(end) = (offset + i64::from(size)).min(dlen).try_into() else { reply.error(EINVAL); return; }; diff --git a/examples/passthrough.rs b/examples/passthrough.rs index beeb1056..299c0060 100644 --- a/examples/passthrough.rs +++ b/examples/passthrough.rs @@ -131,7 +131,7 @@ impl PassthroughFs { Self { root_attr, passthrough_file_attr, - backing_cache: Default::default(), + backing_cache: BackingCache::default(), } } } diff --git a/examples/simple.rs b/examples/simple.rs index 7a419752..88940c29 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -277,10 +277,10 @@ impl SimpleFS { } fn creation_mode(&self, mode: u32) -> u16 { - if !self.suid_support { - (mode & !(libc::S_ISUID | libc::S_ISGID) as u32) as u16 - } else { + if self.suid_support { mode as u16 + } else { + (mode & !(libc::S_ISUID | libc::S_ISGID) as u32) as u16 } } @@ -432,9 +432,8 @@ impl SimpleFS { let entries = self.get_directory_content(parent)?; if let Some((inode, _)) = entries.get(name.as_bytes()) { return self.get_inode(*inode); - } else { - return Err(libc::ENOENT); } + return Err(libc::ENOENT); } fn insert_link( @@ -498,7 +497,7 @@ impl Filesystem for SimpleFS { hardlinks: 2, uid: 0, gid: 0, - xattrs: Default::default(), + xattrs: BTreeMap::default(), }; self.write_inode(&root); let mut entries = BTreeMap::new(); @@ -832,7 +831,7 @@ impl Filesystem for SimpleFS { hardlinks: 1, uid: req.uid(), gid: creation_gid(&parent_attrs, req.gid()), - xattrs: Default::default(), + xattrs: BTreeMap::default(), }; self.write_inode(&attrs); File::create(self.content_path(inode)).unwrap(); @@ -910,7 +909,7 @@ impl Filesystem for SimpleFS { 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()), - xattrs: Default::default(), + xattrs: BTreeMap::default(), }; self.write_inode(&attrs); @@ -1089,7 +1088,7 @@ impl Filesystem for SimpleFS { hardlinks: 1, uid: req.uid(), gid: creation_gid(&parent_attrs, req.gid()), - xattrs: Default::default(), + xattrs: BTreeMap::default(), }; if let Err(error_code) = self.insert_link(req, parent, link_name, inode, FileKind::Symlink) @@ -1797,7 +1796,7 @@ impl Filesystem for SimpleFS { hardlinks: 1, uid: req.uid(), gid: creation_gid(&parent_attrs, req.gid()), - xattrs: Default::default(), + xattrs: BTreeMap::default(), }; self.write_inode(&attrs); File::create(self.content_path(inode)).unwrap(); @@ -1964,9 +1963,8 @@ fn as_file_kind(mut mode: u32) -> FileKind { return FileKind::Symlink; } else if mode == libc::S_IFDIR as u32 { return FileKind::Directory; - } else { - unimplemented!("{mode}"); } + unimplemented!("{mode}"); } fn get_groups(pid: u32) -> Vec { diff --git a/src/lib.rs b/src/lib.rs index 0dd89842..07162524 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -293,7 +293,7 @@ impl KernelConfig { fn congestion_threshold(&self) -> u16 { match self.congestion_threshold { // Default to a threshold of 3/4 of the max background threads - None => (self.max_background as u32 * 3 / 4) as u16, + None => (u32::from(self.max_background) * 3 / 4) as u16, Some(value) => min(value, self.max_background), } } @@ -991,7 +991,8 @@ pub fn spawn_mount<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef>( .map(|x| Some(MountOption::from_str(x.to_str()?))) .collect(); let options = options.ok_or(ErrorKind::InvalidData)?; - Session::new(filesystem, mountpoint.as_ref(), options.as_ref()).and_then(|se| se.spawn()) + Session::new(filesystem, mountpoint.as_ref(), options.as_ref()) + .and_then(session::Session::spawn) } /// Mount the given filesystem to the given mountpoint. This function spawns @@ -1007,5 +1008,5 @@ pub fn spawn_mount2<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef>( options: &[MountOption], ) -> io::Result { check_option_conflicts(options)?; - Session::new(filesystem, mountpoint.as_ref(), options).and_then(|se| se.spawn()) + Session::new(filesystem, mountpoint.as_ref(), options).and_then(session::Session::spawn) } diff --git a/src/ll/argument.rs b/src/ll/argument.rs index 05d70e1c..510a931e 100644 --- a/src/ll/argument.rs +++ b/src/ll/argument.rs @@ -86,7 +86,6 @@ impl<'a> ArgumentIterator<'a> { #[cfg(test)] pub mod tests { - use std::ops::Deref; use super::super::test::AlignedData; use super::*; @@ -105,7 +104,7 @@ pub mod tests { #[test] fn all_data() { - let mut it = ArgumentIterator::new(TEST_DATA.deref()); + let mut it = ArgumentIterator::new(&*TEST_DATA); it.fetch_str().unwrap(); let arg = it.fetch_all(); assert_eq!(arg, [0x62, 0x61, 0x72, 0x00, 0x62, 0x61]); @@ -113,7 +112,7 @@ pub mod tests { #[test] fn generic_argument() { - let mut it = ArgumentIterator::new(TEST_DATA.deref()); + let mut it = ArgumentIterator::new(&*TEST_DATA); let arg: &TestArgument = it.fetch().unwrap(); assert_eq!(arg.p1, 0x66); assert_eq!(arg.p2, 0x6f); @@ -127,7 +126,7 @@ pub mod tests { #[test] fn string_argument() { - let mut it = ArgumentIterator::new(TEST_DATA.deref()); + let mut it = ArgumentIterator::new(&*TEST_DATA); let arg = it.fetch_str().unwrap(); assert_eq!(arg, "foo"); let arg = it.fetch_str().unwrap(); @@ -137,7 +136,7 @@ pub mod tests { #[test] fn mixed_arguments() { - let mut it = ArgumentIterator::new(TEST_DATA.deref()); + let mut it = ArgumentIterator::new(&*TEST_DATA); let arg: &TestArgument = it.fetch().unwrap(); assert_eq!(arg.p1, 0x66); assert_eq!(arg.p2, 0x6f); @@ -150,7 +149,7 @@ pub mod tests { #[test] fn out_of_data() { - let mut it = ArgumentIterator::new(TEST_DATA.deref()); + let mut it = ArgumentIterator::new(&*TEST_DATA); it.fetch::().unwrap(); let arg: Option<&TestArgument> = it.fetch(); assert!(arg.is_none()); diff --git a/src/ll/mod.rs b/src/ll/mod.rs index e97ae2f9..14057640 100644 --- a/src/ll/mod.rs +++ b/src/ll/mod.rs @@ -225,7 +225,7 @@ impl Errno { pub const NO_XATTR: Errno = Self::ENOATTR; pub fn from_i32(err: i32) -> Errno { - err.try_into().ok().map(Errno).unwrap_or(Errno::EIO) + err.try_into().ok().map_or(Errno::EIO, Errno) } } impl From for Errno { diff --git a/src/ll/reply.rs b/src/ll/reply.rs index 2aa02dc4..c8e95f83 100644 --- a/src/ll/reply.rs +++ b/src/ll/reply.rs @@ -228,12 +228,13 @@ impl<'a> Response<'a> { // these fields are only needed for unrestricted ioctls flags: 0, in_iovs: 1, - out_iovs: if !data.is_empty() { 1 } else { 0 }, + // boolean to integer + out_iovs: u32::from(!data.is_empty()), }; // TODO: Don't copy this data let mut v: ResponseBuf = ResponseBuf::from_slice(r.as_bytes()); for x in data { - v.extend_from_slice(x) + v.extend_from_slice(x); } Self::Data(v) } @@ -291,7 +292,7 @@ pub(crate) fn mode_from_kind_and_perm(kind: FileType, perm: u16) -> u32 { FileType::Symlink => libc::S_IFLNK, FileType::Socket => libc::S_IFSOCK, }) as u32 - | perm as u32 + | u32::from(perm) } /// Returns a `fuse_attr` from `FileAttr` pub(crate) fn fuse_attr_from_attr(attr: &crate::FileAttr) -> abi::fuse_attr { diff --git a/src/ll/request.rs b/src/ll/request.rs index 681a517e..b560a29f 100644 --- a/src/ll/request.rs +++ b/src/ll/request.rs @@ -954,9 +954,9 @@ mod op { pub fn capabilities(&self) -> u64 { #[cfg(feature = "abi-7-36")] if self.arg.flags & (FUSE_INIT_EXT as u32) != 0 { - return (self.arg.flags as u64) | ((self.arg.flags2 as u64) << 32); + return u64::from(self.arg.flags) | (u64::from(self.arg.flags2) << 32); } - self.arg.flags as u64 + u64::from(self.arg.flags) } pub fn max_readahead(&self) -> u32 { self.arg.max_readahead diff --git a/src/mnt/mod.rs b/src/mnt/mod.rs index 870dc36e..46eb032b 100644 --- a/src/mnt/mod.rs +++ b/src/mnt/mod.rs @@ -101,12 +101,11 @@ fn is_mounted(fuse_device: &File) -> bool { let err = io::Error::last_os_error(); if err.kind() == io::ErrorKind::Interrupted { continue; - } else { - // This should never happen. The fd is guaranteed good as `File` owns it. - // According to man poll ENOMEM is the only error code unhandled, so we panic - // consistent with rust's usual ENOMEM behaviour. - panic!("Poll failed with error {err}") } + // This should never happen. The fd is guaranteed good as `File` owns it. + // According to man poll ENOMEM is the only error code unhandled, so we panic + // consistent with rust's usual ENOMEM behaviour. + panic!("Poll failed with error {err}") } _ => unreachable!(), }; diff --git a/src/mnt/mount_options.rs b/src/mnt/mount_options.rs index 0ce71969..220ba60a 100644 --- a/src/mnt/mount_options.rs +++ b/src/mnt/mount_options.rs @@ -91,25 +91,26 @@ pub fn check_option_conflicts(options: &[MountOption]) -> Result<(), io::Error> options_set.extend(options.iter().cloned()); let conflicting: HashSet = options.iter().flat_map(conflicts_with).collect(); let intersection: Vec = conflicting.intersection(&options_set).cloned().collect(); - if !intersection.is_empty() { + if intersection.is_empty() { + Ok(()) + } else { Err(io::Error::new( ErrorKind::InvalidInput, format!("Conflicting mount options found: {intersection:?}"), )) - } else { - Ok(()) } } fn conflicts_with(option: &MountOption) -> Vec { match option { - MountOption::FSName(_) => vec![], - MountOption::Subtype(_) => vec![], - MountOption::CUSTOM(_) => vec![], + MountOption::FSName(_) + | MountOption::Subtype(_) + | MountOption::CUSTOM(_) + | MountOption::DirSync + | MountOption::AutoUnmount + | MountOption::DefaultPermissions => vec![], MountOption::AllowOther => vec![MountOption::AllowRoot], MountOption::AllowRoot => vec![MountOption::AllowOther], - MountOption::AutoUnmount => vec![], - MountOption::DefaultPermissions => vec![], MountOption::Dev => vec![MountOption::NoDev], MountOption::NoDev => vec![MountOption::Dev], MountOption::Suid => vec![MountOption::NoSuid], @@ -120,7 +121,6 @@ fn conflicts_with(option: &MountOption) -> Vec { MountOption::NoExec => vec![MountOption::Exec], MountOption::Atime => vec![MountOption::NoAtime], MountOption::NoAtime => vec![MountOption::Atime], - MountOption::DirSync => vec![], MountOption::Sync => vec![MountOption::Async], MountOption::Async => vec![MountOption::Sync], } @@ -133,10 +133,10 @@ pub fn option_to_string(option: &MountOption) -> String { MountOption::Subtype(subtype) => format!("subtype={subtype}"), MountOption::CUSTOM(value) => value.to_string(), MountOption::AutoUnmount => "auto_unmount".to_string(), - MountOption::AllowOther => "allow_other".to_string(), + MountOption::AllowRoot | // AllowRoot is implemented by allowing everyone access and then restricting to // root + owner within fuser - MountOption::AllowRoot => "allow_other".to_string(), + MountOption::AllowOther => "allow_other".to_string(), MountOption::DefaultPermissions => "default_permissions".to_string(), MountOption::Dev => "dev".to_string(), MountOption::NoDev => "nodev".to_string(), @@ -174,7 +174,7 @@ pub(crate) fn parse_options_from_args(args: &[&OsStr]) -> io::Result return Err(err(format!("Error parsing args: expected -o, got {x}"))), }; for x in opt.split(',') { - out.push(MountOption::from_str(x)) + out.push(MountOption::from_str(x)); } } Ok(out) @@ -194,7 +194,7 @@ mod test { #[test] fn option_round_trip() { use super::MountOption::*; - for x in [ + for x in &[ FSName("Blah".to_owned()), Subtype("Bloo".to_owned()), CUSTOM("bongos".to_owned()), @@ -214,10 +214,8 @@ mod test { DirSync, Sync, Async, - ] - .iter() - { - assert_eq!(*x, MountOption::from_str(option_to_string(x).as_ref())) + ] { + assert_eq!(*x, MountOption::from_str(option_to_string(x).as_ref())); } } diff --git a/src/reply.rs b/src/reply.rs index 0938edb7..f065d1ca 100644 --- a/src/reply.rs +++ b/src/reply.rs @@ -85,7 +85,7 @@ impl ReplyRaw { } } fn send_ll(mut self, response: &ll::Response<'_>) { - self.send_ll_mut(response) + self.send_ll_mut(response); } /// Reply to a request with the given error code @@ -280,7 +280,7 @@ impl ReplyOpen { #[cfg(feature = "abi-7-40")] assert_eq!(flags & FOPEN_PASSTHROUGH, 0); self.reply - .send_ll(&ll::Response::new_open(ll::FileHandle(fh), flags, 0)) + .send_ll(&ll::Response::new_open(ll::FileHandle(fh), flags, 0)); } /// Registers a fd for passthrough, returning a `BackingId`. Once you have the backing ID, @@ -300,7 +300,7 @@ impl ReplyOpen { ll::FileHandle(fh), flags | FOPEN_PASSTHROUGH, backing_id.backing_id, - )) + )); } /// Reply to a request with the given error code @@ -328,7 +328,7 @@ impl Reply for ReplyWrite { impl ReplyWrite { /// Reply to a request with the given open result pub fn written(self, size: u32) { - self.reply.send_ll(&ll::Response::new_write(size)) + self.reply.send_ll(&ll::Response::new_write(size)); } /// Reply to a request with the given error code @@ -369,7 +369,7 @@ impl ReplyStatfs { ) { self.reply.send_ll(&ll::Response::new_statfs( blocks, bfree, bavail, files, ffree, bsize, namelen, frsize, - )) + )); } /// Reply to a request with the given error code @@ -406,7 +406,7 @@ impl ReplyCreate { ll::FileHandle(fh), flags, 0, - )) + )); } /// Reply to a request with the given error code @@ -438,7 +438,7 @@ impl ReplyLock { range: (start, end), typ, pid, - })) + })); } /// Reply to a request with the given error code @@ -466,7 +466,7 @@ impl Reply for ReplyBmap { impl ReplyBmap { /// Reply to a request with the given open result pub fn bmap(self, block: u64) { - self.reply.send_ll(&ll::Response::new_bmap(block)) + self.reply.send_ll(&ll::Response::new_bmap(block)); } /// Reply to a request with the given error code @@ -523,7 +523,7 @@ impl Reply for ReplyPoll { impl ReplyPoll { /// Reply to a request with the given poll result pub fn poll(self, revents: u32) { - self.reply.send_ll(&ll::Response::new_poll(revents)) + self.reply.send_ll(&ll::Response::new_poll(revents)); } /// Reply to a request with the given error code @@ -647,12 +647,12 @@ impl Reply for ReplyXattr { impl ReplyXattr { /// Reply to a request with the size of the xattr. pub fn size(self, size: u32) { - self.reply.send_ll(&ll::Response::new_xattr_size(size)) + self.reply.send_ll(&ll::Response::new_xattr_size(size)); } /// Reply to a request with the data in the xattr. pub fn data(self, data: &[u8]) { - self.reply.send_ll(&ll::Response::new_slice(data)) + self.reply.send_ll(&ll::Response::new_slice(data)); } /// Reply to a request with the given error code. @@ -680,7 +680,7 @@ impl Reply for ReplyLseek { impl ReplyLseek { /// Reply to a request with seeked offset pub fn offset(self, offset: i64) { - self.reply.send_ll(&ll::Response::new_lseek(offset)) + self.reply.send_ll(&ll::Response::new_lseek(offset)); } /// Reply to a request with the given error code @@ -736,7 +736,7 @@ mod test { fn send(&self, data: &[IoSlice<'_>]) -> std::io::Result<()> { let mut v = vec![]; for x in data { - v.extend_from_slice(x) + v.extend_from_slice(x); } assert_eq!(self.expected, v); Ok(()) diff --git a/src/request.rs b/src/request.rs index dcc923a8..e0c68d88 100644 --- a/src/request.rs +++ b/src/request.rs @@ -191,7 +191,7 @@ impl<'a> Request<'a> { se.filesystem.getattr( self, self.request.nodeid().into(), - _attr.file_handle().map(|fh| fh.into()), + _attr.file_handle().map(std::convert::Into::into), self.reply(), ); } @@ -206,7 +206,7 @@ impl<'a> Request<'a> { x.atime(), x.mtime(), x.ctime(), - x.file_handle().map(|fh| fh.into()), + x.file_handle().map(std::convert::Into::into), x.crtime(), x.chgtime(), x.bkuptime(), @@ -296,7 +296,7 @@ impl<'a> Request<'a> { x.offset(), x.size(), x.flags(), - x.lock_owner().map(|l| l.into()), + x.lock_owner().map(std::convert::Into::into), self.reply(), ); } @@ -309,7 +309,7 @@ impl<'a> Request<'a> { x.data(), x.write_flags(), x.flags(), - x.lock_owner().map(|l| l.into()), + x.lock_owner().map(std::convert::Into::into), self.reply(), ); } @@ -328,7 +328,7 @@ impl<'a> Request<'a> { self.request.nodeid().into(), x.file_handle().into(), x.flags(), - x.lock_owner().map(|x| x.into()), + x.lock_owner().map(std::convert::Into::into), x.flush(), self.reply(), ); @@ -482,18 +482,17 @@ impl<'a> Request<'a> { ll::Operation::IoCtl(x) => { if x.unrestricted() { return Err(Errno::ENOSYS); - } else { - se.filesystem.ioctl( - self, - self.request.nodeid().into(), - x.file_handle().into(), - x.flags(), - x.command(), - x.in_data(), - x.out_size(), - self.reply(), - ); } + se.filesystem.ioctl( + self, + self.request.nodeid().into(), + x.file_handle().into(), + x.flags(), + x.command(), + x.in_data(), + x.out_size(), + self.reply(), + ); } ll::Operation::Poll(x) => { let ph = PollHandle::new(se.ch.sender(), x.kernel_handle()); diff --git a/src/session.rs b/src/session.rs index 76e26255..467eb4c4 100644 --- a/src/session.rs +++ b/src/session.rs @@ -9,11 +9,11 @@ use libc::{EAGAIN, EINTR, ENODEV, ENOENT}; use log::{info, warn}; use nix::unistd::geteuid; use std::fmt; +use std::io; use std::os::fd::{AsFd, BorrowedFd, OwnedFd}; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::thread::{self, JoinHandle}; -use std::{io, ops::DerefMut}; use crate::Filesystem; use crate::MountOption; @@ -146,10 +146,7 @@ impl Session { // Buffer for receiving requests from the kernel. Only one is allocated and // it is reused immediately after dispatching to conserve memory and allocations. let mut buffer = vec![0; BUFFER_SIZE]; - let buf = aligned_sub_buf( - buffer.deref_mut(), - std::mem::align_of::(), - ); + let buf = aligned_sub_buf(&mut buffer, std::mem::align_of::()); loop { // Read the next request from the given channel to kernel driver // The kernel driver makes sure that we get exactly one request per read @@ -161,13 +158,11 @@ impl Session { None => break, }, Err(err) => match err.raw_os_error() { - // Operation interrupted. Accordingly to FUSE, this is safe to retry - Some(ENOENT) => continue, - // Interrupted system call, retry - Some(EINTR) => continue, - // Explicitly try again - Some(EAGAIN) => continue, - // Filesystem was unmounted, quit the loop + Some( + ENOENT // Operation interrupted. Accordingly to FUSE, this is safe to retry + | EINTR // Interrupted system call, retry + | EAGAIN // Explicitly instructed to try again + ) => continue, Some(ENODEV) => break, // Unhandled error _ => return Err(err),