From 6767faba13c92de22b63ef3f1281e06b70b76422 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Tue, 23 Jun 2026 14:01:31 +0700 Subject: [PATCH] Remove Box in scheme handle --- src/mount/redox/scheme.rs | 609 ++++++++++++++++++-------------------- 1 file changed, 294 insertions(+), 315 deletions(-) diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs index c88dffd242..6fe54a1ef2 100644 --- a/src/mount/redox/scheme.rs +++ b/src/mount/redox/scheme.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::marker::PhantomData; use std::mem; use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -31,10 +32,37 @@ use crate::{Disk, FileSystem, Node, Transaction, TreeData, TreePtr, BLOCK_SIZE}; use super::resource::{DirResource, Entry, FileMmapInfo, FileResource, Resource}; enum Handle { - Resource(Box>), + ResourceDir((DirResource, PhantomData)), + ResourceFile((FileResource, PhantomData)), SchemeRoot, } +impl Handle { + pub fn resource(&self) -> Result<&dyn Resource> { + match self { + Handle::ResourceDir((dir_resource, _)) => Ok(dir_resource as &dyn Resource), + Handle::ResourceFile((file_resource, _)) => Ok(file_resource), + Handle::SchemeRoot => Err(Error::new(EBADF)), + } + } + pub fn resource_mut(&mut self) -> Result<&mut dyn Resource> { + match self { + Handle::ResourceDir((dir_resource, _)) => Ok(dir_resource as &mut dyn Resource), + Handle::ResourceFile((file_resource, _)) => Ok(file_resource), + Handle::SchemeRoot => Err(Error::new(EBADF)), + } + } + pub fn get_resource(res: Option<&Self>) -> Result<&dyn Resource> { + res.ok_or(Error::new(EBADF)).and_then(|s| s.resource()) + } + pub fn get_resource_mut(res: Option<&mut Self>) -> Result<&mut dyn Resource> { + res.ok_or(Error::new(EBADF)).and_then(|s| s.resource_mut()) + } + pub fn get_resource_or(res: Option<&Self>) -> Result>> { + res.ok_or(Error::new(EBADF)).map(|s| s.resource().ok()) + } +} + pub struct FileScheme<'sock, D: Disk> { scheme_name: String, mounted_path: String, @@ -142,9 +170,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } fn handle_connect(&mut self, id: usize, payload: &mut [u8]) -> Result { - let Some(Handle::Resource(resource)) = self.handles.get(&id) else { - return Err(Error::new(EBADF)); - }; + let resource = Handle::get_resource(self.handles.get(&id))?; let inode_id = resource.node_ptr().id(); let target_fd = self .other_scheme_fd_map @@ -178,7 +204,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { .fs .tx(|tx| Self::path_nodes(scheme_name, tx, start_ptr, path, uid, gid, &mut nodes))?; let parent_ptr_opt = nodes.last().map(|x| x.0.ptr()); - let resource: Box> = match node_opt { + let handle: Handle = match node_opt { Some((node, _node_name)) => { if flags & (O_CREAT | O_EXCL) == O_CREAT | O_EXCL { return Err(Error::new(EEXIST)); @@ -202,23 +228,29 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } } - Box::new(DirResource::new( - path.to_string(), - parent_ptr_opt, - node.ptr(), - Some(data), - uid, + Handle::ResourceDir(( + DirResource::new( + path.to_string(), + parent_ptr_opt, + node.ptr(), + Some(data), + uid, + ), + PhantomData, )) } else if flags & O_WRONLY == O_WRONLY { // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path); return Err(Error::new(EISDIR)); } else { - Box::new(DirResource::new( - path.to_string(), - parent_ptr_opt, - node.ptr(), - None, - uid, + Handle::ResourceDir(( + DirResource::new( + path.to_string(), + parent_ptr_opt, + node.ptr(), + None, + uid, + ), + PhantomData, )) } } else if node.data().is_symlink() @@ -276,12 +308,9 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { })?; } - Box::new(FileResource::new( - path.to_string(), - parent_ptr_opt, - node_ptr, - flags, - uid, + Handle::ResourceFile(( + FileResource::new(path.to_string(), parent_ptr_opt, node_ptr, flags, uid), + PhantomData, )) } } @@ -328,20 +357,26 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { })?; if dir { - Box::new(DirResource::new( - path.to_string(), - parent_ptr_opt, - node_ptr, - None, - uid, + Handle::ResourceDir(( + DirResource::new( + path.to_string(), + parent_ptr_opt, + node_ptr, + None, + uid, + ), + PhantomData, )) } else { - Box::new(FileResource::new( - path.to_string(), - parent_ptr_opt, - node_ptr, - flags, - uid, + Handle::ResourceFile(( + FileResource::new( + path.to_string(), + parent_ptr_opt, + node_ptr, + flags, + uid, + ), + PhantomData, )) } } else { @@ -356,7 +391,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } }; - let node_ptr = resource.node_ptr(); + let node_ptr = handle.resource().unwrap().node_ptr(); { let fmap_info = self .fmap @@ -370,7 +405,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } let id = self.next_id.fetch_add(1, Ordering::Relaxed); - self.handles.insert(id, Handle::Resource(resource)); + self.handles.insert(id, handle); Ok(OpenResult::ThisScheme { number: id, @@ -514,7 +549,7 @@ fn dirname(path: &str) -> Option { } // TODO: Reimplement these using the scheme common path related crate -pub fn resolve_path(dir: &Box>, path: String) -> Option { +pub fn resolve_path(dir: &dyn Resource, path: String) -> Option { let max_upward_depth = 64; // Same value as MAX_LEVEL of sym loops in relibc let (canon, _depth) = canonicalize_using_cwd_with_max_upward_depth(dir.path(), &path, max_upward_depth)?; @@ -581,10 +616,10 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { ctx: &CallerCtx, ) -> Result { let path = path.to_string(); - let path_to_open = match self.handles.get(&dirfd).ok_or(Error::new(EBADF))? { + let path_to_open = match Handle::get_resource_or(self.handles.get(&dirfd))? { // If pathname is absolute, then dirfd is ignored. - Handle::Resource(dir_resource) if !path.starts_with('/') => { - resolve_path(&dir_resource, path).ok_or(Error::new(ENOENT))? + Some(res) if !path.starts_with('/') => { + resolve_path(res, path).ok_or(Error::new(ENOENT))? } _ => path.to_string(), }; @@ -595,12 +630,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let uid = ctx.uid; let gid = ctx.gid; let url = url.to_string(); - - let path = match self.handles.get(&dirfd).ok_or(Error::new(EBADF))? { - Handle::Resource(dir_resource) => { - resolve_path(&dir_resource, url).ok_or(Error::new(ENOENT))? - } - Handle::SchemeRoot => url, + let path = match Handle::get_resource_or(self.handles.get(&dirfd))? { + Some(res) => resolve_path(res, url).ok_or(Error::new(ENOENT))?, + None => url, }; let path = path.trim_matches('/'); let start_ptr = TreePtr::root(); @@ -620,9 +652,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _ctx: &CallerCtx, ) -> Result { // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; self.fs.tx(|tx| file.read(&mut self.fmap, buf, offset, tx)) } @@ -635,83 +665,64 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _ctx: &CallerCtx, ) -> Result { // println!("Write {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; self.fs.tx(|tx| file.write(&mut self.fmap, buf, offset, tx)) } fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result { // println!("Seek {}, {} {}", id, pos, whence); - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; self.fs.tx(|tx| file.fsize(tx)) } fn fchmod(&mut self, id: usize, mode: u16, _ctx: &CallerCtx) -> Result<()> { - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - self.fs.tx(|tx| file.fchmod(mode, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + self.fs.tx(|tx| file.fchmod(mode, tx)) } fn fchown(&mut self, id: usize, new_uid: u32, new_gid: u32, _ctx: &CallerCtx) -> Result<()> { - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - self.fs.tx(|tx| file.fchown(new_uid, new_gid, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + self.fs.tx(|tx| file.fchown(new_uid, new_gid, tx)) } fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result { - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - file.fcntl(cmd, arg) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + file.fcntl(cmd, arg) } fn fevent(&mut self, id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result { - if let Some(Handle::Resource(_file)) = self.handles.get(&id) { - // EPERM is returned for handles that are always readable or writable - Err(Error::new(EPERM)) - } else { - Err(Error::new(EBADF)) - } + let _file = Handle::get_resource(self.handles.get(&id))?; + // EPERM is returned for handles that are always readable or writable + Err(Error::new(EPERM)) } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { // println!("Fpath {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - if let Some(Handle::Resource(file)) = self.handles.get(&id) { - let mounted_path = self.mounted_path.as_bytes(); + let file = Handle::get_resource(self.handles.get(&id))?; + let mounted_path = self.mounted_path.as_bytes(); - let mut i = 0; - while i < buf.len() && i < mounted_path.len() { - buf[i] = mounted_path[i]; + let mut i = 0; + while i < buf.len() && i < mounted_path.len() { + buf[i] = mounted_path[i]; + i += 1; + } + + let path = file.path().as_bytes(); + if !path.is_empty() { + if i < buf.len() { + buf[i] = b'/'; i += 1; } - let path = file.path().as_bytes(); - if !path.is_empty() { - if i < buf.len() { - buf[i] = b'/'; - i += 1; - } - - let mut j = 0; - while i < buf.len() && j < path.len() { - buf[i] = path[j]; - i += 1; - j += 1; - } + let mut j = 0; + while i < buf.len() && j < path.len() { + buf[i] = path[j]; + i += 1; + j += 1; } - - Ok(i) - } else { - Err(Error::new(EBADF)) } + + Ok(i) } //TODO: this function has too much code, try to simplify it @@ -722,103 +733,100 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { // println!("Flink {}, {} from {}, {}", id, new_path, uid, gid); - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - //TODO: Check for EINVAL - // The new pathname contained a path prefix of the old, or, more generally, - // an attempt was made to make a directory a subdirectory of itself. + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + //TODO: Check for EINVAL + // The new pathname contained a path prefix of the old, or, more generally, + // an attempt was made to make a directory a subdirectory of itself. - let mut old_name = String::new(); - for part in file.path().split('/') { - if !part.is_empty() { - old_name = part.to_string(); + let mut old_name = String::new(); + for part in file.path().split('/') { + if !part.is_empty() { + old_name = part.to_string(); + } + } + if old_name.is_empty() { + return Err(Error::new(EPERM)); + } + + let mut new_name = String::new(); + for part in new_path.split('/') { + if !part.is_empty() { + new_name = part.to_string(); + } + } + if new_name.is_empty() { + return Err(Error::new(EPERM)); + } + + let scheme_name = &self.scheme_name; + self.fs.tx(|tx| { + let _orig_parent_ptr = match file.parent_ptr_opt() { + Some(some) => some, + None => { + // println!("orig is root"); + return Err(Error::new(EBUSY)); } - } - if old_name.is_empty() { - return Err(Error::new(EPERM)); + }; + + let orig_node = tx.read_tree(file.node_ptr())?; + + if !orig_node.data().owner(uid) { + // println!("orig_node not owned by caller {}", uid); + return Err(Error::new(EACCES)); } - let mut new_name = String::new(); - for part in new_path.split('/') { - if !part.is_empty() { - new_name = part.to_string(); - } - } - if new_name.is_empty() { - return Err(Error::new(EPERM)); - } + let mut new_nodes = Vec::new(); + let new_node_opt = Self::path_nodes( + scheme_name, + tx, + TreePtr::root(), + new_path, + uid, + gid, + &mut new_nodes, + )?; - let scheme_name = &self.scheme_name; - self.fs.tx(|tx| { - let _orig_parent_ptr = match file.parent_ptr_opt() { - Some(some) => some, - None => { - // println!("orig is root"); - return Err(Error::new(EBUSY)); - } - }; - - let orig_node = tx.read_tree(file.node_ptr())?; - - if !orig_node.data().owner(uid) { - // println!("orig_node not owned by caller {}", uid); + if let Some((ref new_parent, _)) = new_nodes.last() { + if !new_parent.data().owner(uid) { + // println!("new_parent not owned by caller {}", uid); return Err(Error::new(EACCES)); } - let mut new_nodes = Vec::new(); - let new_node_opt = Self::path_nodes( - scheme_name, - tx, - TreePtr::root(), - new_path, - uid, - gid, - &mut new_nodes, - )?; - - if let Some((ref new_parent, _)) = new_nodes.last() { - if !new_parent.data().owner(uid) { - // println!("new_parent not owned by caller {}", uid); + if let Some((ref new_node, _)) = new_node_opt { + if !new_node.data().owner(uid) { + // println!("new dir not owned by caller {}", uid); return Err(Error::new(EACCES)); } - if let Some((ref new_node, _)) = new_node_opt { - if !new_node.data().owner(uid) { - // println!("new dir not owned by caller {}", uid); + if new_node.data().is_dir() { + if !orig_node.data().is_dir() { + // println!("orig_node is file, new is dir"); return Err(Error::new(EACCES)); } - if new_node.data().is_dir() { - if !orig_node.data().is_dir() { - // println!("orig_node is file, new is dir"); - return Err(Error::new(EACCES)); - } + let mut children = Vec::new(); + tx.child_nodes(new_node.ptr(), &mut children)?; - let mut children = Vec::new(); - tx.child_nodes(new_node.ptr(), &mut children)?; - - if !children.is_empty() { - // println!("new dir not empty"); - return Err(Error::new(ENOTEMPTY)); - } - } else { - if orig_node.data().is_dir() { - // println!("orig_node is dir, new is file"); - return Err(Error::new(ENOTDIR)); - } + if !children.is_empty() { + // println!("new dir not empty"); + return Err(Error::new(ENOTEMPTY)); + } + } else { + if orig_node.data().is_dir() { + // println!("orig_node is dir, new is file"); + return Err(Error::new(ENOTDIR)); } } - - tx.link_node(new_parent.ptr(), &new_name, orig_node.ptr())?; - - file.set_path(new_path); - Ok(0) - } else { - Err(Error::new(EPERM)) } - }) - } else { - Err(Error::new(EBADF)) - } + + tx.link_node(new_parent.ptr(), &new_name, orig_node.ptr())?; + + file.set_path(new_path); + Ok(0) + } else { + Err(Error::new(EPERM)) + } + }) } //TODO: this function has too much code, try to simplify it @@ -829,132 +837,121 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { // println!("Frename {}, {} from {}, {}", id, new_path, uid, gid); - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - //TODO: Check for EINVAL - // The new pathname contained a path prefix of the old, or, more generally, - // an attempt was made to make a directory a subdirectory of itself. + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + //TODO: Check for EINVAL + // The new pathname contained a path prefix of the old, or, more generally, + // an attempt was made to make a directory a subdirectory of itself. - let mut old_name = String::new(); - for part in file.path().split('/') { - if !part.is_empty() { - old_name = part.to_string(); + let mut old_name = String::new(); + for part in file.path().split('/') { + if !part.is_empty() { + old_name = part.to_string(); + } + } + if old_name.is_empty() { + return Err(Error::new(EPERM)); + } + + let mut new_name = String::new(); + for part in new_path.split('/') { + if !part.is_empty() { + new_name = part.to_string(); + } + } + if new_name.is_empty() { + return Err(Error::new(EPERM)); + } + + let scheme_name = &self.scheme_name; + self.fs.tx(|tx| { + let orig_parent_ptr = match file.parent_ptr_opt() { + Some(some) => some, + None => { + // println!("orig is root"); + return Err(Error::new(EBUSY)); } - } - if old_name.is_empty() { - return Err(Error::new(EPERM)); + }; + + let orig_node = tx.read_tree(file.node_ptr())?; + + if !orig_node.data().owner(uid) { + // println!("orig_node not owned by caller {}", uid); + return Err(Error::new(EACCES)); } - let mut new_name = String::new(); - for part in new_path.split('/') { - if !part.is_empty() { - new_name = part.to_string(); - } - } - if new_name.is_empty() { - return Err(Error::new(EPERM)); - } + let mut new_nodes = Vec::new(); + let new_node_opt = Self::path_nodes( + scheme_name, + tx, + TreePtr::root(), + new_path, + uid, + gid, + &mut new_nodes, + )?; - let scheme_name = &self.scheme_name; - self.fs.tx(|tx| { - let orig_parent_ptr = match file.parent_ptr_opt() { - Some(some) => some, - None => { - // println!("orig is root"); - return Err(Error::new(EBUSY)); - } - }; - - let orig_node = tx.read_tree(file.node_ptr())?; - - if !orig_node.data().owner(uid) { - // println!("orig_node not owned by caller {}", uid); + if let Some((ref new_parent, _)) = new_nodes.last() { + if !new_parent.data().owner(uid) { + // println!("new_parent not owned by caller {}", uid); return Err(Error::new(EACCES)); } - let mut new_nodes = Vec::new(); - let new_node_opt = Self::path_nodes( - scheme_name, - tx, - TreePtr::root(), - new_path, - uid, - gid, - &mut new_nodes, - )?; - - if let Some((ref new_parent, _)) = new_nodes.last() { - if !new_parent.data().owner(uid) { - // println!("new_parent not owned by caller {}", uid); + if let Some((ref new_node, _)) = new_node_opt { + if !new_node.data().owner(uid) { + // println!("new dir not owned by caller {}", uid); return Err(Error::new(EACCES)); } - if let Some((ref new_node, _)) = new_node_opt { - if !new_node.data().owner(uid) { - // println!("new dir not owned by caller {}", uid); + if new_node.data().is_dir() { + if !orig_node.data().is_dir() { + // println!("orig_node is file, new is dir"); return Err(Error::new(EACCES)); } - if new_node.data().is_dir() { - if !orig_node.data().is_dir() { - // println!("orig_node is file, new is dir"); - return Err(Error::new(EACCES)); - } + let mut children = Vec::new(); + tx.child_nodes(new_node.ptr(), &mut children)?; - let mut children = Vec::new(); - tx.child_nodes(new_node.ptr(), &mut children)?; - - if !children.is_empty() { - // println!("new dir not empty"); - return Err(Error::new(ENOTEMPTY)); - } - } else { - if orig_node.data().is_dir() { - // println!("orig_node is dir, new is file"); - return Err(Error::new(ENOTDIR)); - } + if !children.is_empty() { + // println!("new dir not empty"); + return Err(Error::new(ENOTEMPTY)); + } + } else { + if orig_node.data().is_dir() { + // println!("orig_node is dir, new is file"); + return Err(Error::new(ENOTDIR)); } } - - tx.rename_node(orig_parent_ptr, &old_name, new_parent.ptr(), &new_name)?; - - file.set_path(new_path); - Ok(0) - } else { - Err(Error::new(EPERM)) } - }) - } else { - Err(Error::new(EBADF)) - } + + tx.rename_node(orig_parent_ptr, &old_name, new_parent.ptr(), &new_name)?; + + file.set_path(new_path); + Ok(0) + } else { + Err(Error::new(EPERM)) + } + }) } fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { // println!("Fstat {}, {:X}", id, stat as *mut Stat as usize); - if let Some(Handle::Resource(file)) = self.handles.get(&id) { - self.fs.tx(|tx| file.stat(stat, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource(self.handles.get(&id))?; + self.fs.tx(|tx| file.stat(stat, tx)) } fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, _ctx: &CallerCtx) -> Result<()> { - if let Some(Handle::Resource(_file)) = self.handles.get(&id) { - stat.f_bsize = BLOCK_SIZE as u32; - stat.f_blocks = self.fs.header.size() / (stat.f_bsize as u64); - stat.f_bfree = self.fs.allocator().free(); - stat.f_bavail = stat.f_bfree; + let _file = Handle::get_resource(self.handles.get(&id))?; + stat.f_bsize = BLOCK_SIZE as u32; + stat.f_blocks = self.fs.header.size() / (stat.f_bsize as u64); + stat.f_bfree = self.fs.allocator().free(); + stat.f_bavail = stat.f_bfree; - Ok(()) - } else { - Err(Error::new(EBADF)) - } + Ok(()) } fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { // println!("Fsync {}", id); - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.sync(fmaps, tx)) @@ -962,20 +959,14 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { fn ftruncate(&mut self, id: usize, len: u64, _ctx: &CallerCtx) -> Result<()> { // println!("Ftruncate {}, {}", id, len); - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - self.fs.tx(|tx| file.truncate(len, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + self.fs.tx(|tx| file.truncate(len, tx)) } fn futimens(&mut self, id: usize, times: &[TimeSpec], _ctx: &CallerCtx) -> Result<()> { // println!("Futimens {}, {}", id, times.len()); - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - self.fs.tx(|tx| file.utimens(times, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + self.fs.tx(|tx| file.utimens(times, tx)) } fn getdents<'buf>( @@ -984,11 +975,8 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { buf: DirentBuf<&'buf mut [u8]>, opaque_offset: u64, ) -> Result> { - if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { - self.fs.tx(|tx| file.getdents(buf, opaque_offset, tx)) - } else { - Err(Error::new(EBADF)) - } + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; + self.fs.tx(|tx| file.getdents(buf, opaque_offset, tx)) } fn mmap_prep( @@ -999,9 +987,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { flags: MapFlags, _ctx: &CallerCtx, ) -> Result { - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.fmap(fmaps, flags, size, offset, tx)) @@ -1014,9 +1000,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _flags: MunmapFlags, _ctx: &CallerCtx, ) -> Result<()> { - let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { - return Err(Error::new(EBADF)); - }; + let file = Handle::get_resource_mut(self.handles.get_mut(&id))?; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.funmap(fmaps, offset, size, tx)) @@ -1024,10 +1008,13 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { fn on_close(&mut self, id: usize) { // println!("Close {}", id); - let Some(Handle::Resource(file)) = self.handles.remove(&id) else { + let Some(file) = self.handles.remove(&id) else { return; }; - let node_ptr = file.node_ptr(); + let Ok(resource) = file.resource() else { + return; + }; + let node_ptr = resource.node_ptr(); let Some(file_info) = self.fmap.get_mut(&node_ptr.id()) else { return; }; @@ -1056,9 +1043,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let uid = ctx.uid; let gid = ctx.gid; - let Some(Handle::Resource(parent_resource)) = self.handles.get(&sendfd_request.id()) else { - return Err(Error::new(EBADF)); - }; + let parent_resource = Handle::get_resource(self.handles.get(&sendfd_request.id()))?; let mut new_fd = usize::MAX; if let Err(e) = sendfd_request.obtain_fd( @@ -1096,7 +1081,10 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } } - let (resource, node_id): (Box>, u32) = if !last_part.is_empty() { + if last_part.is_empty() { + return Err(Error::new(EINVAL)); + } + let (resource, node_id) = { let stat = other_scheme_fd.stat()?; let mode_type = stat.st_mode as u16 & Node::MODE_TYPE; @@ -1128,20 +1116,12 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let node_id = node_ptr.id(); ( - Box::new(FileResource::new( - file_path, - Some(parent_resource_ptr), - node_ptr, - flags, - uid, - )), + FileResource::new(file_path, Some(parent_resource_ptr), node_ptr, flags, uid), node_id, ) - } else { - return Err(Error::new(EINVAL)); }; - let node_ptr = resource.node_ptr(); + let node_ptr = (&resource as &'_ dyn Resource).node_ptr(); { let fmap_info = self .fmap @@ -1155,7 +1135,8 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } let id = self.next_id.fetch_add(1, Ordering::Relaxed); - self.handles.insert(id, Handle::Resource(resource)); + self.handles + .insert(id, Handle::ResourceFile((resource, PhantomData))); self.other_scheme_fd_map.insert(node_id, other_scheme_fd); Ok(new_fd) } @@ -1215,9 +1196,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } fn inode(&self, id: usize) -> Result { - let Some(Handle::Resource(resource)) = self.handles.get(&id) else { - return Err(Error::new(EBADF)); - }; + let resource = Handle::get_resource(self.handles.get(&id))?; Ok(resource.node_ptr().id() as usize) } }