diff --git a/Cargo.lock b/Cargo.lock index f8ca61852c..88b7f6f261 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -264,9 +264,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "jiff" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ec30f7142be6fe14e1b021f50b85db8df2d4324ea6e91ec3e5dcde092021d0" +checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd" dependencies = [ "jiff-static", "log", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "526b834d727fd59d37b076b0c3236d9adde1b1729a4361e20b2026f738cc1dbe" +checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300" dependencies = [ "proc-macro2", "quote", @@ -424,9 +424,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags", ] @@ -447,7 +447,7 @@ dependencies = [ "endian-num", "env_logger", "fuser", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "libredox", "log", @@ -530,9 +530,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index ebd666715e..2974b6c6ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,14 +39,14 @@ endian-num = "0.1" getrandom = { version = "0.2.5", optional = true } libc = "0.2" log = { version = "0.4.14", default-features = false, optional = true} -redox_syscall = { version = "0.5" } +redox_syscall = { version = "0.5.12" } range-tree = { version = "0.1", optional = true } seahash = { version = "4.1.0", default-features = false } termion = { version = "4", optional = true } uuid = { version = "1.4", default-features = false } redox-path = "0.3.0" libredox = { version = "0.1.3", optional = true } -redox-scheme = { version = "0.2.1", optional = true } +redox-scheme = { version = "0.6.2", optional = true } [features] default = ["std", "log"] diff --git a/src/mount/redox/mod.rs b/src/mount/redox/mod.rs index 611201b021..d8050b8f5d 100644 --- a/src/mount/redox/mod.rs +++ b/src/mount/redox/mod.rs @@ -1,4 +1,4 @@ -use redox_scheme::{RequestKind, SignalBehavior, Socket, V2}; +use redox_scheme::{RequestKind, SignalBehavior, Socket}; use std::io; use std::path::Path; use std::sync::atomic::Ordering; @@ -17,7 +17,7 @@ where F: FnOnce(&Path) -> T, { let mountpoint = mountpoint.as_ref(); - let socket = Socket::::create(&format!("{}", mountpoint.display()))?; + let socket = Socket::create(&format!("{}", mountpoint.display()))?; let mounted_path = format!("/scheme/{}", mountpoint.display()); let res = callback(Path::new(&mounted_path)); @@ -36,7 +36,7 @@ where } } }; - let response = req.handle_scheme_mut(&mut scheme); + let response = req.handle_sync(&mut scheme); if !socket.write_response(response, SignalBehavior::Restart)? { break; diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs index bf556e7638..58f282944e 100644 --- a/src/mount/redox/resource.rs +++ b/src/mount/redox/resource.rs @@ -6,7 +6,8 @@ use libredox::call::MmapArgs; use range_tree::RangeTree; use syscall::data::{Stat, TimeSpec}; -use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM}; +use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; +use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, ENOTDIR, EPERM}; use syscall::flag::{ MapFlags, F_GETFL, F_SETFL, MODE_PERM, O_ACCMODE, O_APPEND, O_RDONLY, O_RDWR, O_WRONLY, PROT_READ, PROT_WRITE, @@ -47,9 +48,9 @@ pub trait Resource { offset: u64, size: usize, tx: &mut Transaction, - ) -> Result; + ) -> Result<()>; - fn fchmod(&mut self, mode: u16, tx: &mut Transaction) -> Result { + fn fchmod(&mut self, mode: u16, tx: &mut Transaction) -> Result<()> { let mut node = tx.read_tree(self.node_ptr())?; if node.data().uid() == self.uid() || self.uid() == 0 { @@ -60,13 +61,13 @@ pub trait Resource { tx.sync_tree(node)?; } - Ok(0) + Ok(()) } else { Err(Error::new(EPERM)) } } - fn fchown(&mut self, uid: u32, gid: u32, tx: &mut Transaction) -> Result { + fn fchown(&mut self, uid: u32, gid: u32, tx: &mut Transaction) -> Result<()> { let mut node = tx.read_tree(self.node_ptr())?; let old_uid = node.data().uid(); @@ -92,7 +93,7 @@ pub trait Resource { tx.sync_tree(node)?; } - Ok(0) + Ok(()) } else { Err(Error::new(EPERM)) } @@ -102,7 +103,7 @@ pub trait Resource { fn path(&self) -> &str; - fn stat(&self, stat: &mut Stat, tx: &mut Transaction) -> Result { + fn stat(&self, stat: &mut Stat, tx: &mut Transaction) -> Result<()> { let node = tx.read_tree(self.node_ptr())?; let ctime = node.data().ctime(); @@ -125,21 +126,33 @@ pub trait Resource { ..Default::default() }; - Ok(0) + Ok(()) } - fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction) -> Result; + fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction) -> Result<()>; - fn truncate(&mut self, len: usize, tx: &mut Transaction) -> Result; + fn truncate(&mut self, len: u64, tx: &mut Transaction) -> Result<()>; - fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction) -> Result; + fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction) -> Result<()>; + + fn getdents<'buf>( + &mut self, + buf: DirentBuf<&'buf mut [u8]>, + opaque_offset: u64, + tx: &mut Transaction, + ) -> Result>; +} + +pub struct Entry { + pub node_ptr: TreePtr, + pub name: String, } pub struct DirResource { path: String, parent_ptr_opt: Option>, node_ptr: TreePtr, - data: Option>, + data: Option>, uid: u32, } @@ -148,7 +161,7 @@ impl DirResource { path: String, parent_ptr_opt: Option>, node_ptr: TreePtr, - data: Option>, + data: Option>, uid: u32, ) -> DirResource { DirResource { @@ -178,16 +191,8 @@ impl Resource for DirResource { self.path = path.to_string(); } - fn read(&mut self, buf: &mut [u8], offset: u64, _tx: &mut Transaction) -> Result { - let data = self.data.as_ref().ok_or(Error::new(EISDIR))?; - let src = usize::try_from(offset) - .ok() - .and_then(|o| data.get(o..)) - .unwrap_or(&[]); - - let byte_count = core::cmp::min(src.len(), buf.len()); - buf[..byte_count].copy_from_slice(&src[..byte_count]); - Ok(byte_count) + fn read(&mut self, _buf: &mut [u8], _offset: u64, _tx: &mut Transaction) -> Result { + Err(Error::new(EISDIR)) } fn write(&mut self, _buf: &[u8], _offset: u64, _tx: &mut Transaction) -> Result { @@ -214,7 +219,7 @@ impl Resource for DirResource { _offset: u64, _size: usize, _tx: &mut Transaction, - ) -> Result { + ) -> Result<()> { Err(Error::new(EBADF)) } @@ -226,17 +231,46 @@ impl Resource for DirResource { &self.path } - fn sync(&mut self, _fmaps: &mut Fmaps, _tx: &mut Transaction) -> Result { + fn sync(&mut self, _fmaps: &mut Fmaps, _tx: &mut Transaction) -> Result<()> { Err(Error::new(EBADF)) } - fn truncate(&mut self, _len: usize, _tx: &mut Transaction) -> Result { + fn truncate(&mut self, _len: u64, _tx: &mut Transaction) -> Result<()> { Err(Error::new(EBADF)) } - fn utimens(&mut self, _times: &[TimeSpec], _tx: &mut Transaction) -> Result { + fn utimens(&mut self, _times: &[TimeSpec], _tx: &mut Transaction) -> Result<()> { Err(Error::new(EBADF)) } + + fn getdents<'buf>( + &mut self, + mut buf: DirentBuf<&'buf mut [u8]>, + opaque_offset: u64, + tx: &mut Transaction, + ) -> Result> { + match &self.data { + Some(data) => { + for (idx, entry) in data.iter().enumerate().skip(opaque_offset as usize) { + let child = tx.read_tree(entry.node_ptr)?; + buf.entry(DirEntry { + inode: child.id() as u64, + next_opaque_id: idx as u64 + 1, + name: &entry.name, + kind: match child.data().mode() & Node::MODE_TYPE { + Node::MODE_DIR => DirentKind::Directory, + Node::MODE_FILE => DirentKind::Regular, + Node::MODE_SYMLINK => DirentKind::Symlink, + //TODO: more types? + _ => DirentKind::Unspecified, + }, + })?; + } + Ok(buf) + } + None => Err(Error::new(EBADF)), + } + } } #[derive(Debug)] @@ -504,7 +538,7 @@ impl Resource for FileResource { offset: u64, size: usize, tx: &mut Transaction, - ) -> Result { + ) -> Result<()> { let fmap_info = fmaps .get_mut(&self.node_ptr.id()) .ok_or(Error::new(EBADFD))?; @@ -536,7 +570,7 @@ impl Resource for FileResource { } //dbg!(&self.fmaps); - Ok(0) + Ok(()) } fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { @@ -554,7 +588,7 @@ impl Resource for FileResource { &self.path } - fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction) -> Result { + fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction) -> Result<()> { if let Some(fmap_info) = fmaps.get_mut(&self.node_ptr.id()) { for (range, fmap) in fmap_info.ranges.iter_mut() { unsafe { @@ -569,25 +603,20 @@ impl Resource for FileResource { } } - Ok(0) + Ok(()) } - fn truncate(&mut self, len: usize, tx: &mut Transaction) -> Result { + fn truncate(&mut self, len: u64, tx: &mut Transaction) -> Result<()> { if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_WRONLY { let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - tx.truncate_node( - self.node_ptr, - len as u64, - mtime.as_secs(), - mtime.subsec_nanos(), - )?; - Ok(0) + tx.truncate_node(self.node_ptr, len, mtime.as_secs(), mtime.subsec_nanos())?; + Ok(()) } else { Err(Error::new(EBADF)) } } - fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction) -> Result { + fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction) -> Result<()> { let mut node = tx.read_tree(self.node_ptr)?; if node.data().uid() == self.uid || self.uid == 0 { @@ -612,11 +641,20 @@ impl Resource for FileResource { tx.sync_tree(node)?; } } - Ok(0) + Ok(()) } else { Err(Error::new(EPERM)) } } + + fn getdents<'buf>( + &mut self, + _buf: DirentBuf<&'buf mut [u8]>, + _opaque_offset: u64, + _tx: &mut Transaction, + ) -> Result> { + Err(Error::new(ENOTDIR)) + } } impl Drop for FileResource { diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs index f64f58d03b..a53e0e4c8e 100644 --- a/src/mount/redox/scheme.rs +++ b/src/mount/redox/scheme.rs @@ -3,8 +3,9 @@ use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; -use redox_scheme::{CallerCtx, OpenResult, SchemeMut}; +use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult}; use syscall::data::{Stat, StatVfs, TimeSpec}; +use syscall::dirent::DirentBuf; use syscall::error::{ Error, Result, EACCES, EBADF, EBUSY, EEXIST, EINVAL, EISDIR, ELOOP, ENOENT, ENOTDIR, ENOTEMPTY, EPERM, EXDEV, @@ -14,7 +15,7 @@ use syscall::flag::{ O_STAT, O_SYMLINK, O_TRUNC, O_WRONLY, }; use syscall::schemev2::NewFdFlags; -use syscall::{MunmapFlags, EBADFD}; +use syscall::MunmapFlags; use redox_path::{ canonicalize_to_standard, canonicalize_using_cwd, canonicalize_using_scheme, scheme_path, @@ -23,7 +24,7 @@ use redox_path::{ use crate::{Disk, FileSystem, Node, Transaction, TreeData, TreePtr, BLOCK_SIZE}; -use super::resource::{DirResource, FileResource, Resource}; +use super::resource::{DirResource, Entry, FileResource, Resource}; pub struct FileScheme { name: String, @@ -164,8 +165,8 @@ fn dirname(path: &str) -> Option { canonicalize_using_cwd(Some(path), "..") } -impl SchemeMut for FileScheme { - fn xopen(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result { +impl SchemeSync for FileScheme { + fn open(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result { let CallerCtx { uid, gid, .. } = *ctx; let path = url.trim_matches('/'); @@ -196,10 +197,10 @@ impl SchemeMut for FileScheme { let mut data = Vec::new(); for child in children.iter() { if let Some(child_name) = child.name() { - if !data.is_empty() { - data.push(b'\n'); - } - data.extend_from_slice(&child_name.as_bytes()); + data.push(Entry { + node_ptr: child.node_ptr(), + name: child_name.to_string(), + }); } } @@ -240,7 +241,7 @@ impl SchemeMut for FileScheme { &mut resolve_nodes, ) })?; - return self.xopen(&resolved, flags, ctx); + return self.open(&resolved, flags, ctx); } else if !node.data().is_symlink() && flags & O_SYMLINK == O_SYMLINK { return Err(Error::new(EINVAL)); } else { @@ -370,8 +371,10 @@ impl SchemeMut for FileScheme { }) } - fn rmdir(&mut self, url: &str, uid: u32, gid: u32) -> Result { + fn rmdir(&mut self, url: &str, ctx: &CallerCtx) -> Result<()> { let path = url.trim_matches('/'); + let uid = ctx.uid; + let gid = ctx.gid; // println!("Rmdir '{}'", path); @@ -401,15 +404,17 @@ impl SchemeMut for FileScheme { } tx.remove_node(parent.ptr(), &child_name, Node::MODE_DIR) - .and(Ok(0)) + .and(Ok(())) } else { Err(Error::new(ENOTDIR)) } }) } - fn unlink(&mut self, url: &str, uid: u32, gid: u32) -> Result { + fn unlink(&mut self, url: &str, ctx: &CallerCtx) -> Result<()> { let path = url.trim_matches('/'); + let uid = ctx.uid; + let gid = ctx.gid; // println!("Unlink '{}'", path); @@ -440,10 +445,10 @@ impl SchemeMut for FileScheme { if child.data().is_symlink() { tx.remove_node(parent.ptr(), &child_name, Node::MODE_SYMLINK) - .and(Ok(0)) + .and(Ok(())) } else { tx.remove_node(parent.ptr(), &child_name, Node::MODE_FILE) - .and(Ok(0)) + .and(Ok(())) } } else { Err(Error::new(EISDIR)) @@ -452,25 +457,39 @@ impl SchemeMut for FileScheme { } /* Resource operations */ - fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result { + fn read( + &mut self, + id: usize, + buf: &mut [u8], + offset: u64, + _fcntl_flags: u32, + _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))?; self.fs.tx(|tx| file.read(buf, offset, tx)) } - fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result { + fn write( + &mut self, + id: usize, + buf: &[u8], + offset: u64, + _fcntl_flags: u32, + _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))?; self.fs.tx(|tx| file.write(buf, offset, tx)) } - fn fsize(&mut self, id: usize) -> Result { + 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))?; self.fs.tx(|tx| file.fsize(tx)) } - fn fchmod(&mut self, id: usize, mode: u16) -> Result { + fn fchmod(&mut self, id: usize, mode: u16, _ctx: &CallerCtx) -> Result<()> { if let Some(file) = self.files.get_mut(&id) { self.fs.tx(|tx| file.fchmod(mode, tx)) } else { @@ -478,15 +497,15 @@ impl SchemeMut for FileScheme { } } - fn fchown(&mut self, id: usize, uid: u32, gid: u32) -> Result { + fn fchown(&mut self, id: usize, new_uid: u32, new_gid: u32, _ctx: &CallerCtx) -> Result<()> { if let Some(file) = self.files.get_mut(&id) { - self.fs.tx(|tx| file.fchown(uid, gid, tx)) + self.fs.tx(|tx| file.fchown(new_uid, new_gid, tx)) } else { Err(Error::new(EBADF)) } } - fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { + fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result { if let Some(file) = self.files.get_mut(&id) { file.fcntl(cmd, arg) } else { @@ -494,7 +513,7 @@ impl SchemeMut for FileScheme { } } - fn fevent(&mut self, id: usize, _flags: EventFlags) -> Result { + 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 Err(Error::new(EPERM)) @@ -503,7 +522,7 @@ impl SchemeMut for FileScheme { } } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + 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) { let name = self.name.as_bytes(); @@ -537,8 +556,110 @@ impl SchemeMut for FileScheme { } //TODO: this function has too much code, try to simplify it - fn frename(&mut self, id: usize, url: &str, uid: u32, gid: u32) -> Result { + fn flink(&mut self, id: usize, url: &str, ctx: &CallerCtx) -> Result { let new_path = url.trim_matches('/'); + let uid = ctx.uid; + let gid = ctx.gid; + + // println!("Flink {}, {} from {}, {}", id, new_path, uid, gid); + + if let Some(file) = self.files.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(); + } + } + 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.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); + return Err(Error::new(EACCES)); + } + + let mut new_nodes = Vec::new(); + let new_node_opt = + Self::path_nodes(scheme_name, tx, 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); + 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); + 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)?; + + 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)) + } + } + + //TODO: this function has too much code, try to simplify it + fn frename(&mut self, id: usize, url: &str, ctx: &CallerCtx) -> Result { + let new_path = url.trim_matches('/'); + let uid = ctx.uid; + let gid = ctx.gid; // println!("Frename {}, {} from {}, {}", id, new_path, uid, gid); @@ -634,7 +755,7 @@ impl SchemeMut for FileScheme { } } - fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { + 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) { self.fs.tx(|tx| file.stat(stat, tx)) @@ -643,20 +764,20 @@ impl SchemeMut for FileScheme { } } - fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs) -> Result { + fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, _ctx: &CallerCtx) -> Result<()> { if let Some(_file) = self.files.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(0) + Ok(()) } else { Err(Error::new(EBADF)) } } - fn fsync(&mut self, id: usize) -> Result { + 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 fmaps = &mut self.fmap; @@ -664,7 +785,7 @@ impl SchemeMut for FileScheme { self.fs.tx(|tx| file.sync(fmaps, tx)) } - fn ftruncate(&mut self, id: usize, len: usize) -> Result { + fn ftruncate(&mut self, id: usize, len: u64, _ctx: &CallerCtx) -> Result<()> { // println!("Ftruncate {}, {}", id, len); if let Some(file) = self.files.get_mut(&id) { self.fs.tx(|tx| file.truncate(len, tx)) @@ -673,7 +794,7 @@ impl SchemeMut for FileScheme { } } - fn futimens(&mut self, id: usize, times: &[TimeSpec]) -> Result { + 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) { self.fs.tx(|tx| file.utimens(times, tx)) @@ -682,27 +803,55 @@ impl SchemeMut for FileScheme { } } - fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result { + fn getdents<'buf>( + &mut self, + id: usize, + buf: DirentBuf<&'buf mut [u8]>, + opaque_offset: u64, + ) -> Result> { + if let Some(file) = self.files.get_mut(&id) { + self.fs.tx(|tx| file.getdents(buf, opaque_offset, tx)) + } else { + Err(Error::new(EBADF)) + } + } + + fn mmap_prep( + &mut self, + id: usize, + offset: u64, + size: usize, + flags: MapFlags, + _ctx: &CallerCtx, + ) -> Result { let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.fmap(fmaps, flags, size, offset, tx)) } #[allow(unused_variables)] - fn munmap(&mut self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result { + fn munmap( + &mut self, + id: usize, + offset: u64, + size: usize, + flags: MunmapFlags, + _ctx: &CallerCtx, + ) -> Result<()> { let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?; let fmaps = &mut self.fmap; self.fs.tx(|tx| file.funmap(fmaps, offset, size, tx)) } - fn close(&mut self, id: usize) -> Result { + fn on_close(&mut self, id: usize) { // println!("Close {}", id); - let file = self.files.remove(&id).ok_or(Error::new(EBADF))?; - let file_info = self - .fmap - .get_mut(&file.node_ptr().id()) - .ok_or(Error::new(EBADFD))?; + let Some(file) = self.files.remove(&id) else { + return; + }; + let Some(file_info) = self.fmap.get_mut(&file.node_ptr().id()) else { + return; + }; file_info.open_fds = file_info .open_fds @@ -711,7 +860,5 @@ impl SchemeMut for FileScheme { // TODO: If open_fds reaches zero and there are no hardlinks (directory entries) to any // particular inode, remove that inode here. - - Ok(0) } }