diff --git a/Cargo.lock b/Cargo.lock index 726e87c950..391534f40e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -347,9 +347,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", @@ -494,9 +494,9 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" [[package]] name = "redox-scheme" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cea2668a5932f878a4298a1d7f8950249bbbb77120fb263da252c589152f5ea" +checksum = "5eb0cee524a5c6e4db180250f699e101ee25f3f79ad2618527e539e028cb6722" dependencies = [ "libredox", "redox_syscall", @@ -504,9 +504,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ "bitflags", ] @@ -519,7 +519,7 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" [[package]] name = "redoxfs" -version = "0.8.6" +version = "0.9.0" dependencies = [ "aes", "argon2", diff --git a/Cargo.toml b/Cargo.toml index 2ebf671814..d063d78818 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "redoxfs" description = "The Redox Filesystem" repository = "https://gitlab.redox-os.org/redox-os/redoxfs" -version = "0.8.6" +version = "0.9.0" license-file = "LICENSE" readme = "README.md" authors = ["Jeremy Soller "] @@ -56,7 +56,7 @@ log = { version = "0.4.14", default-features = false, optional = true } lz4_flex = { version = "0.11", default-features = false, features = ["checked-decode"] } parse-size = { version = "1", optional = true } range-tree = { version = "0.1", optional = true } -redox_syscall = "0.6.0" +redox_syscall = "0.7.0" seahash = { version = "4.1.0", default-features = false } termion = { version = "4", optional = true } uuid = { version = "1.4", default-features = false } @@ -85,9 +85,9 @@ std = [ fuser = { version = "0.16", optional = true } [target.'cfg(target_os = "redox")'.dependencies] -libredox = { version = "0.1.11", features = ["call"], optional = true } +libredox = { version = "0.1.12", features = ["call"], optional = true } redox-path = "0.3.0" -redox-scheme = { version = "0.8.3", optional = true } +redox-scheme = { version = "0.9.0", optional = true } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } diff --git a/src/mount/redox/mod.rs b/src/mount/redox/mod.rs index 3baafa527d..0a9abeb546 100644 --- a/src/mount/redox/mod.rs +++ b/src/mount/redox/mod.rs @@ -20,13 +20,21 @@ where F: FnOnce(&Path) -> T, { let mountpoint = mountpoint.as_ref(); - let scheme_name = format!("{}", mountpoint.display()); - let socket = Socket::create(&scheme_name)?; + let socket = Socket::create()?; + let scheme_name = format!("{}", mountpoint.display()); let mounted_path = format!("/scheme/{}", mountpoint.display()); + + let mut scheme = FileScheme::new(scheme_name, mounted_path.clone(), filesystem, &socket); + + redox_scheme::scheme::register_sync_scheme( + &socket, + &format!("{}", mountpoint.display()), + &mut scheme, + )?; + let res = callback(Path::new(&mounted_path)); - let mut scheme = FileScheme::new(scheme_name, mounted_path, filesystem, &socket); while IS_UMT.load(Ordering::SeqCst) == 0 { let req = match socket.next_request(SignalBehavior::Restart)? { None => break, diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs index a483b5389d..1cda78f925 100644 --- a/src/mount/redox/scheme.rs +++ b/src/mount/redox/scheme.rs @@ -28,13 +28,18 @@ use crate::{Disk, FileSystem, Node, Transaction, TreeData, TreePtr, BLOCK_SIZE}; use super::resource::{DirResource, Entry, FileMmapInfo, FileResource, Resource}; +enum Handle { + Resource(Box>), + SchemeRoot, +} + pub struct FileScheme<'sock, D: Disk> { scheme_name: String, mounted_path: String, pub(crate) fs: FileSystem, socket: &'sock Socket, next_id: AtomicUsize, - files: BTreeMap>>, + handles: BTreeMap>, fmap: super::resource::Fmaps, // Map of file id to other scheme's file descriptor. @@ -54,7 +59,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { fs, socket, next_id: AtomicUsize::new(1), - files: BTreeMap::new(), + handles: BTreeMap::new(), fmap: BTreeMap::new(), other_scheme_fd_map: BTreeMap::new(), } @@ -126,7 +131,9 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } fn handle_connect(&mut self, id: usize, payload: &mut [u8]) -> Result { - let resource = self.files.get(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(resource)) = self.handles.get(&id) else { + return Err(Error::new(EBADF)); + }; let inode_id = resource.node_ptr().id(); let target_fd = self .other_scheme_fd_map @@ -136,6 +143,10 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { return Ok(len); } + fn open(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result { + self.open_internal(TreePtr::root(), url, flags, ctx) + } + fn open_internal( &mut self, start_ptr: TreePtr, @@ -347,7 +358,7 @@ impl<'sock, D: Disk> FileScheme<'sock, D> { } let id = self.next_id.fetch_add(1, Ordering::Relaxed); - self.files.insert(id, resource); + self.handles.insert(id, Handle::Resource(resource)); Ok(OpenResult::ThisScheme { number: id, @@ -418,8 +429,10 @@ fn dirname(path: &str) -> Option { } impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { - fn open(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result { - self.open_internal(TreePtr::root(), url, flags, ctx) + fn scheme_root(&mut self) -> Result { + let id = self.next_id.fetch_add(1, Ordering::Relaxed); + self.handles.insert(id, Handle::SchemeRoot); + Ok(id) } fn openat( @@ -430,13 +443,14 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _fcntl_flags: u32, ctx: &CallerCtx, ) -> Result { - // If pathname is absolute, then dirfd is ignored. - if path.starts_with('/') { - return self.open_internal(TreePtr::root(), path, flags, ctx); - } - let dir_resource = self.files.get(&dirfd).ok_or(Error::new(EBADF))?; - // Only allow DirResource as base for openat - let dir_node_ptr = dir_resource.node_ptr(); + let dir_node_ptr = match self.handles.get(&dirfd).ok_or(Error::new(EBADF))? { + // If pathname is absolute, then dirfd is ignored. + Handle::Resource(dir_resource) if !path.starts_with('/') => { + // only allow dirresource as base for openat + dir_resource.node_ptr() + } + _ => TreePtr::root(), + }; self.open_internal(dir_node_ptr, path, flags, ctx) } @@ -445,8 +459,12 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let uid = ctx.uid; let gid = ctx.gid; - let start_ptr = self.files.get(&dirfd).ok_or(Error::new(EBADF))?.node_ptr(); - // println!("Unlinkat '{}' flags: {:X}", path, flags);+ + let start_ptr = match self.handles.get(&dirfd).ok_or(Error::new(EBADF))? { + Handle::Resource(dir_resource) => dir_resource.node_ptr(), + Handle::SchemeRoot => TreePtr::root(), + }; + + // println!("Unlinkat '{}' flags: {:X}", path, flags); let scheme_name = &self.scheme_name; @@ -505,9 +523,11 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let Some(node_id) = unlink_result? else { return Ok(()); }; + if let Some(fd) = self.other_scheme_fd_map.remove(&node_id) { let _ = syscall::close(fd); } + Ok(()) } @@ -521,7 +541,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _ctx: &CallerCtx, ) -> Result { // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; self.fs.tx(|tx| file.read(buf, offset, tx)) } @@ -534,18 +556,22 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { _ctx: &CallerCtx, ) -> Result { // println!("Write {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; self.fs.tx(|tx| file.write(buf, offset, tx)) } fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result { // println!("Seek {}, {} {}", id, pos, whence); - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; self.fs.tx(|tx| file.fsize(tx)) } fn fchmod(&mut self, id: usize, mode: u16, _ctx: &CallerCtx) -> Result<()> { - if let Some(file) = self.files.get_mut(&id) { + if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { self.fs.tx(|tx| file.fchmod(mode, tx)) } else { Err(Error::new(EBADF)) @@ -553,7 +579,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } fn fchown(&mut self, id: usize, new_uid: u32, new_gid: u32, _ctx: &CallerCtx) -> Result<()> { - if let Some(file) = self.files.get_mut(&id) { + 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)) @@ -561,7 +587,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result { - if let Some(file) = self.files.get_mut(&id) { + if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { file.fcntl(cmd, arg) } else { Err(Error::new(EBADF)) @@ -569,8 +595,8 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } fn fevent(&mut self, id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result { - if let Some(_file) = self.files.get(&id) { - // EPERM is returned for files that are always readable or writable + 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)) @@ -579,7 +605,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { 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(file) = self.files.get(&id) { + if let Some(Handle::Resource(file)) = self.handles.get(&id) { let mounted_path = self.mounted_path.as_bytes(); let mut i = 0; @@ -614,7 +640,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { // println!("Flink {}, {} from {}, {}", id, new_path, uid, gid); - if let Some(file) = self.files.get_mut(&id) { + 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. @@ -721,7 +747,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { // println!("Frename {}, {} from {}, {}", id, new_path, uid, gid); - if let Some(file) = self.files.get_mut(&id) { + 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. @@ -822,7 +848,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { 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(file) = self.files.get(&id) { + if let Some(Handle::Resource(file)) = self.handles.get(&id) { self.fs.tx(|tx| file.stat(stat, tx)) } else { Err(Error::new(EBADF)) @@ -830,7 +856,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, _ctx: &CallerCtx) -> Result<()> { - if let Some(_file) = self.files.get(&id) { + 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(); @@ -844,7 +870,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { // println!("Fsync {}", id); - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.sync(fmaps, tx)) @@ -852,7 +880,7 @@ 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(file) = self.files.get_mut(&id) { + if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { self.fs.tx(|tx| file.truncate(len, tx)) } else { Err(Error::new(EBADF)) @@ -861,7 +889,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { fn futimens(&mut self, id: usize, times: &[TimeSpec], _ctx: &CallerCtx) -> Result<()> { // println!("Futimens {}, {}", id, times.len()); - if let Some(file) = self.files.get_mut(&id) { + if let Some(Handle::Resource(file)) = self.handles.get_mut(&id) { self.fs.tx(|tx| file.utimens(times, tx)) } else { Err(Error::new(EBADF)) @@ -874,7 +902,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { buf: DirentBuf<&'buf mut [u8]>, opaque_offset: u64, ) -> Result> { - if let Some(file) = self.files.get_mut(&id) { + 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)) @@ -889,7 +917,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { flags: MapFlags, _ctx: &CallerCtx, ) -> Result { - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.fmap(fmaps, flags, size, offset, tx)) @@ -903,7 +933,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { flags: MunmapFlags, _ctx: &CallerCtx, ) -> Result<()> { - let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(file)) = self.handles.get_mut(&id) else { + return Err(Error::new(EBADF)); + }; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.funmap(fmaps, offset, size, tx)) @@ -911,7 +943,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { fn on_close(&mut self, id: usize) { // println!("Close {}", id); - let Some(file) = self.files.remove(&id) else { + let Some(Handle::Resource(file)) = self.handles.remove(&id) else { return; }; let node_ptr = file.node_ptr(); @@ -943,10 +975,9 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { let uid = ctx.uid; let gid = ctx.gid; - let parent_resource = self - .files - .get(&sendfd_request.id()) - .ok_or(Error::new(EBADF))?; + let Some(Handle::Resource(parent_resource)) = self.handles.get(&sendfd_request.id()) else { + return Err(Error::new(EBADF)); + }; let mut new_fd = usize::MAX; if let Err(e) = sendfd_request.obtain_fd( @@ -1042,7 +1073,7 @@ impl<'sock, D: Disk> SchemeSync for FileScheme<'sock, D> { } let id = self.next_id.fetch_add(1, Ordering::Relaxed); - self.files.insert(id, resource); + self.handles.insert(id, Handle::Resource(resource)); self.other_scheme_fd_map.insert(node_id, new_fd); Ok(new_fd) }