refactor: fix all warnings
This commit is contained in:
+161
-161
@@ -1,162 +1,162 @@
|
||||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
// extern crate proc_macro;
|
||||
// extern crate syn;
|
||||
// #[macro_use]
|
||||
// extern crate quote;
|
||||
//
|
||||
// use proc_macro::TokenStream;
|
||||
// use quote::ToTokens;
|
||||
// use std::collections::HashSet;
|
||||
// use syn::{parse_macro_input, ImplItem, ItemImpl, Ident};
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use std::collections::HashSet;
|
||||
use syn::{parse_macro_input, ImplItem, ItemImpl, Ident};
|
||||
|
||||
fn impl_inode_fn<T: ToTokens>(name: &str, behavior: T) -> ImplItem {
|
||||
// TODO somehow know if current crate is vfs or not?
|
||||
ImplItem::Verbatim(match name {
|
||||
"create" => quote! {
|
||||
fn create(&mut self, _at: VnodeRef, _name: &str, kind: VnodeKind) ->
|
||||
Result<VnodeRef, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"remove" => quote! {
|
||||
fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), libsys::error::Errno> {
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"lookup" => quote! {
|
||||
fn lookup(&mut self, _at: VnodeRef, _name: &str) ->
|
||||
Result<VnodeRef, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"stat" => quote! {
|
||||
fn stat(&mut self, _at: VnodeRef) ->
|
||||
Result<libsys::stat::Stat, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"truncate" => quote! {
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) ->
|
||||
Result<(), libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"size" => quote! {
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, libsys::error::Errno> {
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"read" => quote! {
|
||||
fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"write" => quote! {
|
||||
fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"open" => quote! {
|
||||
fn open(&mut self, _node: VnodeRef, _flags: libsys::stat::OpenFlags) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"close" => quote! {
|
||||
fn close(&mut self, _node: VnodeRef) -> Result<(), libsys::error::Errno> {
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"ioctl" => quote! {
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
_node: VnodeRef,
|
||||
_cmd: libsys::ioctl::IoctlCmd,
|
||||
_ptr: usize,
|
||||
_len: usize) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"is_ready" => quote! {
|
||||
fn is_ready(&mut self, _node: VnodeRef, _write: bool) ->
|
||||
Result<bool, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
"readdir" => quote! {
|
||||
fn readdir(
|
||||
&mut self,
|
||||
_node: VnodeRef,
|
||||
_pos: usize,
|
||||
_entries: &mut [libsys::stat::DirectoryEntry]
|
||||
) ->
|
||||
Result<usize, libsys::error::Errno>
|
||||
{
|
||||
#behavior
|
||||
}
|
||||
},
|
||||
_ => panic!("TODO implement {:?}", name),
|
||||
})
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn auto_inode(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut impl_item = parse_macro_input!(input as ItemImpl);
|
||||
let mut missing = HashSet::<String>::new();
|
||||
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(libsys::error::Errno::NotImplemented) },
|
||||
_ => panic!("Unknown #[auto_inode] behavior: {:?}", behavior)
|
||||
};
|
||||
|
||||
missing.insert("create".to_string());
|
||||
missing.insert("remove".to_string());
|
||||
missing.insert("lookup".to_string());
|
||||
missing.insert("open".to_string());
|
||||
missing.insert("close".to_string());
|
||||
missing.insert("truncate".to_string());
|
||||
missing.insert("read".to_string());
|
||||
missing.insert("write".to_string());
|
||||
missing.insert("stat".to_string());
|
||||
missing.insert("size".to_string());
|
||||
missing.insert("ioctl".to_string());
|
||||
missing.insert("is_ready".to_string());
|
||||
missing.insert("readdir".to_string());
|
||||
|
||||
for item in &impl_item.items {
|
||||
match item {
|
||||
ImplItem::Method(method) => {
|
||||
let name = &method.sig.ident.to_string();
|
||||
if missing.contains(name) {
|
||||
missing.remove(name);
|
||||
}
|
||||
}
|
||||
_ => panic!("Unexpected impl item"),
|
||||
}
|
||||
}
|
||||
|
||||
for item in &missing {
|
||||
impl_item
|
||||
.items
|
||||
.push(impl_inode_fn(item, behavior.clone()));
|
||||
}
|
||||
|
||||
impl_item.to_token_stream().into()
|
||||
}
|
||||
//fn impl_inode_fn<T: ToTokens>(name: &str, behavior: T) -> ImplItem {
|
||||
// // TODO somehow know if current crate is vfs or not?
|
||||
// ImplItem::Verbatim(match name {
|
||||
// "create" => quote! {
|
||||
// fn create(&mut self, _at: VnodeRef, _name: &str, kind: VnodeKind) ->
|
||||
// Result<VnodeRef, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "remove" => quote! {
|
||||
// fn remove(&mut self, _at: VnodeRef, _name: &str) -> Result<(), libsys::error::Errno> {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "lookup" => quote! {
|
||||
// fn lookup(&mut self, _at: VnodeRef, _name: &str) ->
|
||||
// Result<VnodeRef, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "stat" => quote! {
|
||||
// fn stat(&mut self, _at: VnodeRef) ->
|
||||
// Result<libsys::stat::Stat, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "truncate" => quote! {
|
||||
// fn truncate(&mut self, _node: VnodeRef, _size: usize) ->
|
||||
// Result<(), libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "size" => quote! {
|
||||
// fn size(&mut self, _node: VnodeRef) -> Result<usize, libsys::error::Errno> {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "read" => quote! {
|
||||
// fn read(&mut self, _node: VnodeRef, _pos: usize, _data: &mut [u8]) ->
|
||||
// Result<usize, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "write" => quote! {
|
||||
// fn write(&mut self, _node: VnodeRef, _pos: usize, _data: &[u8]) ->
|
||||
// Result<usize, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "open" => quote! {
|
||||
// fn open(&mut self, _node: VnodeRef, _flags: libsys::stat::OpenFlags) ->
|
||||
// Result<usize, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "close" => quote! {
|
||||
// fn close(&mut self, _node: VnodeRef) -> Result<(), libsys::error::Errno> {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "ioctl" => quote! {
|
||||
// fn ioctl(
|
||||
// &mut self,
|
||||
// _node: VnodeRef,
|
||||
// _cmd: libsys::ioctl::IoctlCmd,
|
||||
// _ptr: usize,
|
||||
// _len: usize) ->
|
||||
// Result<usize, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "is_ready" => quote! {
|
||||
// fn is_ready(&mut self, _node: VnodeRef, _write: bool) ->
|
||||
// Result<bool, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// "readdir" => quote! {
|
||||
// fn readdir(
|
||||
// &mut self,
|
||||
// _node: VnodeRef,
|
||||
// _pos: usize,
|
||||
// _entries: &mut [libsys::stat::DirectoryEntry]
|
||||
// ) ->
|
||||
// Result<usize, libsys::error::Errno>
|
||||
// {
|
||||
// #behavior
|
||||
// }
|
||||
// },
|
||||
// _ => panic!("TODO implement {:?}", name),
|
||||
// })
|
||||
//}
|
||||
//
|
||||
//#[proc_macro_attribute]
|
||||
//pub fn auto_inode(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
// let mut impl_item = parse_macro_input!(input as ItemImpl);
|
||||
// let mut missing = HashSet::<String>::new();
|
||||
// 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(libsys::error::Errno::NotImplemented) },
|
||||
// _ => panic!("Unknown #[auto_inode] behavior: {:?}", behavior)
|
||||
// };
|
||||
//
|
||||
// missing.insert("create".to_string());
|
||||
// missing.insert("remove".to_string());
|
||||
// missing.insert("lookup".to_string());
|
||||
// missing.insert("open".to_string());
|
||||
// missing.insert("close".to_string());
|
||||
// missing.insert("truncate".to_string());
|
||||
// missing.insert("read".to_string());
|
||||
// missing.insert("write".to_string());
|
||||
// missing.insert("stat".to_string());
|
||||
// missing.insert("size".to_string());
|
||||
// missing.insert("ioctl".to_string());
|
||||
// missing.insert("is_ready".to_string());
|
||||
// missing.insert("readdir".to_string());
|
||||
//
|
||||
// for item in &impl_item.items {
|
||||
// match item {
|
||||
// ImplItem::Method(method) => {
|
||||
// let name = &method.sig.ident.to_string();
|
||||
// if missing.contains(name) {
|
||||
// missing.remove(name);
|
||||
// }
|
||||
// }
|
||||
// _ => panic!("Unexpected impl item"),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for item in &missing {
|
||||
// impl_item
|
||||
// .items
|
||||
// .push(impl_inode_fn(item, behavior.clone()));
|
||||
// }
|
||||
//
|
||||
// impl_item.to_token_stream().into()
|
||||
//}
|
||||
|
||||
@@ -11,6 +11,9 @@ pub struct BlockRef<'a, A: BlockAllocator + Copy> {
|
||||
alloc: MaybeUninit<A>,
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait is unsafe to implement due to its direct memory management
|
||||
pub unsafe trait BlockAllocator {
|
||||
fn alloc(&self) -> *mut u8;
|
||||
/// # Safety
|
||||
|
||||
+9
-10
@@ -18,7 +18,6 @@ impl<A: BlockAllocator + Copy + 'static> VnodeDirectory for DirInode<A> {
|
||||
let data = match kind {
|
||||
VnodeCreateKind::Directory => VnodeData::Directory(RefCell::new(Some(Box::new(DirInode { alloc: self.alloc })))),
|
||||
VnodeCreateKind::File => VnodeData::File(RefCell::new(Some(Box::new(FileInode::new(Bvec::new(self.alloc)))))),
|
||||
_ => todo!()
|
||||
};
|
||||
Ok(Vnode::new(name, data, Vnode::SEEKABLE | Vnode::CACHE_READDIR))
|
||||
// match kind {
|
||||
@@ -38,9 +37,9 @@ impl<A: BlockAllocator + Copy + 'static> VnodeDirectory for DirInode<A> {
|
||||
/// Read directory entries into target buffer
|
||||
fn readdir(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
pos: usize,
|
||||
data: &mut [DirectoryEntry],
|
||||
_node: VnodeRef,
|
||||
_pos: usize,
|
||||
_data: &mut [DirectoryEntry],
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
@@ -59,21 +58,21 @@ impl<A: BlockAllocator + Copy + 'static> VnodeCommon for DirInode<A> {
|
||||
/// Performs filetype-specific request
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
_node: VnodeRef,
|
||||
_cmd: IoctlCmd,
|
||||
_ptr: usize,
|
||||
_len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Reports the size of this filesystem object in bytes
|
||||
fn size(&mut self, node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns `true` if node is ready for an operation
|
||||
fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result<bool, Errno> {
|
||||
fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result<bool, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -35,16 +35,16 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeCommon for FileInode<'a, A> {
|
||||
/// Performs filetype-specific request
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
_node: VnodeRef,
|
||||
_cmd: IoctlCmd,
|
||||
_ptr: usize,
|
||||
_len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns `true` if node is ready for an operation
|
||||
fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result<bool, Errno> {
|
||||
fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result<bool, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -6,9 +6,6 @@ extern crate alloc;
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate fs_macros;
|
||||
|
||||
use alloc::{boxed::Box, rc::Rc};
|
||||
use core::any::Any;
|
||||
use core::cell::{Ref, RefCell};
|
||||
@@ -69,11 +66,10 @@ impl<A: BlockAllocator + Copy + 'static> Ramfs<A> {
|
||||
VnodeData::Directory(RefCell::new(Some(Box::new(DirInode::new(self.alloc)))))
|
||||
}
|
||||
VnodeCreateKind::File => VnodeData::File(RefCell::new(None)),
|
||||
_ => todo!(),
|
||||
};
|
||||
let node = Vnode::new(name, data, Vnode::SEEKABLE | Vnode::CACHE_READDIR);
|
||||
node.props_mut().mode = tar.mode();
|
||||
node.set_fs(self.clone());
|
||||
node.set_fs(self);
|
||||
node
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
use libsys::{error::Errno, stat::FileMode};
|
||||
use vfs::{VnodeData, VnodeCreateKind};
|
||||
use vfs::VnodeCreateKind;
|
||||
|
||||
#[repr(packed)]
|
||||
#[allow(dead_code)]
|
||||
@@ -85,7 +85,6 @@ impl Tar {
|
||||
let t = match self.node_create_kind() {
|
||||
VnodeCreateKind::File => FileMode::S_IFREG,
|
||||
VnodeCreateKind::Directory => FileMode::S_IFDIR,
|
||||
_ => todo!()
|
||||
};
|
||||
FileMode::from_bits(from_octal(&self.mode) as u32).unwrap() | t
|
||||
}
|
||||
|
||||
+4
-7
@@ -128,13 +128,10 @@ impl Ioctx {
|
||||
|
||||
/// Changes current working directory of the process
|
||||
pub fn chdir(&mut self, path: &str) -> Result<(), Errno> {
|
||||
todo!()
|
||||
// let node = self.find(None, path, true)?;
|
||||
// if !node.is_directory() {
|
||||
// return Err(Errno::NotADirectory);
|
||||
// }
|
||||
// self.cwd = node;
|
||||
// Ok(())
|
||||
let node = self.find(None, path, true)?;
|
||||
let _dir = node.as_directory()?;
|
||||
self.cwd = node;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -13,6 +13,7 @@ use libsys::{
|
||||
pub type VnodeRef = Rc<Vnode>;
|
||||
pub type VnodeKind = Discriminant<VnodeData>;
|
||||
|
||||
/// Trait implemented by both regular files and directories
|
||||
pub trait VnodeCommon {
|
||||
/// Performs filetype-specific request
|
||||
fn ioctl(
|
||||
@@ -30,7 +31,7 @@ pub trait VnodeCommon {
|
||||
fn size(&mut self, node: VnodeRef) -> Result<usize, Errno>;
|
||||
|
||||
/// Returns `true` if node is ready for an operation
|
||||
fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result<bool, Errno>;
|
||||
fn ready(&mut self, node: VnodeRef, write: bool) -> Result<bool, Errno>;
|
||||
|
||||
/// Opens a vnode for access. Returns initial file position.
|
||||
fn open(&mut self, node: VnodeRef, opts: OpenFlags) -> Result<usize, Errno>;
|
||||
@@ -38,6 +39,7 @@ pub trait VnodeCommon {
|
||||
fn close(&mut self, node: VnodeRef) -> Result<(), Errno>;
|
||||
}
|
||||
|
||||
/// Regular file access interface
|
||||
pub trait VnodeFile: VnodeCommon {
|
||||
/// Changes file's underlying storage size
|
||||
fn truncate(&mut self, node: VnodeRef, size: usize) -> Result<(), Errno>;
|
||||
@@ -48,14 +50,18 @@ pub trait VnodeFile: VnodeCommon {
|
||||
fn write(&mut self, node: VnodeRef, pos: usize, data: &[u8]) -> Result<usize, Errno>;
|
||||
}
|
||||
|
||||
/// Directory access interface
|
||||
pub trait VnodeDirectory: VnodeCommon {
|
||||
/// Creates entry `name` of type `kind` in directory `at`
|
||||
fn create(
|
||||
&mut self,
|
||||
at: VnodeRef,
|
||||
name: &str,
|
||||
kind: VnodeCreateKind,
|
||||
) -> Result<VnodeRef, Errno>;
|
||||
/// Removes entry `name` for directory `at`
|
||||
fn remove(&mut self, at: VnodeRef, name: &str) -> Result<(), Errno>;
|
||||
/// Loads an entry `name` in directory `at` from filesystem
|
||||
fn lookup(&mut self, at: VnodeRef, name: &str) -> Result<VnodeRef, Errno>;
|
||||
|
||||
/// Read directory entries into target buffer
|
||||
@@ -91,15 +97,22 @@ pub struct VnodeProps {
|
||||
pub mode: FileMode,
|
||||
}
|
||||
|
||||
/// Specific node implementation data
|
||||
pub enum VnodeData {
|
||||
/// Directory node
|
||||
Directory(RefCell<Option<Box<dyn VnodeDirectory>>>),
|
||||
/// Regular file node
|
||||
File(RefCell<Option<Box<dyn VnodeFile>>>),
|
||||
/// Character device node
|
||||
Char(&'static dyn CharDevice)
|
||||
}
|
||||
|
||||
/// Node types for create() calls
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum VnodeCreateKind {
|
||||
/// Directory node
|
||||
Directory,
|
||||
/// Regular file node
|
||||
File,
|
||||
}
|
||||
|
||||
@@ -173,6 +186,7 @@ impl Vnode {
|
||||
*self.fs.borrow_mut() = Some(fs);
|
||||
}
|
||||
|
||||
/// Returns node's directory implementation data
|
||||
pub fn as_directory(&self) -> Result<&RefCell<Option<Box<dyn VnodeDirectory>>>, Errno> {
|
||||
match &self.data {
|
||||
VnodeData::Directory(data) => Ok(data),
|
||||
@@ -180,6 +194,7 @@ impl Vnode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns node's regular file implementation data
|
||||
pub fn as_file(&self) -> Result<&RefCell<Option<Box<dyn VnodeFile>>>, Errno> {
|
||||
match &self.data {
|
||||
VnodeData::File(data) => Ok(data),
|
||||
|
||||
@@ -83,7 +83,7 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! {
|
||||
// Enable MMU
|
||||
virt::enable().expect("Failed to initialize virtual memory");
|
||||
|
||||
let fdt = init_device_tree(fdt_base).expect("Device tree init failed");
|
||||
let _fdt = init_device_tree(fdt_base).expect("Device tree init failed");
|
||||
|
||||
// Most basic machine init: initialize proper debug output
|
||||
// physical memory
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::arch::{machine, intrin};
|
||||
use crate::debug::Level;
|
||||
use crate::dev::irq::{IntController, IrqContext};
|
||||
use crate::mem;
|
||||
use crate::proc::{sched, Process, Thread};
|
||||
use crate::proc::{sched, Thread};
|
||||
use crate::syscall;
|
||||
use cortex_a::registers::{ESR_EL1, FAR_EL1};
|
||||
use libsys::{abi::SystemCall, signal::Signal, error::Errno};
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
//! AArch64-specific assembly functions
|
||||
use core::arch::asm;
|
||||
|
||||
/// Disables delievery of IRQs
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: requires EL0
|
||||
#[inline(always)]
|
||||
pub unsafe fn irq_disable() {
|
||||
asm!("msr daifset, {bits}", bits = const 2, options(nomem, nostack, preserves_flags));
|
||||
}
|
||||
|
||||
/// Discards an entry related to `addr` from TLB cache
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: requires EL0
|
||||
#[inline(always)]
|
||||
pub unsafe fn flush_tlb_virt(addr: usize) {
|
||||
pub unsafe fn flush_tlb_virt(_addr: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Discards all entries related to `asid` from TLB cache
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Only safe to use for known [Process]es and their ASIDs
|
||||
// TODO non-portable
|
||||
#[inline(always)]
|
||||
pub unsafe fn flush_tlb_asid(asid: usize) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! aarch64 architecture implementation
|
||||
|
||||
use core::arch::asm;
|
||||
use cortex_a::registers::DAIF;
|
||||
use tock_registers::interfaces::{Readable, Writeable};
|
||||
|
||||
|
||||
@@ -8,13 +8,15 @@ use tock_registers::{
|
||||
|
||||
macro_rules! wrap_msr {
|
||||
($struct_name:ident, $name:ident, $reg:literal, $fields:tt) => {
|
||||
#[allow(missing_docs)]
|
||||
pub struct $struct_name;
|
||||
|
||||
register_bitfields! {
|
||||
u64,
|
||||
#[allow(missing_docs)]
|
||||
pub $name $fields
|
||||
}
|
||||
|
||||
pub struct $struct_name;
|
||||
|
||||
impl Readable for $struct_name {
|
||||
type T = u64;
|
||||
type R = $name::Register;
|
||||
@@ -41,11 +43,11 @@ macro_rules! wrap_msr {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub const $name: $struct_name = $struct_name;
|
||||
};
|
||||
}
|
||||
|
||||
/// EL1 Architectural Feature Access Control Register
|
||||
wrap_msr!(CpacrEl1, CPACR_EL1, "cpacr_el1", [
|
||||
/// Enable EL0 and EL1 SIMD/FP accesses to EL1
|
||||
FPEN OFFSET(20) NUMBITS(2) [
|
||||
|
||||
@@ -16,6 +16,7 @@ use libsys::{debug::TraceLevel, error::Errno};
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
|
||||
/// Currently active print level
|
||||
pub static LEVEL: Level = Level::Debug;
|
||||
|
||||
/// Kernel logging levels
|
||||
|
||||
+13
-19
@@ -1,25 +1,14 @@
|
||||
use crate::arch::machine::{self, IrqNumber};
|
||||
use crate::dev::{
|
||||
irq::{IntController, IntSource},
|
||||
serial::SerialDevice,
|
||||
tty::{CharRing, TtyDevice},
|
||||
Device,
|
||||
};
|
||||
use crate::mem::virt::DeviceMemoryIo;
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use libsys::{error::Errno, ioctl::IoctlCmd};
|
||||
//! Virtual (pseudo) device implemetation
|
||||
use crate::dev::Device;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
use libsys::{error::Errno, ioctl::IoctlCmd};
|
||||
use vfs::CharDevice;
|
||||
|
||||
/// Pseudorandom number generator device
|
||||
pub struct Random {
|
||||
state: AtomicU32
|
||||
state: AtomicU32,
|
||||
}
|
||||
/// Zero device
|
||||
pub struct Zero;
|
||||
|
||||
impl Device for Random {
|
||||
@@ -53,7 +42,6 @@ impl CharDevice for Random {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Device for Zero {
|
||||
fn name(&self) -> &'static str {
|
||||
"Zero device"
|
||||
@@ -84,10 +72,12 @@ impl CharDevice for Zero {
|
||||
}
|
||||
|
||||
impl Random {
|
||||
/// Initializes PRNG with a seed value
|
||||
pub fn set_state(&self, state: u32) {
|
||||
self.state.store(state, Ordering::Release);
|
||||
}
|
||||
|
||||
/// Returns a single pseudo-random value
|
||||
pub fn read_single(&self) -> u32 {
|
||||
let mut x = self.state.load(Ordering::Acquire);
|
||||
x ^= x << 13;
|
||||
@@ -98,5 +88,9 @@ impl Random {
|
||||
}
|
||||
}
|
||||
|
||||
pub static RANDOM: Random = Random { state: AtomicU32::new(0) };
|
||||
/// Pseudorandom number generator device
|
||||
pub static RANDOM: Random = Random {
|
||||
state: AtomicU32::new(0),
|
||||
};
|
||||
/// Zero device
|
||||
pub static ZERO: Zero = Zero;
|
||||
|
||||
+11
-6
@@ -1,10 +1,10 @@
|
||||
//! Device list pseudo-filesystem
|
||||
use crate::util::InitOnce;
|
||||
use alloc::boxed::Box;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use libsys::{stat::FileMode, error::Errno};
|
||||
use vfs::{CharDevice, Vnode, VnodeData, VnodeRef};
|
||||
use core::cell::RefCell;
|
||||
use vfs::CharDevice;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use libsys::{error::Errno, stat::FileMode};
|
||||
use vfs::{Vnode, VnodeData, VnodeRef};
|
||||
|
||||
/// Possible character device kinds
|
||||
#[derive(Debug)]
|
||||
@@ -17,7 +17,11 @@ static DEVFS_ROOT: InitOnce<VnodeRef> = InitOnce::new();
|
||||
|
||||
/// Initializes devfs
|
||||
pub fn init() {
|
||||
let node = Vnode::new("", VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT);
|
||||
let node = Vnode::new(
|
||||
"",
|
||||
VnodeData::Directory(RefCell::new(None)),
|
||||
Vnode::CACHE_READDIR | Vnode::CACHE_STAT,
|
||||
);
|
||||
// let node = Vnode::new("", VnodeKind::Directory, Vnode::CACHE_READDIR | Vnode::CACHE_STAT);
|
||||
node.props_mut().mode = FileMode::default_dir();
|
||||
DEVFS_ROOT.init(node);
|
||||
@@ -28,13 +32,14 @@ pub fn root() -> &'static VnodeRef {
|
||||
DEVFS_ROOT.get()
|
||||
}
|
||||
|
||||
/// Adds device `dev` to devfs with `name`
|
||||
pub fn add_named_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> {
|
||||
infoln!("Add char device: {}", name);
|
||||
|
||||
let node = Vnode::new(name, VnodeData::Char(dev), Vnode::CACHE_STAT);
|
||||
// let node = Vnode::new(name, VnodeKind::Char, Vnode::CACHE_STAT);
|
||||
// node.set_data(Box::new(CharDeviceWrapper::new(dev)));
|
||||
node.props_mut().mode = FileMode::from_bits(0o600).unwrap() | FileMode::S_IFCHR;
|
||||
node.props_mut().mode = FileMode::from_bits(0o600).unwrap() | FileMode::S_IFCHR;
|
||||
|
||||
DEVFS_ROOT.get().attach(node);
|
||||
|
||||
|
||||
+47
-27
@@ -1,17 +1,16 @@
|
||||
//! System control/info virtual filesystem
|
||||
use crate::debug::{self, Level};
|
||||
use crate::util::InitOnce;
|
||||
use alloc::boxed::Box;
|
||||
use core::cell::RefCell;
|
||||
use core::fmt::{self, Write};
|
||||
use core::str::FromStr;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use fs_macros::auto_inode;
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
stat::{FileMode, OpenFlags, Stat},
|
||||
ioctl::IoctlCmd,
|
||||
stat::{FileMode, OpenFlags, Stat},
|
||||
};
|
||||
use vfs::{CharDevice, Vnode, VnodeCommon, VnodeData, VnodeFile, VnodeRef};
|
||||
use vfs::{Vnode, VnodeCommon, VnodeData, VnodeFile, VnodeRef};
|
||||
|
||||
struct NodeData<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Errno>> {
|
||||
read_func: R,
|
||||
@@ -59,32 +58,33 @@ impl<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Err
|
||||
/// Performs filetype-specific request
|
||||
fn ioctl(
|
||||
&mut self,
|
||||
node: VnodeRef,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
_node: VnodeRef,
|
||||
_cmd: IoctlCmd,
|
||||
_ptr: usize,
|
||||
_len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Retrieves file status
|
||||
fn stat(&mut self, node: VnodeRef) -> Result<Stat, Errno> {
|
||||
fn stat(&mut self, _node: VnodeRef) -> Result<Stat, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Reports the size of this filesystem object in bytes
|
||||
fn size(&mut self, node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn size(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns `true` if node is ready for an operation
|
||||
fn is_ready(&mut self, node: VnodeRef, write: bool) -> Result<bool, Errno> {
|
||||
fn ready(&mut self, _node: VnodeRef, _write: bool) -> Result<bool, Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Errno>> VnodeFile
|
||||
for NodeData<R, W> {
|
||||
for NodeData<R, W>
|
||||
{
|
||||
fn read(&mut self, _node: VnodeRef, pos: usize, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
if pos != 0 {
|
||||
// TODO handle this
|
||||
@@ -101,10 +101,10 @@ impl<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Err
|
||||
(self.write_func)(data)
|
||||
}
|
||||
|
||||
fn truncate(&mut self, node: VnodeRef, size: usize) -> Result<(), Errno> {
|
||||
fn truncate(&mut self, _node: VnodeRef, _size: usize) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Errno>>
|
||||
NodeData<R, W>
|
||||
{
|
||||
@@ -117,7 +117,6 @@ impl<R: Fn(&mut [u8]) -> Result<usize, Errno>, W: Fn(&[u8]) -> Result<usize, Err
|
||||
}
|
||||
|
||||
static SYSFS_ROOT: InitOnce<VnodeRef> = InitOnce::new();
|
||||
static TEST_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// TODO subdirs
|
||||
fn add_generic_node<R, W>(parent: Option<VnodeRef>, name: &str, mode: FileMode, read: R, write: W)
|
||||
@@ -139,6 +138,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a node with and `read` and `write` operations
|
||||
pub fn add_read_write_node<R, W>(parent: Option<VnodeRef>, name: &str, read: R, write: W)
|
||||
where
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno> + 'static,
|
||||
@@ -153,6 +153,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
/// Adds `read`-only node
|
||||
pub fn add_read_node<R>(parent: Option<VnodeRef>, name: &str, read: R)
|
||||
where
|
||||
R: Fn(&mut [u8]) -> Result<usize, Errno> + 'static,
|
||||
@@ -166,8 +167,13 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a directory in sysfs structure
|
||||
pub fn add_directory(parent: Option<VnodeRef>, name: &str) -> Result<VnodeRef, Errno> {
|
||||
let node = Vnode::new(name, VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT);
|
||||
let node = Vnode::new(
|
||||
name,
|
||||
VnodeData::Directory(RefCell::new(None)),
|
||||
Vnode::CACHE_READDIR | Vnode::CACHE_STAT,
|
||||
);
|
||||
node.props_mut().mode = FileMode::from_bits(0o500).unwrap() | FileMode::S_IFDIR;
|
||||
|
||||
if let Some(parent) = parent {
|
||||
@@ -179,26 +185,39 @@ pub fn add_directory(parent: Option<VnodeRef>, name: &str) -> Result<VnodeRef, E
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
/// Returns sysfs root node reference
|
||||
pub fn root() -> &'static VnodeRef {
|
||||
SYSFS_ROOT.get()
|
||||
}
|
||||
|
||||
/// Sets up the sysfs tree
|
||||
pub fn init() {
|
||||
let node = Vnode::new("", VnodeData::Directory(RefCell::new(None)), Vnode::CACHE_READDIR | Vnode::CACHE_STAT);
|
||||
let node = Vnode::new(
|
||||
"",
|
||||
VnodeData::Directory(RefCell::new(None)),
|
||||
Vnode::CACHE_READDIR | Vnode::CACHE_STAT,
|
||||
);
|
||||
node.props_mut().mode = FileMode::default_dir();
|
||||
SYSFS_ROOT.init(node);
|
||||
|
||||
let debug_dir = add_directory(None, "debug").unwrap();
|
||||
|
||||
add_read_write_node(Some(debug_dir.clone()), "level", |buf| {
|
||||
let mut writer = BufferWriter::new(buf);
|
||||
write!(&mut writer, "{}\n", debug::LEVEL as u32).map_err(|_| Errno::InvalidArgument)?;
|
||||
Ok(writer.count())
|
||||
}, |buf| {
|
||||
let s = core::str::from_utf8(buf).map_err(|_| Errno::InvalidArgument)?;
|
||||
let value = u32::from_str(s).map_err(|_| Errno::InvalidArgument).and_then(Level::try_from)?;
|
||||
todo!()
|
||||
});
|
||||
add_read_write_node(
|
||||
Some(debug_dir),
|
||||
"level",
|
||||
|buf| {
|
||||
let mut writer = BufferWriter::new(buf);
|
||||
writeln!(&mut writer, "{}", debug::LEVEL as u32).map_err(|_| Errno::InvalidArgument)?;
|
||||
Ok(writer.count())
|
||||
},
|
||||
|buf| {
|
||||
let s = core::str::from_utf8(buf).map_err(|_| Errno::InvalidArgument)?;
|
||||
let _value = u32::from_str(s)
|
||||
.map_err(|_| Errno::InvalidArgument)
|
||||
.and_then(Level::try_from)?;
|
||||
todo!()
|
||||
},
|
||||
);
|
||||
|
||||
add_read_node(None, "uptime", |buf| {
|
||||
use crate::arch::machine;
|
||||
@@ -206,7 +225,8 @@ pub fn init() {
|
||||
|
||||
let mut writer = BufferWriter::new(buf);
|
||||
let time = machine::local_timer().timestamp()?;
|
||||
write!(&mut writer, "{} {}\n", time.as_secs(), time.subsec_nanos()).map_err(|_| Errno::InvalidArgument)?;
|
||||
writeln!(&mut writer, "{} {}", time.as_secs(), time.subsec_nanos())
|
||||
.map_err(|_| Errno::InvalidArgument)?;
|
||||
Ok(writer.count())
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ pub mod sync;
|
||||
pub mod syscall;
|
||||
pub mod util;
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
||||
unsafe {
|
||||
|
||||
@@ -28,6 +28,7 @@ pub fn kernel_end_phys() -> usize {
|
||||
}
|
||||
|
||||
// TODO cross-platform variant
|
||||
/// Returns `true` if `virt` address is accessible for requested operation
|
||||
#[inline(always)]
|
||||
pub fn is_el0_accessible(virt: usize, write: bool) -> bool {
|
||||
use core::arch::asm;
|
||||
|
||||
@@ -4,6 +4,9 @@ use crate::sync::IrqSafeSpinLock;
|
||||
use core::mem;
|
||||
use libsys::{error::Errno, mem::memcpy};
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe to implement because of direct memory manipulation
|
||||
pub unsafe trait Manager {
|
||||
fn alloc_page(&mut self, pu: PageUsage) -> Result<usize, Errno>;
|
||||
fn alloc_contiguous_pages(&mut self, pu: PageUsage, count: usize) -> Result<usize, Errno>;
|
||||
|
||||
+14
-4
@@ -1,7 +1,10 @@
|
||||
//! Process file descriptors and I/O context
|
||||
use alloc::collections::BTreeMap;
|
||||
use libsys::{error::Errno, stat::{FileDescriptor, UserId, GroupId}};
|
||||
use vfs::{FileRef, Ioctx, VnodeRef, VnodeData};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
stat::{FileDescriptor, GroupId, UserId},
|
||||
};
|
||||
use vfs::{FileRef, Ioctx, VnodeRef};
|
||||
|
||||
/// Process I/O context. Contains file tables, root/cwd info etc.
|
||||
pub struct ProcessIo {
|
||||
@@ -74,7 +77,11 @@ impl ProcessIo {
|
||||
}
|
||||
|
||||
/// Clones a file descriptor into an available slot or, if specified, requested one
|
||||
pub fn duplicate_file(&mut self, src: FileDescriptor, dst: Option<FileDescriptor>) -> Result<FileDescriptor, Errno> {
|
||||
pub fn duplicate_file(
|
||||
&mut self,
|
||||
src: FileDescriptor,
|
||||
dst: Option<FileDescriptor>,
|
||||
) -> Result<FileDescriptor, Errno> {
|
||||
let file_ref = self.file(src)?;
|
||||
if let Some(dst) = dst {
|
||||
let idx = u32::from(dst);
|
||||
@@ -91,7 +98,10 @@ impl ProcessIo {
|
||||
|
||||
/// Returns [File] struct referred to by file descriptor `idx`
|
||||
pub fn file(&mut self, fd: FileDescriptor) -> Result<FileRef, Errno> {
|
||||
self.files.get(&u32::from(fd)).cloned().ok_or(Errno::InvalidFile)
|
||||
self.files
|
||||
.get(&u32::from(fd))
|
||||
.cloned()
|
||||
.ok_or(Errno::InvalidFile)
|
||||
}
|
||||
|
||||
/// Returns [Ioctx] structure reference of this I/O context
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::proc::{
|
||||
};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use alloc::{rc::Rc, vec::Vec};
|
||||
use core::arch::asm;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use libsys::{
|
||||
error::Errno,
|
||||
@@ -463,10 +462,12 @@ impl Process {
|
||||
Ok(base + offset)
|
||||
}
|
||||
|
||||
/// Returns the process's address space ID
|
||||
pub fn asid(&self) -> usize {
|
||||
(self.id().asid() as usize) << 48
|
||||
}
|
||||
|
||||
/// Flushes TLB cache for the process address space
|
||||
pub fn invalidate_tlb(&self) {
|
||||
unsafe {
|
||||
intrin::flush_tlb_asid(self.asid());
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::arch::intrin;
|
||||
use core::alloc::Layout;
|
||||
use libsys::error::Errno;
|
||||
use crate::proc::Process;
|
||||
use core::arch::asm;
|
||||
|
||||
// TODO _mut() versions checking whether pages are actually writable
|
||||
|
||||
|
||||
@@ -251,7 +251,8 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
let path = arg::str_ref(args[1], args[2])?;
|
||||
let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let flags = args[4] as u32;
|
||||
// TODO honor this option
|
||||
let _flags = args[4] as u32;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
@@ -198,9 +198,9 @@ unsafe impl GlobalAlloc for Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
#[cfg(feature = "verbose")]
|
||||
trace_debug!("free({:p}, {:?})", ptr, layout);
|
||||
trace_debug!("free({:p}, {:?})", ptr, _layout);
|
||||
assert!(!ptr.is_null());
|
||||
let mut block = ptr.sub(size_of::<Block>()) as *mut Block;
|
||||
let mut block_ref = &mut *block;
|
||||
|
||||
Vendored
+3
-1
@@ -1,7 +1,9 @@
|
||||
#[cfg(feature = "verbose")]
|
||||
use crate::trace;
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(feature = "verbose")]
|
||||
use libsys::debug::TraceLevel;
|
||||
use libsys::{
|
||||
debug::TraceLevel,
|
||||
ProgramArgs,
|
||||
};
|
||||
|
||||
|
||||
Vendored
+27
-25
@@ -1,9 +1,11 @@
|
||||
use crate::io::{Read, read_line};
|
||||
use core::str::FromStr;
|
||||
use core::fmt;
|
||||
use crate::trace_debug;
|
||||
use crate::file::File;
|
||||
use libsys::{FixedStr, stat::{UserId, GroupId}};
|
||||
use crate::io::{self, read_line};
|
||||
use core::str::FromStr;
|
||||
use libsys::{
|
||||
stat::{GroupId, UserId},
|
||||
error::Errno,
|
||||
FixedStr,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct UserInfo {
|
||||
@@ -35,11 +37,11 @@ impl UserInfo {
|
||||
self.gid
|
||||
}
|
||||
|
||||
pub fn find<F: Fn(&Self) -> bool>(pred: F) -> Result<Self, ()> {
|
||||
let mut file = File::open("/etc/passwd").map_err(|_| ())?;
|
||||
pub fn find<F: Fn(&Self) -> bool>(pred: F) -> Result<Self, io::Error> {
|
||||
let mut file = File::open("/etc/passwd")?;
|
||||
let mut buf = [0; 128];
|
||||
loop {
|
||||
let line = read_line(&mut file, &mut buf).map_err(|_| ())?;
|
||||
let line = read_line(&mut file, &mut buf)?;
|
||||
if let Some(line) = line {
|
||||
let ent = UserInfo::from_str(line)?;
|
||||
if pred(&ent) {
|
||||
@@ -49,37 +51,37 @@ impl UserInfo {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
Err(io::Error::from(Errno::InvalidArgument))
|
||||
}
|
||||
|
||||
pub fn by_name(name: &str) -> Result<Self, ()> {
|
||||
pub fn by_name(name: &str) -> Result<Self, io::Error> {
|
||||
Self::find(|ent| ent.name() == name)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for UserInfo {
|
||||
type Err = ();
|
||||
type Err = io::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
let mut iter = s.split(":");
|
||||
fn from_str(s: &str) -> Result<Self, io::Error> {
|
||||
let mut iter = s.split(':');
|
||||
|
||||
let name = iter.next().ok_or(())?;
|
||||
let name = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
let uid = iter
|
||||
.next()
|
||||
.ok_or(())
|
||||
.and_then(|e| u32::from_str(e).map_err(|_| ()))
|
||||
.ok_or_else(|| io::Error::from(Errno::InvalidArgument))
|
||||
.and_then(|e| u32::from_str(e).map_err(|_| io::Error::from(Errno::InvalidArgument)))
|
||||
.map(UserId::from)?;
|
||||
let gid = iter
|
||||
.next()
|
||||
.ok_or(())
|
||||
.and_then(|e| u32::from_str(e).map_err(|_| ()))
|
||||
.ok_or_else(|| io::Error::from(Errno::InvalidArgument))
|
||||
.and_then(|e| u32::from_str(e).map_err(|_| io::Error::from(Errno::InvalidArgument)))
|
||||
.map(GroupId::from)?;
|
||||
let comment = iter.next().ok_or(())?;
|
||||
let home = iter.next().ok_or(())?;
|
||||
let shell = iter.next().ok_or(())?;
|
||||
let _comment = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
let home = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
let shell = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
|
||||
if iter.next().is_some() {
|
||||
return Err(());
|
||||
return Err(io::Error::from(Errno::InvalidArgument));
|
||||
}
|
||||
|
||||
let mut res = Self {
|
||||
@@ -90,9 +92,9 @@ impl FromStr for UserInfo {
|
||||
shell: FixedStr::empty(),
|
||||
};
|
||||
|
||||
res.name.copy_from_str(&name);
|
||||
res.home.copy_from_str(&home);
|
||||
res.shell.copy_from_str(&shell);
|
||||
res.name.copy_from_str(name);
|
||||
res.home.copy_from_str(home);
|
||||
res.shell.copy_from_str(shell);
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
Vendored
+12
-13
@@ -1,7 +1,7 @@
|
||||
use crate::file::File;
|
||||
use crate::io::{Read, read_line};
|
||||
use crate::io::{self, read_line};
|
||||
use core::str::FromStr;
|
||||
use libsys::FixedStr;
|
||||
use libsys::{FixedStr, error::Errno};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct UserShadow {
|
||||
@@ -18,12 +18,11 @@ impl UserShadow {
|
||||
self.password.as_str()
|
||||
}
|
||||
|
||||
|
||||
pub fn find<F: Fn(&Self) -> bool>(pred: F) -> Result<Self, ()> {
|
||||
let mut file = File::open("/etc/shadow").map_err(|_| ())?;
|
||||
pub fn find<F: Fn(&Self) -> bool>(pred: F) -> Result<Self, io::Error> {
|
||||
let mut file = File::open("/etc/shadow")?;
|
||||
let mut buf = [0; 128];
|
||||
loop {
|
||||
let line = read_line(&mut file, &mut buf).map_err(|_| ())?;
|
||||
let line = read_line(&mut file, &mut buf)?;
|
||||
if let Some(line) = line {
|
||||
let ent = UserShadow::from_str(line)?;
|
||||
if pred(&ent) {
|
||||
@@ -33,25 +32,25 @@ impl UserShadow {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
Err(io::Error::from(Errno::DoesNotExist))
|
||||
}
|
||||
|
||||
pub fn by_name(name: &str) -> Result<Self, ()> {
|
||||
pub fn by_name(name: &str) -> Result<Self, io::Error> {
|
||||
Self::find(|ent| ent.name() == name)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for UserShadow {
|
||||
type Err = ();
|
||||
type Err = io::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
fn from_str(s: &str) -> Result<Self, io::Error> {
|
||||
let mut iter = s.split(':');
|
||||
|
||||
let name = iter.next().ok_or(())?;
|
||||
let password = iter.next().ok_or(())?;
|
||||
let name = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
let password = iter.next().ok_or_else(|| io::Error::from(Errno::InvalidArgument))?;
|
||||
|
||||
if iter.next().is_some() {
|
||||
return Err(());
|
||||
return Err(io::Error::from(Errno::InvalidArgument));
|
||||
}
|
||||
|
||||
let mut res = Self {
|
||||
|
||||
@@ -44,14 +44,14 @@ pub fn stat(pathname: &str) -> Result<Stat, Error> {
|
||||
}
|
||||
|
||||
// TODO use BufRead instead once it's implemented
|
||||
pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result<Option<&'a str>, ()> {
|
||||
pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result<Option<&'a str>, Error> {
|
||||
let mut pos = 0;
|
||||
loop {
|
||||
if pos == buf.len() {
|
||||
return Err(());
|
||||
return Err(Error::from(Errno::OutOfMemory));
|
||||
}
|
||||
|
||||
let count = f.read(&mut buf[pos..=pos]).map_err(|_| ())?;
|
||||
let count = f.read(&mut buf[pos..=pos])?;
|
||||
if count == 0 {
|
||||
if pos == 0 {
|
||||
return Ok(None);
|
||||
@@ -64,5 +64,5 @@ pub(crate) fn read_line<'a, F: Read>(f: &mut F, buf: &'a mut [u8]) -> Result<Opt
|
||||
|
||||
pos += 1;
|
||||
}
|
||||
core::str::from_utf8(&buf[..pos]).map_err(|_| ()).map(Some)
|
||||
core::str::from_utf8(&buf[..pos]).map_err(|_| Error::from(Errno::InvalidArgument)).map(Some)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ use libsys::{
|
||||
termios::{Termios, TermiosLflag},
|
||||
};
|
||||
use libusr::{env::{self, UserInfo, UserShadow}, io};
|
||||
use core::str::FromStr;
|
||||
|
||||
struct HiddenInput {
|
||||
fd: FileDescriptor,
|
||||
@@ -158,6 +157,6 @@ fn main() -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
login_as(username);
|
||||
login_as(username).ok();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user