proc: reimplement OpenOptions
This commit is contained in:
parent
0bdc30afdc
commit
d3e3d3add8
@ -8,7 +8,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||
vfs = { path = "lib/vfs" }
|
||||
vfs-macros = { path = "lib/vfs/macros" }
|
||||
|
||||
aarch64-cpu = "9.3.1"
|
||||
atomic_enum = "0.2.0"
|
||||
|
@ -7,5 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||
vfs-macros = { path = "macros" }
|
||||
bitflags = "2.3.3"
|
||||
|
@ -1,16 +0,0 @@
|
||||
[package]
|
||||
name = "vfs-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
proc-macro-crate = "1.3.1"
|
||||
proc-macro2 = "1.0.66"
|
||||
quote = "1.0.31"
|
||||
syn = { version = "2.0.26", features = ["full"] }
|
@ -1,55 +0,0 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Ident, Span};
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{parse_macro_input, ImplItem, ItemImpl};
|
||||
|
||||
mod vnode_impl;
|
||||
use vnode_impl::IMPLS;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn auto_vnode_impl(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let current_crate = crate_name("vfs").unwrap();
|
||||
|
||||
let vfs_crate = match current_crate {
|
||||
FoundCrate::Itself => Ident::new("crate", Span::call_site()),
|
||||
FoundCrate::Name(name) => Ident::new(&name, Span::call_site()),
|
||||
};
|
||||
let vfs_crate = quote! { #vfs_crate };
|
||||
|
||||
let mut impl_item = parse_macro_input!(input as ItemImpl);
|
||||
let behavior = if attr.is_empty() {
|
||||
"unimplemented".to_string()
|
||||
} else {
|
||||
parse_macro_input!(attr as Ident).to_string()
|
||||
};
|
||||
let behavior = match behavior.as_str() {
|
||||
"unimplemented" => quote! { unimplemented!() },
|
||||
"panic" => quote! { panic!() },
|
||||
"error" => quote! { Err(yggdrasil_abi::error::Error::NotImplemented) },
|
||||
_ => panic!("Unknown #[auto_vnode_impl] behavior: {:?}", behavior),
|
||||
};
|
||||
|
||||
let mut missing_impls: HashSet<&str> = HashSet::from_iter(IMPLS.keys().copied());
|
||||
|
||||
for item in &impl_item.items {
|
||||
match item {
|
||||
ImplItem::Fn(f) => {
|
||||
let name = &f.sig.ident.to_string();
|
||||
missing_impls.remove(name.as_str());
|
||||
}
|
||||
_ => panic!("Unexpected item in Vnode impl"),
|
||||
}
|
||||
}
|
||||
|
||||
for &item in &missing_impls {
|
||||
let f = IMPLS.get(item).unwrap();
|
||||
let fn_impl = f(&vfs_crate, &behavior);
|
||||
|
||||
impl_item.items.push(ImplItem::Verbatim(fn_impl));
|
||||
}
|
||||
|
||||
impl_item.to_token_stream().into()
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use proc_macro2::TokenStream as TS2;
|
||||
use quote::quote;
|
||||
|
||||
fn impl_open(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn open(&mut self, _node: &#vfs::VnodeRef, _opts: yggdrasil_abi::io::OpenFlags)
|
||||
-> Result<u64, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_close(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn close(&mut self, _node: &#vfs::VnodeRef) -> Result<(), Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_create(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn create(&mut self, _at: &#vfs::VnodeRef, _name: &str, _kind: #vfs::VnodeKind)
|
||||
-> Result<#vfs::VnodeRef, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_write(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn write(&mut self, _node: &#vfs::VnodeRef, _pos: u64, _data: &[u8])
|
||||
-> Result<usize, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_read(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn read(&mut self, _node: &#vfs::VnodeRef, _pos: u64, _data: &mut [u8])
|
||||
-> Result<usize, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref IMPLS: HashMap<&'static str, fn(&TS2, &TS2) -> TS2> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("open".into(), impl_open as _);
|
||||
m.insert("close".into(), impl_close as _);
|
||||
m.insert("create".into(), impl_create as _);
|
||||
m.insert("write".into(), impl_write as _);
|
||||
m.insert("read".into(), impl_read as _);
|
||||
m
|
||||
};
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
use vfs_macros::auto_vnode_impl;
|
||||
use yggdrasil_abi::{error::Error, io::OpenFlags};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
io::{FileMode, OpenOptions},
|
||||
};
|
||||
|
||||
use crate::{node::VnodeImpl, VnodeRef};
|
||||
|
||||
@ -18,9 +20,13 @@ impl CharDeviceWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_vnode_impl(error)]
|
||||
impl VnodeImpl for CharDeviceWrapper {
|
||||
fn open(&mut self, _node: &VnodeRef, _opts: OpenFlags) -> Result<u64, Error> {
|
||||
fn open(
|
||||
&mut self,
|
||||
_node: &VnodeRef,
|
||||
_opts: OpenOptions,
|
||||
_mode: FileMode,
|
||||
) -> Result<u64, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
use yggdrasil_abi::{error::Error, io::OpenFlags, path};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
io::{FileMode, OpenOptions},
|
||||
path,
|
||||
};
|
||||
|
||||
use crate::{file::FileRef, node::VnodeRef};
|
||||
|
||||
@ -107,7 +111,8 @@ impl IoContext {
|
||||
&self,
|
||||
at: Option<VnodeRef>,
|
||||
path: &str,
|
||||
opts: OpenFlags,
|
||||
opts: OpenOptions,
|
||||
mode: FileMode,
|
||||
) -> Result<FileRef, Error> {
|
||||
let node = match self.find(at.clone(), path, true, true) {
|
||||
Err(Error::DoesNotExist) => {
|
||||
@ -117,7 +122,7 @@ impl IoContext {
|
||||
o => o,
|
||||
}?;
|
||||
|
||||
node.open(opts)
|
||||
node.open(opts, mode)
|
||||
}
|
||||
|
||||
pub fn root(&self) -> &VnodeRef {
|
||||
|
@ -9,7 +9,10 @@ use alloc::{
|
||||
string::String,
|
||||
vec::Vec,
|
||||
};
|
||||
use yggdrasil_abi::{error::Error, io::OpenFlags};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
io::{FileMode, OpenOptions},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
file::{File, FileFlags, FileRef},
|
||||
@ -46,16 +49,33 @@ pub struct Vnode {
|
||||
}
|
||||
|
||||
pub trait VnodeImpl {
|
||||
fn create(&mut self, at: &VnodeRef, name: &str, kind: VnodeKind) -> Result<VnodeRef, Error>;
|
||||
fn create(&mut self, _at: &VnodeRef, _name: &str, _kind: VnodeKind) -> Result<VnodeRef, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn open(&mut self, node: &VnodeRef, opts: OpenFlags) -> Result<u64, Error>;
|
||||
fn close(&mut self, node: &VnodeRef) -> Result<(), Error>;
|
||||
fn open(
|
||||
&mut self,
|
||||
_node: &VnodeRef,
|
||||
_opts: OpenOptions,
|
||||
_mode: FileMode,
|
||||
) -> Result<u64, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn read(&mut self, node: &VnodeRef, pos: u64, data: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write(&mut self, node: &VnodeRef, pos: u64, data: &[u8]) -> Result<usize, Error>;
|
||||
fn close(&mut self, _node: &VnodeRef) -> Result<(), Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn read(&mut self, _node: &VnodeRef, _pos: u64, _data: &mut [u8]) -> Result<usize, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn write(&mut self, _node: &VnodeRef, _pos: u64, _data: &[u8]) -> Result<usize, Error> {
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
|
||||
fn size(&mut self, _node: &VnodeRef) -> Result<u64, Error> {
|
||||
unimplemented!()
|
||||
Err(Error::NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,13 +225,13 @@ impl Vnode {
|
||||
}
|
||||
|
||||
// Node operations
|
||||
pub fn open(self: &VnodeRef, flags: OpenFlags) -> Result<FileRef, Error> {
|
||||
pub fn open(self: &VnodeRef, flags: OpenOptions, mode: FileMode) -> Result<FileRef, Error> {
|
||||
let mut open_flags = FileFlags::empty();
|
||||
|
||||
if flags.is_read() {
|
||||
if flags.contains(OpenOptions::READ) {
|
||||
open_flags |= FileFlags::READ;
|
||||
}
|
||||
if flags.is_write() {
|
||||
if flags.contains(OpenOptions::WRITE) {
|
||||
open_flags |= FileFlags::WRITE;
|
||||
}
|
||||
|
||||
@ -220,7 +240,7 @@ impl Vnode {
|
||||
}
|
||||
|
||||
if let Some(ref mut data) = *self.data() {
|
||||
let pos = data.open(self, flags)?;
|
||||
let pos = data.open(self, flags, mode)?;
|
||||
Ok(File::normal(self.clone(), pos, open_flags))
|
||||
} else {
|
||||
todo!()
|
||||
|
@ -1,8 +1,7 @@
|
||||
use abi::error::Error;
|
||||
use abi::{error::Error, io::FileMode};
|
||||
use alloc::{boxed::Box, rc::Rc};
|
||||
use vfs::{Filesystem, Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
use vfs_macros::auto_vnode_impl;
|
||||
use yggdrasil_abi::io::OpenFlags;
|
||||
use yggdrasil_abi::io::OpenOptions;
|
||||
|
||||
use crate::util::OneTimeInit;
|
||||
|
||||
@ -163,7 +162,6 @@ struct RegularInode {
|
||||
data: &'static [u8],
|
||||
}
|
||||
|
||||
#[auto_vnode_impl]
|
||||
impl VnodeImpl for DirInode {
|
||||
fn create(&mut self, _at: &VnodeRef, name: &str, kind: VnodeKind) -> Result<VnodeRef, Error> {
|
||||
let child = Vnode::new(name, kind);
|
||||
@ -176,10 +174,9 @@ impl VnodeImpl for DirInode {
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_vnode_impl]
|
||||
impl VnodeImpl for RegularInode {
|
||||
fn open(&mut self, node: &VnodeRef, opts: OpenFlags) -> Result<u64, Error> {
|
||||
if opts.is_write() {
|
||||
fn open(&mut self, node: &VnodeRef, opts: OpenOptions, _mode: FileMode) -> Result<u64, Error> {
|
||||
if opts.contains(OpenOptions::WRITE) {
|
||||
panic!("TODO: tarfs write");
|
||||
}
|
||||
|
||||
|
10
src/main.rs
10
src/main.rs
@ -17,11 +17,11 @@ extern crate yggdrasil_abi as abi;
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::{OpenFlags, RawFd},
|
||||
io::{FileMode, OpenOptions, RawFd},
|
||||
};
|
||||
use fs::{devfs, tar::TarFilesystem, INITRD_DATA};
|
||||
use task::process::Process;
|
||||
use vfs::{Filesystem, IoContext, Read, VnodeRef};
|
||||
use vfs::{Filesystem, IoContext, VnodeRef};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@ -66,13 +66,15 @@ pub fn kernel_main() {
|
||||
|
||||
let ioctx = IoContext::new(root);
|
||||
let node = ioctx.find(None, "/init", true, true).unwrap();
|
||||
let file = node.open(OpenFlags::new().read()).unwrap();
|
||||
let file = node.open(OpenOptions::READ, FileMode::empty()).unwrap();
|
||||
|
||||
{
|
||||
let user_init = proc::exec::load_elf(file, &["/init"]).unwrap();
|
||||
let mut io = user_init.io.lock();
|
||||
io.set_ioctx(ioctx);
|
||||
let stdout = tty_node.open(OpenFlags::new().write()).unwrap();
|
||||
let stdout = tty_node
|
||||
.open(OpenOptions::WRITE, FileMode::empty())
|
||||
.unwrap();
|
||||
let stderr = stdout.clone();
|
||||
|
||||
io.set_file(RawFd::STDOUT, stdout).unwrap();
|
||||
|
@ -3,7 +3,7 @@ use core::time::Duration;
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::{OpenFlags, RawFd},
|
||||
io::{FileMode, OpenOptions, RawFd},
|
||||
syscall::SyscallFunction,
|
||||
};
|
||||
use vfs::{Read, Write};
|
||||
@ -103,12 +103,13 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
}
|
||||
SyscallFunction::Open => {
|
||||
let path = arg_user_str(args[0] as usize, args[1] as usize)?;
|
||||
let opts = OpenFlags(args[2] as u32);
|
||||
let opts = OpenOptions::from(args[2] as u32);
|
||||
let mode = FileMode::from(args[3] as u32);
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let file = io.ioctx().open(None, path, opts)?;
|
||||
let file = io.ioctx().open(None, path, opts, mode)?;
|
||||
let fd = io.place_file(file)?;
|
||||
|
||||
Ok(fd.0 as usize)
|
||||
|
Loading…
x
Reference in New Issue
Block a user