feature: add Stat struct and fstatat()
This commit is contained in:
Generated
+1
-56
@@ -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"
|
||||
|
||||
+5
-1
@@ -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<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<usize, Errno> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ edition = "2021"
|
||||
[dependencies]
|
||||
error = { path = "../../error" }
|
||||
libcommon = { path = "../../libcommon" }
|
||||
hashbrown = "0.11.*"
|
||||
syscall = { path = "../../syscall" }
|
||||
|
||||
+5
-1
@@ -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<usize, Errno> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn stat(&mut self, _node: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
impl CharDeviceWrapper {
|
||||
|
||||
@@ -9,6 +9,8 @@ extern crate std;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub use syscall::stat::Stat;
|
||||
|
||||
mod block;
|
||||
pub use block::BlockDevice;
|
||||
mod fs;
|
||||
|
||||
+13
-1
@@ -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<usize, Errno>;
|
||||
|
||||
/// 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<usize, Errno>;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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!("> ");
|
||||
|
||||
|
||||
+28
-1
@@ -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<usize> {
|
||||
let mut res: usize;
|
||||
@@ -19,6 +22,13 @@ fn translate(virt: usize) -> Option<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_user_ptr_struct<'a, T>(base: usize) -> Result<&'a mut T, Errno> {
|
||||
let bytes = validate_user_ptr(base, size_of::<T>())?;
|
||||
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<usize, Errno> {
|
||||
|
||||
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::<Stat>(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 => {
|
||||
|
||||
+22
-1
@@ -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<Stat, ()> {
|
||||
let mut buf = MaybeUninit::<Stat>::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)+)))
|
||||
|
||||
+2
-1
@@ -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"]
|
||||
|
||||
@@ -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;
|
||||
|
||||
+25
-1
@@ -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
|
||||
}
|
||||
|
||||
+3
-2
@@ -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::*;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
Reference in New Issue
Block a user