mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-15 16:26:48 +00:00
Add correct stat syscall support
This commit is contained in:
parent
036f75505d
commit
116b687cae
@ -2,7 +2,7 @@ use crate::prelude::*;
|
||||
use crate::tty::get_n_tty;
|
||||
use core::any::Any;
|
||||
|
||||
use crate::fs::utils::{IoEvents, IoctlCmd};
|
||||
use crate::fs::utils::{IoEvents, IoctlCmd, Metadata};
|
||||
|
||||
/// The basic operations defined on a file
|
||||
pub trait File: Send + Sync + Any {
|
||||
@ -32,4 +32,8 @@ pub trait File: Send + Sync + Any {
|
||||
fn flush(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
panic!("metadata unsupported");
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
mod file;
|
||||
mod inode_handle;
|
||||
|
||||
use crate::fs::utils::Metadata;
|
||||
use crate::prelude::*;
|
||||
use crate::rights::{ReadOp, WriteOp};
|
||||
use alloc::sync::Arc;
|
||||
use core::ops::Range;
|
||||
|
||||
pub use self::file::File;
|
||||
pub use self::inode_handle::InodeHandle;
|
||||
@ -67,6 +67,13 @@ impl FileHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Metadata {
|
||||
match &self.inner {
|
||||
Inner::File(file) => file.metadata(),
|
||||
Inner::Inode(inode_handle) => inode_handle.dentry().vnode().inode().metadata(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean_for_close(&self) -> Result<()> {
|
||||
match &self.inner {
|
||||
Inner::Inode(inode_handle) => {
|
||||
|
@ -19,12 +19,14 @@ pub struct RamFS {
|
||||
|
||||
impl RamFS {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let sb = SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX);
|
||||
let root = Arc::new(RamInode(RwLock::new(Inode_::new_dir(
|
||||
ROOT_INO,
|
||||
InodeMode::from_bits_truncate(0o755),
|
||||
&sb,
|
||||
))));
|
||||
let ramfs = Arc::new(Self {
|
||||
metadata: RwLock::new(SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX)),
|
||||
metadata: RwLock::new(sb),
|
||||
root,
|
||||
inode_allocator: AtomicUsize::new(ROOT_INO + 1),
|
||||
});
|
||||
@ -71,28 +73,28 @@ struct Inode_ {
|
||||
}
|
||||
|
||||
impl Inode_ {
|
||||
pub fn new_dir(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_dir(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
inner: Inner::Dir(DirEntry::new()),
|
||||
metadata: Metadata::new_dir(ino, mode),
|
||||
metadata: Metadata::new_dir(ino, mode, sb),
|
||||
this: Weak::default(),
|
||||
fs: Weak::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_file(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_file(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
inner: Inner::File,
|
||||
metadata: Metadata::new_file(ino, mode),
|
||||
metadata: Metadata::new_file(ino, mode, sb),
|
||||
this: Weak::default(),
|
||||
fs: Weak::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_symlink(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_symlink(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
inner: Inner::SymLink(Str256::from("")),
|
||||
metadata: Metadata::new_synlink(ino, mode),
|
||||
metadata: Metadata::new_symlink(ino, mode, sb),
|
||||
this: Weak::default(),
|
||||
fs: Weak::default(),
|
||||
}
|
||||
@ -315,19 +317,22 @@ impl Inode for RamInode {
|
||||
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
||||
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
||||
}
|
||||
let fs = self_inode.fs.upgrade().unwrap();
|
||||
let new_inode = match type_ {
|
||||
InodeType::File => {
|
||||
let file_inode = Arc::new(RamInode(RwLock::new(Inode_::new_file(
|
||||
self_inode.fs.upgrade().unwrap().alloc_id(),
|
||||
fs.alloc_id(),
|
||||
mode,
|
||||
&fs.sb(),
|
||||
))));
|
||||
file_inode.0.write().fs = self_inode.fs.clone();
|
||||
file_inode
|
||||
}
|
||||
InodeType::Dir => {
|
||||
let dir_inode = Arc::new(RamInode(RwLock::new(Inode_::new_dir(
|
||||
self_inode.fs.upgrade().unwrap().alloc_id(),
|
||||
fs.alloc_id(),
|
||||
mode,
|
||||
&fs.sb(),
|
||||
))));
|
||||
dir_inode.0.write().fs = self_inode.fs.clone();
|
||||
dir_inode.0.write().inner.as_direntry_mut().unwrap().init(
|
||||
@ -338,8 +343,9 @@ impl Inode for RamInode {
|
||||
}
|
||||
InodeType::SymLink => {
|
||||
let sym_inode = Arc::new(RamInode(RwLock::new(Inode_::new_symlink(
|
||||
self_inode.fs.upgrade().unwrap().alloc_id(),
|
||||
fs.alloc_id(),
|
||||
mode,
|
||||
&fs.sb(),
|
||||
))));
|
||||
sym_inode.0.write().fs = self_inode.fs.clone();
|
||||
sym_inode
|
||||
|
@ -3,7 +3,7 @@ use crate::tty::{get_n_tty, Tty};
|
||||
|
||||
use super::file_handle::File;
|
||||
use super::file_table::FileDescripter;
|
||||
use super::utils::IoEvents;
|
||||
use super::utils::{InodeMode, InodeType, IoEvents, Metadata};
|
||||
|
||||
pub const FD_STDIN: FileDescripter = 0;
|
||||
pub const FD_STDOUT: FileDescripter = 1;
|
||||
@ -45,6 +45,25 @@ impl File for Stdin {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino: 0,
|
||||
size: 0,
|
||||
blk_size: 1024,
|
||||
blocks: 0,
|
||||
atime: Default::default(),
|
||||
mtime: Default::default(),
|
||||
ctime: Default::default(),
|
||||
type_: InodeType::CharDevice,
|
||||
mode: InodeMode::from_bits_truncate(0o620),
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl File for Stdout {
|
||||
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
|
||||
@ -62,6 +81,25 @@ impl File for Stdout {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino: 0,
|
||||
size: 0,
|
||||
blk_size: 1024,
|
||||
blocks: 0,
|
||||
atime: Default::default(),
|
||||
mtime: Default::default(),
|
||||
ctime: Default::default(),
|
||||
type_: InodeType::CharDevice,
|
||||
mode: InodeMode::from_bits_truncate(0o620),
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl File for Stderr {
|
||||
@ -80,6 +118,25 @@ impl File for Stderr {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino: 0,
|
||||
size: 0,
|
||||
blk_size: 1024,
|
||||
blocks: 0,
|
||||
atime: Default::default(),
|
||||
mtime: Default::default(),
|
||||
ctime: Default::default(),
|
||||
type_: InodeType::CharDevice,
|
||||
mode: InodeMode::from_bits_truncate(0o620),
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdin {
|
||||
|
@ -4,17 +4,19 @@ use bitflags::bitflags;
|
||||
use core::any::Any;
|
||||
use jinux_frame::vm::VmFrame;
|
||||
|
||||
use super::{DirentWriterContext, FileSystem, IoctlCmd};
|
||||
use super::{DirentWriterContext, FileSystem, IoctlCmd, SuperBlock};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum InodeType {
|
||||
File = 1,
|
||||
Dir = 2,
|
||||
SymLink = 3,
|
||||
CharDevice = 4,
|
||||
BlockDevice = 5,
|
||||
NamedPipe = 0o010000,
|
||||
CharDevice = 0o020000,
|
||||
Dir = 0o040000,
|
||||
BlockDevice = 0o060000,
|
||||
File = 0o100000,
|
||||
SymLink = 0o120000,
|
||||
Socket = 0o140000,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
@ -91,12 +93,12 @@ pub struct Metadata {
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
pub fn new_dir(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_dir(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 2,
|
||||
blk_size: 0,
|
||||
blk_size: sb.bsize,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
@ -110,12 +112,12 @@ impl Metadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_file(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_file(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blk_size: sb.bsize,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
@ -129,12 +131,12 @@ impl Metadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_synlink(ino: usize, mode: InodeMode) -> Self {
|
||||
pub fn new_symlink(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blk_size: sb.bsize,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
@ -149,7 +151,8 @@ impl Metadata {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
#[derive(Default, Copy, Clone, Pod, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
#[repr(C)]
|
||||
pub struct Timespec {
|
||||
pub sec: i64,
|
||||
pub nsec: i64,
|
||||
|
@ -1,15 +1,6 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
type dev_t = usize;
|
||||
type ino_t = usize;
|
||||
type mode_t = u32;
|
||||
type nlink_t = usize;
|
||||
type uid_t = u32;
|
||||
type gid_t = u32;
|
||||
type off_t = u32;
|
||||
type blksize_t = isize;
|
||||
type blkcnt_t = isize;
|
||||
type timespec = isize;
|
||||
use super::{Metadata, Timespec};
|
||||
|
||||
pub const S_IFMT: u32 = 0o170000;
|
||||
pub const S_IFCHR: u32 = 0o020000;
|
||||
@ -22,59 +13,55 @@ pub const S_IFLNK: u32 = 0o120000;
|
||||
#[repr(C)]
|
||||
pub struct Stat {
|
||||
/// ID of device containing file
|
||||
st_dev: dev_t,
|
||||
st_dev: usize,
|
||||
/// Inode number
|
||||
st_ino: ino_t,
|
||||
/// File type and mode
|
||||
st_mode: mode_t,
|
||||
st_ino: usize,
|
||||
/// Number of hard links
|
||||
st_nlink: nlink_t,
|
||||
st_nlink: usize,
|
||||
/// File type and mode
|
||||
st_mode: u32,
|
||||
/// User ID of owner
|
||||
st_uid: uid_t,
|
||||
st_uid: u32,
|
||||
/// Group ID of owner
|
||||
st_gid: gid_t,
|
||||
st_gid: u32,
|
||||
/// Padding bytes
|
||||
__pad0: u32,
|
||||
/// Device ID (if special file)
|
||||
st_rdev: dev_t,
|
||||
st_rdev: usize,
|
||||
/// Total size, in bytes
|
||||
st_size: off_t,
|
||||
st_size: isize,
|
||||
/// Block size for filesystem I/O
|
||||
st_blksize: blksize_t,
|
||||
/// Number of 512B blocks allocated
|
||||
st_blocks: blkcnt_t,
|
||||
st_blksize: isize,
|
||||
/// Number of 512-byte blocks allocated
|
||||
st_blocks: isize,
|
||||
/// Time of last access
|
||||
st_atime: timespec,
|
||||
st_atime: Timespec,
|
||||
/// Time of last modification
|
||||
st_mtime: timespec,
|
||||
st_mtime: Timespec,
|
||||
/// Time of last status change
|
||||
st_ctime: timespec,
|
||||
st_ctime: Timespec,
|
||||
/// Unused field
|
||||
__unused: [i64; 3],
|
||||
}
|
||||
|
||||
impl Stat {
|
||||
/// We use the same stat as linux
|
||||
pub fn stdout_stat() -> Self {
|
||||
let mut stat = Stat::default();
|
||||
stat.st_mode = S_IFCHR | 0o620;
|
||||
stat.st_nlink = 1;
|
||||
stat.st_blksize = 1024;
|
||||
stat
|
||||
}
|
||||
|
||||
/// Fake stat for a dir
|
||||
pub fn fake_dir_stat() -> Self {
|
||||
let mut stat = Stat::default();
|
||||
stat.st_mode = S_IFDIR | 0o755;
|
||||
stat.st_nlink = 20;
|
||||
stat.st_blksize = 4096;
|
||||
stat
|
||||
}
|
||||
|
||||
// Fake stat for /bin/stty
|
||||
pub fn fake_stty_stat() -> Self {
|
||||
let mut stat = Stat::default();
|
||||
stat.st_mode = S_IFREG | 0o755;
|
||||
stat.st_nlink = 1;
|
||||
stat.st_blksize = 4096;
|
||||
stat.st_size = 84344;
|
||||
stat
|
||||
impl From<Metadata> for Stat {
|
||||
fn from(info: Metadata) -> Self {
|
||||
Self {
|
||||
st_dev: info.dev,
|
||||
st_ino: info.ino,
|
||||
st_nlink: info.nlinks,
|
||||
st_mode: info.type_ as u32 | info.mode.bits() as u32,
|
||||
st_uid: info.uid as u32,
|
||||
st_gid: info.gid as u32,
|
||||
__pad0: 0,
|
||||
st_rdev: 0,
|
||||
st_size: info.size as isize,
|
||||
st_blksize: info.blk_size as isize,
|
||||
st_blocks: info.blocks as isize,
|
||||
st_atime: info.atime,
|
||||
st_mtime: info.mtime,
|
||||
st_ctime: info.ctime,
|
||||
__unused: [0; 3],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
use jinux_frame::vm::VmIo;
|
||||
|
||||
use crate::fs::utils::Stat;
|
||||
use crate::{log_syscall_entry, prelude::*};
|
||||
|
||||
use crate::syscall::{SyscallReturn, SYS_FSTAT};
|
||||
|
||||
pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_FSTAT);
|
||||
debug!("fd = {}, stat_buf_addr = 0x{:x}", fd, stat_buf_ptr);
|
||||
|
||||
let current = current!();
|
||||
let root_vmar = current.root_vmar();
|
||||
if fd == 1 {
|
||||
let stat = Stat::stdout_stat();
|
||||
root_vmar.write_val(stat_buf_ptr, &stat)?;
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
// TODO: fstat only returns fake result now
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
use crate::fs::utils::Stat;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
use crate::util::write_val_to_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_LSTAT;
|
||||
|
||||
pub fn sys_lstat(filename_ptr: Vaddr, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_LSTAT);
|
||||
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
debug!(
|
||||
"filename = {:?}, stat_buf_ptr = 0x{:x}",
|
||||
filename, stat_buf_ptr
|
||||
);
|
||||
// TODO: only return a fake result here
|
||||
if filename == CString::new(".")? || filename == CString::new("/")? {
|
||||
let stat = Stat::fake_dir_stat();
|
||||
write_val_to_user(stat_buf_ptr, &stat)?;
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
todo!()
|
||||
}
|
@ -12,7 +12,6 @@ use crate::syscall::exit::sys_exit;
|
||||
use crate::syscall::exit_group::sys_exit_group;
|
||||
use crate::syscall::fcntl::sys_fcntl;
|
||||
use crate::syscall::fork::sys_fork;
|
||||
use crate::syscall::fstat::sys_fstat;
|
||||
use crate::syscall::futex::sys_futex;
|
||||
use crate::syscall::getcwd::sys_getcwd;
|
||||
use crate::syscall::getegid::sys_getegid;
|
||||
@ -27,7 +26,6 @@ use crate::syscall::ioctl::sys_ioctl;
|
||||
use crate::syscall::kill::sys_kill;
|
||||
use crate::syscall::link::{sys_link, sys_linkat};
|
||||
use crate::syscall::lseek::sys_lseek;
|
||||
use crate::syscall::lstat::sys_lstat;
|
||||
use crate::syscall::madvise::sys_madvise;
|
||||
use crate::syscall::mkdir::{sys_mkdir, sys_mkdirat};
|
||||
use crate::syscall::mmap::sys_mmap;
|
||||
@ -47,7 +45,7 @@ use crate::syscall::sched_yield::sys_sched_yield;
|
||||
use crate::syscall::set_robust_list::sys_set_robust_list;
|
||||
use crate::syscall::set_tid_address::sys_set_tid_address;
|
||||
use crate::syscall::setpgid::sys_setpgid;
|
||||
use crate::syscall::stat::sys_stat;
|
||||
use crate::syscall::stat::{sys_fstat, sys_fstatat, sys_lstat, sys_stat};
|
||||
use crate::syscall::tgkill::sys_tgkill;
|
||||
use crate::syscall::uname::sys_uname;
|
||||
use crate::syscall::unlink::{sys_unlink, sys_unlinkat};
|
||||
@ -69,7 +67,6 @@ mod exit;
|
||||
mod exit_group;
|
||||
mod fcntl;
|
||||
mod fork;
|
||||
mod fstat;
|
||||
mod futex;
|
||||
mod getcwd;
|
||||
mod getegid;
|
||||
@ -84,7 +81,6 @@ mod ioctl;
|
||||
mod kill;
|
||||
mod link;
|
||||
mod lseek;
|
||||
mod lstat;
|
||||
mod madvise;
|
||||
mod mkdir;
|
||||
mod mmap;
|
||||
@ -198,6 +194,7 @@ define_syscall_nums!(
|
||||
SYS_WAITID = 247,
|
||||
SYS_OPENAT = 257,
|
||||
SYS_MKDIRAT = 258,
|
||||
SYS_FSTATAT = 262,
|
||||
SYS_UNLINKAT = 263,
|
||||
SYS_LINKAT = 265,
|
||||
SYS_SET_ROBUST_LIST = 273,
|
||||
@ -314,6 +311,7 @@ pub fn syscall_dispatch(
|
||||
SYS_WAITID => syscall_handler!(5, sys_waitid, args),
|
||||
SYS_OPENAT => syscall_handler!(4, sys_openat, args),
|
||||
SYS_MKDIRAT => syscall_handler!(3, sys_mkdirat, args),
|
||||
SYS_FSTATAT => syscall_handler!(4, sys_fstatat, args),
|
||||
SYS_UNLINKAT => syscall_handler!(3, sys_unlinkat, args),
|
||||
SYS_LINKAT => syscall_handler!(5, sys_linkat, args),
|
||||
SYS_SET_ROBUST_LIST => syscall_handler!(2, sys_set_robust_list, args),
|
||||
|
@ -1,16 +1,79 @@
|
||||
use super::SYS_STAT;
|
||||
use crate::fs::{
|
||||
file_table::FileDescripter,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
utils::Stat,
|
||||
};
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
use crate::{log_syscall_entry, prelude::*};
|
||||
use crate::util::write_val_to_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::{SYS_FSTAT, SYS_FSTATAT};
|
||||
|
||||
pub fn sys_fstat(fd: FileDescripter, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_FSTAT);
|
||||
debug!("fd = {}, stat_buf_addr = 0x{:x}", fd, stat_buf_ptr);
|
||||
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let file = file_table.get_file(fd)?;
|
||||
let stat = Stat::from(file.metadata());
|
||||
write_val_to_user(stat_buf_ptr, &stat)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_stat(filename_ptr: Vaddr, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_STAT);
|
||||
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
debug!(
|
||||
"filename = {:?}, stat_buf_ptr = 0x{:x}",
|
||||
filename, stat_buf_ptr
|
||||
);
|
||||
return_errno_with_message!(Errno::ENOSYS, "Stat is unimplemented");
|
||||
self::sys_fstatat(AT_FDCWD, filename_ptr, stat_buf_ptr, 0)
|
||||
}
|
||||
|
||||
pub fn sys_lstat(filename_ptr: Vaddr, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
self::sys_fstatat(
|
||||
AT_FDCWD,
|
||||
filename_ptr,
|
||||
stat_buf_ptr,
|
||||
StatFlags::AT_SYMLINK_NOFOLLOW.bits(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn sys_fstatat(
|
||||
dirfd: FileDescripter,
|
||||
filename_ptr: Vaddr,
|
||||
stat_buf_ptr: Vaddr,
|
||||
flags: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_FSTATAT);
|
||||
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
let flags =
|
||||
StatFlags::from_bits(flags).ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?;
|
||||
debug!(
|
||||
"dirfd = {}, filename = {:?}, stat_buf_ptr = 0x{:x}, flags = {:?}",
|
||||
dirfd, filename, stat_buf_ptr, flags
|
||||
);
|
||||
let current = current!();
|
||||
let dentry = {
|
||||
let filename = filename.to_string_lossy();
|
||||
if filename.is_empty() && !flags.contains(StatFlags::AT_EMPTY_PATH) {
|
||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||
}
|
||||
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
|
||||
let fs = current.fs().read();
|
||||
if flags.contains(StatFlags::AT_SYMLINK_NOFOLLOW) {
|
||||
fs.lookup_no_follow(&fs_path)?
|
||||
} else {
|
||||
fs.lookup(&fs_path)?
|
||||
}
|
||||
};
|
||||
let stat = Stat::from(dentry.vnode().inode().metadata());
|
||||
write_val_to_user(stat_buf_ptr, &stat)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct StatFlags: u32 {
|
||||
const AT_EMPTY_PATH = 1 << 12;
|
||||
const AT_NO_AUTOMOUNT = 1 << 11;
|
||||
const AT_SYMLINK_NOFOLLOW = 1 << 8;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user