Update redox-scheme, implement flink and getdents
This commit is contained in:
Generated
+11
-11
@@ -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
@@ -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"]
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user