diff --git a/Cargo.lock b/Cargo.lock index 9abe78b..be671b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "autocfg" version = "1.0.1" @@ -81,26 +70,6 @@ dependencies = [ "unsafe_unwrap", ] -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "init" version = "0.1.0" @@ -124,12 +93,6 @@ dependencies = [ "vfs", ] -[[package]] -name = "libc" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" - [[package]] name = "libcommon" version = "0.1.0" @@ -182,12 +145,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - [[package]] name = "osdev5" version = "0.1.0" @@ -273,23 +230,11 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80" -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - [[package]] name = "vfs" version = "0.1.0" dependencies = [ "error", - "hashbrown", "libcommon", + "syscall", ] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/fs/memfs/src/dir.rs b/fs/memfs/src/dir.rs index 4bb4605..a9a8510 100644 --- a/fs/memfs/src/dir.rs +++ b/fs/memfs/src/dir.rs @@ -1,4 +1,4 @@ -use vfs::{VnodeImpl, VnodeKind, VnodeRef, Vnode}; +use vfs::{VnodeImpl, VnodeKind, VnodeRef, Vnode, Stat}; use alloc::boxed::Box; use error::Errno; @@ -50,5 +50,9 @@ impl VnodeImpl for DirInode { fn size(&mut self, _node: VnodeRef) -> Result { todo!() } + + fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> { + todo!(); + } } diff --git a/fs/memfs/src/file.rs b/fs/memfs/src/file.rs index 0daa14e..b8b182e 100644 --- a/fs/memfs/src/file.rs +++ b/fs/memfs/src/file.rs @@ -1,4 +1,4 @@ -use vfs::{VnodeImpl, VnodeKind, VnodeRef}; +use vfs::{VnodeImpl, VnodeKind, VnodeRef, Stat}; use error::Errno; use crate::{BlockAllocator, Bvec}; @@ -53,4 +53,11 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> { fn size(&mut self, _node: VnodeRef) -> Result { Ok(self.data.size()) } + + fn stat(&mut self, node: VnodeRef, stat: &mut Stat) -> Result<(), Errno> { + stat.size = self.data.size() as u64; + stat.blksize = 4096; + stat.mode = 0o755; + Ok(()) + } } diff --git a/fs/vfs/Cargo.toml b/fs/vfs/Cargo.toml index b963dce..dd4bb6a 100644 --- a/fs/vfs/Cargo.toml +++ b/fs/vfs/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] error = { path = "../../error" } libcommon = { path = "../../libcommon" } -hashbrown = "0.11.*" +syscall = { path = "../../syscall" } diff --git a/fs/vfs/src/char.rs b/fs/vfs/src/char.rs index 09fd7ff..af4e14e 100644 --- a/fs/vfs/src/char.rs +++ b/fs/vfs/src/char.rs @@ -1,4 +1,4 @@ -use crate::{VnodeImpl, VnodeKind, VnodeRef}; +use crate::{VnodeImpl, VnodeKind, VnodeRef, Stat}; use error::Errno; /// Generic character device trait @@ -59,6 +59,10 @@ impl VnodeImpl for CharDeviceWrapper { fn size(&mut self, _node: VnodeRef) -> Result { panic!(); } + + fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> { + todo!(); + } } impl CharDeviceWrapper { diff --git a/fs/vfs/src/lib.rs b/fs/vfs/src/lib.rs index 1afae46..407f937 100644 --- a/fs/vfs/src/lib.rs +++ b/fs/vfs/src/lib.rs @@ -9,6 +9,8 @@ extern crate std; extern crate alloc; +pub use syscall::stat::Stat; + mod block; pub use block::BlockDevice; mod fs; diff --git a/fs/vfs/src/node.rs b/fs/vfs/src/node.rs index 6afa59c..27e9460 100644 --- a/fs/vfs/src/node.rs +++ b/fs/vfs/src/node.rs @@ -1,4 +1,4 @@ -use crate::{File, FileMode, Filesystem}; +use crate::{File, FileMode, Filesystem, Stat}; use alloc::{borrow::ToOwned, boxed::Box, rc::Rc, string::String, vec::Vec}; use core::cell::{RefCell, RefMut}; use core::fmt; @@ -70,6 +70,9 @@ pub trait VnodeImpl { /// Resizes the file storage if necessary. fn write(&mut self, node: VnodeRef, pos: usize, data: &[u8]) -> Result; + /// Retrieves file status + fn stat(&mut self, node: VnodeRef, stat: &mut Stat) -> Result<(), Errno>; + /// Reports the size of this filesystem object in bytes fn size(&mut self, node: VnodeRef) -> Result; } @@ -339,6 +342,15 @@ impl Vnode { Err(Errno::NotImplemented) } } + + /// Reports file status + pub fn stat(self: &VnodeRef, stat: &mut Stat) -> Result<(), Errno> { + if let Some(ref mut data) = *self.data() { + data.stat(self.clone(), stat) + } else { + Err(Errno::NotImplemented) + } + } } impl fmt::Debug for Vnode { diff --git a/init/src/main.rs b/init/src/main.rs index c90312c..502fbb0 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -5,13 +5,18 @@ #[macro_use] extern crate libusr; +use libusr::io; + #[no_mangle] fn main() -> i32 { let mut buf = [0; 128]; + let stat = io::stat("/test.txt").unwrap(); print!("\x1B[2J\x1B[1;1H"); println!("Hello!"); + println!("test.txt: {:?}", stat); + loop { print!("> "); diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 97848c0..fd4607d 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -5,7 +5,10 @@ use core::mem::size_of; use core::time::Duration; use error::Errno; use libcommon::{Read, Write}; -use syscall::abi; +use syscall::{ + abi, + stat::{Stat, AT_FDCWD}, +}; fn translate(virt: usize) -> Option { let mut res: usize; @@ -19,6 +22,13 @@ fn translate(virt: usize) -> Option { } } +fn validate_user_ptr_struct<'a, T>(base: usize) -> Result<&'a mut T, Errno> { + let bytes = validate_user_ptr(base, size_of::())?; + Ok(unsafe { + &mut *(bytes.as_mut_ptr() as *mut T) + }) +} + fn validate_user_ptr<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Errno> { if base > mem::KERNEL_OFFSET || base + len > mem::KERNEL_OFFSET { warnln!( @@ -133,6 +143,23 @@ pub unsafe fn syscall(num: usize, args: &[usize]) -> Result { io.file(args[0])?.write(buf) } + abi::SYS_FSTATAT => { + let proc = Process::current(); + let mut io = proc.io.lock(); + let fd = args[0]; + let filename = validate_user_str(args[1], 256)?; + let buf = validate_user_ptr_struct::(args[2])?; + + // TODO "self" flag + let at = if fd as i32 != AT_FDCWD { + todo!(); + } else { + None + }; + let node = io.ioctx().find(at, filename, true)?; + node.stat(buf)?; + Ok(0) + } // Extra system calls abi::SYS_EX_DEBUG_TRACE => { diff --git a/libusr/src/io.rs b/libusr/src/io.rs index a888811..836cd40 100644 --- a/libusr/src/io.rs +++ b/libusr/src/io.rs @@ -1,8 +1,29 @@ -use crate::sys; +use crate::sys::{self, Stat}; +use syscall::stat::AT_FDCWD; +use core::mem::MaybeUninit; use core::fmt; const STDOUT_FILENO: i32 = 0; +pub fn stat(pathname: &str) -> Result { + let mut buf = MaybeUninit::::uninit(); + let mut path = [0u8; 256]; + + let bytes = pathname.as_bytes(); + path[..pathname.len()].copy_from_slice(&bytes); + path[pathname.len()] = 0; + + unsafe { + let res = sys::sys_fstatat(AT_FDCWD, path.as_ptr(), buf.as_mut_ptr(), 0); + if res != 0 { + todo!(); + } + Ok(buf.assume_init()) + } +} + +// print!/println! group + #[macro_export] macro_rules! print { ($($args:tt)+) => ($crate::io::_print(format_args!($($args)+))) diff --git a/libusr/src/lib.rs b/libusr/src/lib.rs index 62b4360..524a768 100644 --- a/libusr/src/lib.rs +++ b/libusr/src/lib.rs @@ -8,7 +8,8 @@ pub mod os; pub mod io; pub mod sys { - pub use syscall::*; + pub use syscall::calls::*; + pub use syscall::stat::Stat; } #[link_section = ".text._start"] diff --git a/syscall/src/abi.rs b/syscall/src/abi.rs index ef02091..c707b51 100644 --- a/syscall/src/abi.rs +++ b/syscall/src/abi.rs @@ -7,3 +7,4 @@ pub const SYS_EXIT: usize = 1; pub const SYS_READ: usize = 2; pub const SYS_WRITE: usize = 3; pub const SYS_OPEN: usize = 4; +pub const SYS_FSTATAT: usize = 5; diff --git a/syscall/src/calls.rs b/syscall/src/calls.rs index 315e688..e9f0f42 100644 --- a/syscall/src/calls.rs +++ b/syscall/src/calls.rs @@ -1,4 +1,5 @@ use crate::abi; +use crate::stat::Stat; macro_rules! syscall { ($num:expr, $a0:expr) => {{ @@ -22,6 +23,13 @@ macro_rules! syscall { in("x8") $num, options(nostack)); res }}; + ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, in("x1") $a1, in("x2") $a2, + in("x3") $a3, in("x8") $num, options(nostack)); + res + }}; } #[inline(always)] @@ -42,7 +50,12 @@ pub unsafe fn sys_ex_debug_trace(msg: *const u8, len: usize) -> usize { #[inline(always)] pub unsafe fn sys_open(pathname: *const u8, mode: u32, flags: u32) -> i32 { - syscall!(abi::SYS_OPEN, pathname as usize, mode as usize, flags as usize) as i32 + syscall!( + abi::SYS_OPEN, + pathname as usize, + mode as usize, + flags as usize + ) as i32 } #[inline(always)] @@ -54,3 +67,14 @@ pub unsafe fn sys_read(fd: i32, data: *mut u8, len: usize) -> isize { pub unsafe fn sys_write(fd: i32, data: *const u8, len: usize) -> isize { syscall!(abi::SYS_WRITE, fd as usize, data as usize, len) as isize } + +#[inline(always)] +pub unsafe fn sys_fstatat(at: i32, pathname: *const u8, statbuf: *mut Stat, flags: i32) -> i32 { + syscall!( + abi::SYS_FSTATAT, + at as usize, + pathname as usize, + statbuf as usize, + flags as usize + ) as i32 +} diff --git a/syscall/src/lib.rs b/syscall/src/lib.rs index a62b941..ce77afc 100644 --- a/syscall/src/lib.rs +++ b/syscall/src/lib.rs @@ -5,9 +5,10 @@ compile_error!("Not yet implemented"); pub mod abi; -pub use abi::*; + +pub mod stat; #[cfg(feature = "user")] -mod calls; +pub mod calls; #[cfg(feature = "user")] pub use calls::*; diff --git a/syscall/src/stat.rs b/syscall/src/stat.rs new file mode 100644 index 0000000..035ddd7 --- /dev/null +++ b/syscall/src/stat.rs @@ -0,0 +1,9 @@ +pub const AT_FDCWD: i32 = -2; + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct Stat { + pub mode: u32, + pub size: u64, + pub blksize: u32, +}