Update redox-scheme, implement flink and getdents

This commit is contained in:
Jeremy Soller
2025-05-03 13:27:33 -06:00
parent 940b027514
commit c403c1eb54
5 changed files with 283 additions and 98 deletions
Generated
+11 -11
View File
@@ -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",
+2 -2
View File
@@ -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"]
+3 -3
View File
@@ -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::<V2>::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;
+79 -41
View File
@@ -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<D: Disk> {
offset: u64,
size: usize,
tx: &mut Transaction<D>,
) -> Result<usize>;
) -> Result<()>;
fn fchmod(&mut self, mode: u16, tx: &mut Transaction<D>) -> Result<usize> {
fn fchmod(&mut self, mode: u16, tx: &mut Transaction<D>) -> 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<D: Disk> {
tx.sync_tree(node)?;
}
Ok(0)
Ok(())
} else {
Err(Error::new(EPERM))
}
}
fn fchown(&mut self, uid: u32, gid: u32, tx: &mut Transaction<D>) -> Result<usize> {
fn fchown(&mut self, uid: u32, gid: u32, tx: &mut Transaction<D>) -> Result<()> {
let mut node = tx.read_tree(self.node_ptr())?;
let old_uid = node.data().uid();
@@ -92,7 +93,7 @@ pub trait Resource<D: Disk> {
tx.sync_tree(node)?;
}
Ok(0)
Ok(())
} else {
Err(Error::new(EPERM))
}
@@ -102,7 +103,7 @@ pub trait Resource<D: Disk> {
fn path(&self) -> &str;
fn stat(&self, stat: &mut Stat, tx: &mut Transaction<D>) -> Result<usize> {
fn stat(&self, stat: &mut Stat, tx: &mut Transaction<D>) -> Result<()> {
let node = tx.read_tree(self.node_ptr())?;
let ctime = node.data().ctime();
@@ -125,21 +126,33 @@ pub trait Resource<D: Disk> {
..Default::default()
};
Ok(0)
Ok(())
}
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> Result<usize>;
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> Result<()>;
fn truncate(&mut self, len: usize, tx: &mut Transaction<D>) -> Result<usize>;
fn truncate(&mut self, len: u64, tx: &mut Transaction<D>) -> Result<()>;
fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction<D>) -> Result<usize>;
fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction<D>) -> Result<()>;
fn getdents<'buf>(
&mut self,
buf: DirentBuf<&'buf mut [u8]>,
opaque_offset: u64,
tx: &mut Transaction<D>,
) -> Result<DirentBuf<&'buf mut [u8]>>;
}
pub struct Entry {
pub node_ptr: TreePtr<Node>,
pub name: String,
}
pub struct DirResource {
path: String,
parent_ptr_opt: Option<TreePtr<Node>>,
node_ptr: TreePtr<Node>,
data: Option<Vec<u8>>,
data: Option<Vec<Entry>>,
uid: u32,
}
@@ -148,7 +161,7 @@ impl DirResource {
path: String,
parent_ptr_opt: Option<TreePtr<Node>>,
node_ptr: TreePtr<Node>,
data: Option<Vec<u8>>,
data: Option<Vec<Entry>>,
uid: u32,
) -> DirResource {
DirResource {
@@ -178,16 +191,8 @@ impl<D: Disk> Resource<D> for DirResource {
self.path = path.to_string();
}
fn read(&mut self, buf: &mut [u8], offset: u64, _tx: &mut Transaction<D>) -> Result<usize> {
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<D>) -> Result<usize> {
Err(Error::new(EISDIR))
}
fn write(&mut self, _buf: &[u8], _offset: u64, _tx: &mut Transaction<D>) -> Result<usize> {
@@ -214,7 +219,7 @@ impl<D: Disk> Resource<D> for DirResource {
_offset: u64,
_size: usize,
_tx: &mut Transaction<D>,
) -> Result<usize> {
) -> Result<()> {
Err(Error::new(EBADF))
}
@@ -226,17 +231,46 @@ impl<D: Disk> Resource<D> for DirResource {
&self.path
}
fn sync(&mut self, _fmaps: &mut Fmaps, _tx: &mut Transaction<D>) -> Result<usize> {
fn sync(&mut self, _fmaps: &mut Fmaps, _tx: &mut Transaction<D>) -> Result<()> {
Err(Error::new(EBADF))
}
fn truncate(&mut self, _len: usize, _tx: &mut Transaction<D>) -> Result<usize> {
fn truncate(&mut self, _len: u64, _tx: &mut Transaction<D>) -> Result<()> {
Err(Error::new(EBADF))
}
fn utimens(&mut self, _times: &[TimeSpec], _tx: &mut Transaction<D>) -> Result<usize> {
fn utimens(&mut self, _times: &[TimeSpec], _tx: &mut Transaction<D>) -> Result<()> {
Err(Error::new(EBADF))
}
fn getdents<'buf>(
&mut self,
mut buf: DirentBuf<&'buf mut [u8]>,
opaque_offset: u64,
tx: &mut Transaction<D>,
) -> Result<DirentBuf<&'buf mut [u8]>> {
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<D: Disk> Resource<D> for FileResource {
offset: u64,
size: usize,
tx: &mut Transaction<D>,
) -> Result<usize> {
) -> Result<()> {
let fmap_info = fmaps
.get_mut(&self.node_ptr.id())
.ok_or(Error::new(EBADFD))?;
@@ -536,7 +570,7 @@ impl<D: Disk> Resource<D> for FileResource {
}
//dbg!(&self.fmaps);
Ok(0)
Ok(())
}
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
@@ -554,7 +588,7 @@ impl<D: Disk> Resource<D> for FileResource {
&self.path
}
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> Result<usize> {
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> 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<D: Disk> Resource<D> for FileResource {
}
}
Ok(0)
Ok(())
}
fn truncate(&mut self, len: usize, tx: &mut Transaction<D>) -> Result<usize> {
fn truncate(&mut self, len: u64, tx: &mut Transaction<D>) -> 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<D>) -> Result<usize> {
fn utimens(&mut self, times: &[TimeSpec], tx: &mut Transaction<D>) -> Result<()> {
let mut node = tx.read_tree(self.node_ptr)?;
if node.data().uid() == self.uid || self.uid == 0 {
@@ -612,11 +641,20 @@ impl<D: Disk> Resource<D> 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<D>,
) -> Result<DirentBuf<&'buf mut [u8]>> {
Err(Error::new(ENOTDIR))
}
}
impl Drop for FileResource {
+188 -41
View File
@@ -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<D: Disk> {
name: String,
@@ -164,8 +165,8 @@ fn dirname(path: &str) -> Option<String> {
canonicalize_using_cwd(Some(path), "..")
}
impl<D: Disk> SchemeMut for FileScheme<D> {
fn xopen(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
impl<D: Disk> SchemeSync for FileScheme<D> {
fn open(&mut self, url: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
let CallerCtx { uid, gid, .. } = *ctx;
let path = url.trim_matches('/');
@@ -196,10 +197,10 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
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<D: Disk> SchemeMut for FileScheme<D> {
&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<D: Disk> SchemeMut for FileScheme<D> {
})
}
fn rmdir(&mut self, url: &str, uid: u32, gid: u32) -> Result<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
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<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
/* Resource operations */
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<usize> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_fcntl_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
// 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<usize> {
fn write(
&mut self,
id: usize,
buf: &[u8],
offset: u64,
_fcntl_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
// 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<u64> {
fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result<u64> {
// 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<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn fchown(&mut self, id: usize, uid: u32, gid: u32) -> Result<usize> {
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<usize> {
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result<usize> {
if let Some(file) = self.files.get_mut(&id) {
file.fcntl(cmd, arg)
} else {
@@ -494,7 +513,7 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn fevent(&mut self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
fn fevent(&mut self, id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result<EventFlags> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
// 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<D: Disk> SchemeMut for FileScheme<D> {
}
//TODO: this function has too much code, try to simplify it
fn frename(&mut self, id: usize, url: &str, uid: u32, gid: u32) -> Result<usize> {
fn flink(&mut self, id: usize, url: &str, ctx: &CallerCtx) -> Result<usize> {
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<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs) -> Result<usize> {
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<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
self.fs.tx(|tx| file.sync(fmaps, tx))
}
fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn futimens(&mut self, id: usize, times: &[TimeSpec]) -> Result<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
}
}
fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<usize> {
fn getdents<'buf>(
&mut self,
id: usize,
buf: DirentBuf<&'buf mut [u8]>,
opaque_offset: u64,
) -> Result<DirentBuf<&'buf mut [u8]>> {
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<usize> {
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<usize> {
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<usize> {
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<D: Disk> SchemeMut for FileScheme<D> {
// TODO: If open_fds reaches zero and there are no hardlinks (directory entries) to any
// particular inode, remove that inode here.
Ok(0)
}
}