fs: implement Seek syscall
This commit is contained in:
parent
ba3819ee8e
commit
461bfb2791
@ -198,8 +198,8 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::rc::Rc;
|
||||
use vfs::{Filesystem, IoContext, Read, Seek, SeekFrom, VnodeKind, Write};
|
||||
use yggdrasil_abi::io::{FileMode, OpenOptions};
|
||||
use vfs::{Filesystem, IoContext, Read, Seek, VnodeKind, Write};
|
||||
use yggdrasil_abi::io::{FileMode, OpenOptions, SeekFrom};
|
||||
|
||||
use crate::MemoryFilesystem;
|
||||
|
||||
|
@ -73,6 +73,13 @@ impl File {
|
||||
flags: FileFlags::READ,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn node(&self) -> Result<VnodeRef, Error> {
|
||||
match &self.inner {
|
||||
FileInner::Normal(inner) => Ok(inner.vnode.clone()),
|
||||
FileInner::Directory(inner) => Ok(inner.vnode.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for File {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use yggdrasil_abi::error::Error;
|
||||
use yggdrasil_abi::io::DirectoryEntry;
|
||||
use yggdrasil_abi::io::{DirectoryEntry, SeekFrom};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@ -29,13 +29,6 @@ pub use node::{Vnode, VnodeDump, VnodeImpl, VnodeKind, VnodeRef, VnodeWeak};
|
||||
|
||||
pub const DIR_POSITION_FROM_CACHE: u64 = u64::MAX;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SeekFrom {
|
||||
Start(u64),
|
||||
End(i64),
|
||||
Current(i64),
|
||||
}
|
||||
|
||||
pub trait Write {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize, Error>;
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ use elf::{
|
||||
endian::AnyEndian,
|
||||
ElfStream, ParseError,
|
||||
};
|
||||
use vfs::{FileRef, Read, Seek, SeekFrom};
|
||||
use yggdrasil_abi::error::Error;
|
||||
use vfs::{FileRef, Read, Seek};
|
||||
use yggdrasil_abi::{error::Error, io::SeekFrom};
|
||||
|
||||
use crate::mem::{
|
||||
phys::{self, PageUsage},
|
||||
|
@ -3,11 +3,11 @@ use core::{mem::MaybeUninit, time::Duration};
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::{DirectoryEntry, FileAttr, FileMode, OpenOptions, RawFd},
|
||||
io::{DirectoryEntry, FileAttr, FileMode, OpenOptions, RawFd, SeekFrom},
|
||||
syscall::SyscallFunction,
|
||||
};
|
||||
use alloc::rc::Rc;
|
||||
use vfs::{Read, ReadDirectory, VnodeKind, Write};
|
||||
use vfs::{Read, ReadDirectory, Seek, VnodeKind, VnodeRef, Write};
|
||||
use yggdrasil_abi::{
|
||||
error::SyscallResult,
|
||||
io::{MountOptions, UnmountOptions},
|
||||
@ -16,13 +16,37 @@ use yggdrasil_abi::{
|
||||
use crate::{
|
||||
fs,
|
||||
mem::table::{PageAttributes, VirtualMemoryManager},
|
||||
proc::wait,
|
||||
proc::{io::ProcessIo, wait},
|
||||
sync::IrqSafeSpinlockGuard,
|
||||
task::process::Process,
|
||||
};
|
||||
|
||||
mod arg;
|
||||
use arg::*;
|
||||
|
||||
fn run_with_io<T, F: FnOnce(IrqSafeSpinlockGuard<ProcessIo>) -> T>(f: F) -> T {
|
||||
let proc = Process::current();
|
||||
let io = proc.io.lock();
|
||||
|
||||
f(io)
|
||||
}
|
||||
|
||||
fn run_with_io_at<
|
||||
T,
|
||||
F: FnOnce(Option<VnodeRef>, IrqSafeSpinlockGuard<ProcessIo>) -> Result<T, Error>,
|
||||
>(
|
||||
at: Option<RawFd>,
|
||||
f: F,
|
||||
) -> Result<T, Error> {
|
||||
let proc = Process::current();
|
||||
let io = proc.io.lock();
|
||||
let at = at
|
||||
.map(|fd| io.file(fd).and_then(|f| f.borrow().node()))
|
||||
.transpose()?;
|
||||
|
||||
f(at, io)
|
||||
}
|
||||
|
||||
fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error> {
|
||||
match func {
|
||||
SyscallFunction::DebugTrace => {
|
||||
@ -84,92 +108,87 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
let fd = RawFd(args[0] as u32);
|
||||
let data = arg_buffer_ref(args[1] as _, args[2] as _)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let io = proc.io.lock();
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
run_with_io(|io| {
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
|
||||
file_borrow.write(data)
|
||||
file_borrow.write(data)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Read => {
|
||||
let fd = RawFd(args[0] as u32);
|
||||
let data = arg_buffer_mut(args[1] as _, args[2] as _)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let io = proc.io.lock();
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
run_with_io(|io| {
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
|
||||
file_borrow.read(data)
|
||||
file_borrow.read(data)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Open => {
|
||||
let path = arg_user_str(args[0] as usize, args[1] as usize)?;
|
||||
let opts = OpenOptions::from(args[2] as u32);
|
||||
let mode = FileMode::from(args[3] as u32);
|
||||
let at = arg_option_fd(args[0] as u32);
|
||||
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
|
||||
let opts = OpenOptions::from(args[3] as u32);
|
||||
let mode = FileMode::from(args[4] as u32);
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io_at(at, |at, mut io| {
|
||||
debugln!("run_with_io_at {:?}", at);
|
||||
let file = io.ioctx().open(at, path, opts, mode)?;
|
||||
let fd = io.place_file(file)?;
|
||||
|
||||
let file = io.ioctx().open(None, path, opts, mode)?;
|
||||
let fd = io.place_file(file)?;
|
||||
|
||||
Ok(fd.0 as usize)
|
||||
Ok(fd.0 as usize)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Close => {
|
||||
let fd = RawFd(args[0] as u32);
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
io.close_file(fd)?;
|
||||
Ok(0)
|
||||
run_with_io(|mut io| {
|
||||
io.close_file(fd)?;
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Mount => {
|
||||
let options = arg_user_ref::<MountOptions>(args[0] as usize)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io(|mut io| {
|
||||
let target_node = io.ioctx().find(None, options.target, true, false)?;
|
||||
if !target_node.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
|
||||
let target_node = io.ioctx().find(None, options.target, true, false)?;
|
||||
if !target_node.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
let fs_root = fs::create_filesystem(options)?;
|
||||
|
||||
let fs_root = fs::create_filesystem(options)?;
|
||||
target_node.mount(fs_root)?;
|
||||
|
||||
target_node.mount(fs_root)?;
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
Ok(0)
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Unmount => {
|
||||
let options = arg_user_ref::<UnmountOptions>(args[0] as usize)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io(|mut io| {
|
||||
let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?;
|
||||
mountpoint.unmount_target()?;
|
||||
|
||||
let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?;
|
||||
mountpoint.unmount_target()?;
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
Ok(0)
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::OpenDirectory => {
|
||||
let at = arg_option_fd(args[0] as u32);
|
||||
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io_at(at, |at, mut io| {
|
||||
let node = io.ioctx().find(at, path, true, true)?;
|
||||
let file = node.open_directory()?;
|
||||
let fd = io.place_file(file)?;
|
||||
|
||||
// TODO handle at
|
||||
assert!(at.is_none());
|
||||
|
||||
let node = io.ioctx().find(None, path, true, true)?;
|
||||
let file = node.open_directory()?;
|
||||
let fd = io.place_file(file)?;
|
||||
|
||||
Ok(fd.0 as usize)
|
||||
Ok(fd.0 as usize)
|
||||
})
|
||||
}
|
||||
SyscallFunction::ReadDirectory => {
|
||||
let fd = RawFd(args[0] as u32);
|
||||
@ -178,53 +197,45 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
args[2] as usize,
|
||||
)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let io = proc.io.lock();
|
||||
run_with_io(|io| {
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
|
||||
file_borrow.read_dir_entries(buffer)
|
||||
file_borrow.read_dir_entries(buffer)
|
||||
})
|
||||
}
|
||||
SyscallFunction::CreateDirectory => {
|
||||
let at = arg_option_fd(args[0] as u32);
|
||||
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
|
||||
let mode = FileMode::from(args[3] as u32);
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io_at(at, |at, mut io| {
|
||||
let (parent, name) = abi::path::split_right(path);
|
||||
let parent_node = io.ioctx().find(at, parent, true, true)?;
|
||||
parent_node.create(name, VnodeKind::Directory)?;
|
||||
|
||||
// TODO handle at
|
||||
assert!(at.is_none());
|
||||
|
||||
let (parent, name) = abi::path::split_right(path);
|
||||
let parent_node = io.ioctx().find(None, parent, true, true)?;
|
||||
parent_node.create(name, VnodeKind::Directory)?;
|
||||
|
||||
Ok(0)
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Remove => {
|
||||
let at = arg_option_fd(args[0] as u32);
|
||||
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
|
||||
let recurse = args[3] != 0;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io_at(at, |at, mut io| {
|
||||
let node = io.ioctx().find(at, path, false, false)?;
|
||||
|
||||
assert!(at.is_none());
|
||||
if node.is_root() || Rc::ptr_eq(io.ioctx().root(), &node) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
let node = io.ioctx().find(None, path, false, false)?;
|
||||
let (_, filename) = abi::path::split_right(path);
|
||||
let parent = node.parent();
|
||||
|
||||
if node.is_root() || Rc::ptr_eq(io.ioctx().root(), &node) {
|
||||
todo!();
|
||||
}
|
||||
parent.remove(node, recurse)?;
|
||||
|
||||
let (_, filename) = abi::path::split_right(path);
|
||||
let parent = node.parent();
|
||||
|
||||
parent.remove(node, recurse)?;
|
||||
|
||||
Ok(0)
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::GetMetadata => {
|
||||
let at = arg_option_fd(args[0] as u32);
|
||||
@ -232,17 +243,29 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
let buffer = arg_user_mut::<MaybeUninit<FileAttr>>(args[3] as usize)?;
|
||||
let follow = args[4] != 0;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
run_with_io_at(at, |at, mut io| {
|
||||
let node = if path.is_empty() {
|
||||
at.ok_or(Error::InvalidArgument)?
|
||||
} else {
|
||||
io.ioctx().find(None, path, follow, true)?
|
||||
};
|
||||
|
||||
assert!(at.is_none());
|
||||
let metadata = node.metadata()?;
|
||||
buffer.write(metadata);
|
||||
|
||||
let node = io.ioctx().find(None, path, follow, true)?;
|
||||
Ok(0)
|
||||
})
|
||||
}
|
||||
SyscallFunction::Seek => {
|
||||
let fd = RawFd(args[0] as u32);
|
||||
let pos = SeekFrom::from(args[1]);
|
||||
|
||||
let metadata = node.metadata()?;
|
||||
buffer.write(metadata);
|
||||
run_with_io(|io| {
|
||||
let file = io.file(fd)?;
|
||||
let mut file_borrow = file.borrow_mut();
|
||||
|
||||
Ok(0)
|
||||
file_borrow.seek(pos).map(|v| v as usize)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user