mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
commit
85b8253a2c
63
src/services/libs/jinux-std/src/fs/file_handle.rs
Normal file
63
src/services/libs/jinux-std/src/fs/file_handle.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::prelude::*;
|
||||
use crate::rights::{ReadOp, WriteOp};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use super::file::File;
|
||||
use super::inode_handle::InodeHandle;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileHandle {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Inner {
|
||||
File(Arc<dyn File>),
|
||||
Inode(InodeHandle),
|
||||
}
|
||||
|
||||
impl FileHandle {
|
||||
pub fn new_file(file: Arc<dyn File>) -> Self {
|
||||
let inner = Inner::File(file);
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn new_inode_handle(inode_handle: InodeHandle) -> Self {
|
||||
let inner = Inner::Inode(inode_handle);
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn as_file(&self) -> Option<&Arc<dyn File>> {
|
||||
match &self.inner {
|
||||
Inner::File(file) => Some(file),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_inode_handle(&self) -> Option<&InodeHandle> {
|
||||
match &self.inner {
|
||||
Inner::Inode(inode_handle) => Some(inode_handle),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
match &self.inner {
|
||||
Inner::File(file) => file.read(buf),
|
||||
Inner::Inode(inode_handle) => {
|
||||
let static_handle = inode_handle.clone().to_static::<ReadOp>()?;
|
||||
static_handle.read(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
match &self.inner {
|
||||
Inner::File(file) => file.write(buf),
|
||||
Inner::Inode(inode_handle) => {
|
||||
let static_handle = inode_handle.clone().to_static::<WriteOp>()?;
|
||||
static_handle.write(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::{
|
||||
file::{File, FileDescripter},
|
||||
file::FileDescripter,
|
||||
file_handle::FileHandle,
|
||||
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileTable {
|
||||
table: BTreeMap<FileDescripter, Arc<dyn File>>,
|
||||
table: BTreeMap<FileDescripter, FileHandle>,
|
||||
}
|
||||
|
||||
impl FileTable {
|
||||
@ -22,9 +23,9 @@ impl FileTable {
|
||||
let stdin = Stdin::new_with_default_console();
|
||||
let stdout = Stdout::new_with_default_console();
|
||||
let stderr = Stderr::new_with_default_console();
|
||||
table.insert(FD_STDIN, Arc::new(stdin) as Arc<dyn File>);
|
||||
table.insert(FD_STDOUT, Arc::new(stdout) as Arc<dyn File>);
|
||||
table.insert(FD_STDERR, Arc::new(stderr) as Arc<dyn File>);
|
||||
table.insert(FD_STDIN, FileHandle::new_file(Arc::new(stdin)));
|
||||
table.insert(FD_STDOUT, FileHandle::new_file(Arc::new(stdout)));
|
||||
table.insert(FD_STDERR, FileHandle::new_file(Arc::new(stderr)));
|
||||
Self { table }
|
||||
}
|
||||
|
||||
@ -50,7 +51,7 @@ impl FileTable {
|
||||
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, item: Arc<dyn File>) -> FileDescripter {
|
||||
pub fn insert(&mut self, item: FileHandle) -> FileDescripter {
|
||||
let fd = self.max_fd() + 1;
|
||||
self.table.insert(fd, item);
|
||||
fd
|
||||
@ -60,7 +61,7 @@ impl FileTable {
|
||||
self.table.remove(&fd);
|
||||
}
|
||||
|
||||
pub fn get_file(&self, fd: FileDescripter) -> Result<&Arc<dyn File>> {
|
||||
pub fn get_file(&self, fd: FileDescripter) -> Result<&FileHandle> {
|
||||
self.table
|
||||
.get(&fd)
|
||||
.ok_or(Error::with_message(Errno::EBADF, "fd not exits"))
|
||||
|
66
src/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs
Normal file
66
src/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::rights::{Rights, TRights};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl InodeHandle<Rights> {
|
||||
pub fn new(
|
||||
inode: Arc<dyn Inode>,
|
||||
access_mode: AccessMode,
|
||||
status_flags: StatusFlags,
|
||||
) -> Result<Self> {
|
||||
let inode_info = inode.metadata();
|
||||
if access_mode.is_readable() && !inode_info.mode.is_readable() {
|
||||
return_errno_with_message!(Errno::EACCES, "File is not readable");
|
||||
}
|
||||
if access_mode.is_writable() && !inode_info.mode.is_writable() {
|
||||
return_errno_with_message!(Errno::EACCES, "File is not writable");
|
||||
}
|
||||
if access_mode.is_writable() && inode_info.type_ == InodeType::Dir {
|
||||
return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write");
|
||||
}
|
||||
let inner = Arc::new(InodeHandle_ {
|
||||
inode,
|
||||
offset: Mutex::new(0),
|
||||
access_mode,
|
||||
status_flags: Mutex::new(status_flags),
|
||||
});
|
||||
Ok(Self(inner, Rights::from(access_mode)))
|
||||
}
|
||||
|
||||
pub fn to_static<R1: TRights>(self) -> Result<InodeHandle<R1>> {
|
||||
let rights = Rights::from_bits(R1::BITS).ok_or(Error::new(Errno::EBADF))?;
|
||||
if !self.1.contains(rights) {
|
||||
return_errno_with_message!(Errno::EBADF, "check rights failed");
|
||||
}
|
||||
Ok(InodeHandle(self.0, R1::new()))
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
if !self.1.contains(Rights::READ) {
|
||||
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
||||
}
|
||||
self.0.read(buf)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if !self.1.contains(Rights::WRITE) {
|
||||
return_errno_with_message!(Errno::EBADF, "File is not writable");
|
||||
}
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
||||
if !self.1.contains(Rights::READ) {
|
||||
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
||||
}
|
||||
self.0.readdir(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for InodeHandle<Rights> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), self.1.clone())
|
||||
}
|
||||
}
|
146
src/services/libs/jinux-std/src/fs/inode_handle/mod.rs
Normal file
146
src/services/libs/jinux-std/src/fs/inode_handle/mod.rs
Normal file
@ -0,0 +1,146 @@
|
||||
//! Opend File Handle
|
||||
|
||||
mod dyn_cap;
|
||||
mod static_cap;
|
||||
|
||||
use super::utils::{
|
||||
AccessMode, DirentWriter, DirentWriterContext, Inode, InodeType, SeekFrom, StatusFlags,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::rights::Rights;
|
||||
use alloc::sync::Arc;
|
||||
|
||||
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
|
||||
|
||||
struct InodeHandle_ {
|
||||
inode: Arc<dyn Inode>,
|
||||
offset: Mutex<usize>,
|
||||
access_mode: AccessMode,
|
||||
status_flags: Mutex<StatusFlags>,
|
||||
}
|
||||
|
||||
impl InodeHandle_ {
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut offset = self.offset.lock();
|
||||
let file_size = self.inode.metadata().size;
|
||||
let start = file_size.min(*offset);
|
||||
let end = file_size.min(*offset + buf.len());
|
||||
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
|
||||
self.inode.read_at(start, &mut buf[0..start - end])?
|
||||
} else {
|
||||
self.inode.read_at(start, &mut buf[0..start - end])?
|
||||
// TODO: use page cache
|
||||
// self.inode.pages().read_at(start, buf[0..start - end])?
|
||||
};
|
||||
|
||||
*offset += len;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let mut offset = self.offset.lock();
|
||||
let file_size = self.inode.metadata().size;
|
||||
if self.status_flags.lock().contains(StatusFlags::O_APPEND) {
|
||||
*offset = file_size;
|
||||
}
|
||||
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
|
||||
self.inode.write_at(*offset, buf)?
|
||||
} else {
|
||||
self.inode.write_at(*offset, buf)?
|
||||
// TODO: use page cache
|
||||
// let len = self.inode.pages().write_at(*offset, buf)?;
|
||||
// if offset + len > file_size {
|
||||
// self.inode.resize(offset + len)?;
|
||||
// }
|
||||
// len
|
||||
};
|
||||
|
||||
*offset += len;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
|
||||
let mut offset = self.offset.lock();
|
||||
let new_offset: i64 = match pos {
|
||||
SeekFrom::Start(off /* as u64 */) => {
|
||||
if off > i64::max_value() as u64 {
|
||||
return_errno_with_message!(Errno::EINVAL, "file offset is too large");
|
||||
}
|
||||
off as i64
|
||||
}
|
||||
SeekFrom::End(off /* as i64 */) => {
|
||||
let file_size = self.inode.metadata().size as i64;
|
||||
assert!(file_size >= 0);
|
||||
file_size
|
||||
.checked_add(off)
|
||||
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?
|
||||
}
|
||||
SeekFrom::Current(off /* as i64 */) => (*offset as i64)
|
||||
.checked_add(off)
|
||||
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?,
|
||||
};
|
||||
if new_offset < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "file offset must not be negative");
|
||||
}
|
||||
// Invariant: 0 <= new_offset <= i64::max_value()
|
||||
let new_offset = new_offset as usize;
|
||||
*offset = new_offset;
|
||||
Ok(new_offset)
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
let offset = self.offset.lock();
|
||||
*offset
|
||||
}
|
||||
|
||||
pub fn access_mode(&self) -> AccessMode {
|
||||
self.access_mode
|
||||
}
|
||||
|
||||
pub fn status_flags(&self) -> StatusFlags {
|
||||
let status_flags = self.status_flags.lock();
|
||||
*status_flags
|
||||
}
|
||||
|
||||
pub fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
||||
let mut status_flags = self.status_flags.lock();
|
||||
// Can change only the O_APPEND, O_ASYNC, O_NOATIME, and O_NONBLOCK flags
|
||||
let valid_flags_mask = StatusFlags::O_APPEND
|
||||
| StatusFlags::O_ASYNC
|
||||
| StatusFlags::O_NOATIME
|
||||
| StatusFlags::O_NONBLOCK;
|
||||
status_flags.remove(valid_flags_mask);
|
||||
status_flags.insert(new_status_flags & valid_flags_mask);
|
||||
}
|
||||
|
||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
||||
let mut offset = self.offset.lock();
|
||||
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
|
||||
let written_size = self.inode.readdir(&mut dir_writer_ctx)?;
|
||||
*offset = dir_writer_ctx.pos();
|
||||
Ok(written_size)
|
||||
}
|
||||
}
|
||||
|
||||
/// Methods for both dyn and static
|
||||
impl<R> InodeHandle<R> {
|
||||
pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
|
||||
self.0.seek(pos)
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
self.0.offset()
|
||||
}
|
||||
|
||||
pub fn access_mode(&self) -> AccessMode {
|
||||
self.0.access_mode()
|
||||
}
|
||||
|
||||
pub fn status_flags(&self) -> StatusFlags {
|
||||
self.0.status_flags()
|
||||
}
|
||||
|
||||
pub fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
||||
self.0.set_status_flags(new_status_flags)
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
use crate::prelude::*;
|
||||
use crate::rights::*;
|
||||
use jinux_rights_proc::require;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<R: TRights> InodeHandle<R> {
|
||||
#[require(R > Read)]
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
|
||||
#[require(R > Write)]
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
#[require(R > Read)]
|
||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
||||
self.0.readdir(writer)
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
pub mod events;
|
||||
pub mod fcntl;
|
||||
pub mod file;
|
||||
pub mod file_handle;
|
||||
pub mod file_table;
|
||||
pub mod inode_handle;
|
||||
pub mod ioctl;
|
||||
pub mod poll;
|
||||
pub mod stat;
|
||||
pub mod stdio;
|
||||
pub mod utils;
|
||||
|
53
src/services/libs/jinux-std/src/fs/utils/access_mode.rs
Normal file
53
src/services/libs/jinux-std/src/fs/utils/access_mode.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use crate::rights::Rights;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum AccessMode {
|
||||
/// read only
|
||||
O_RDONLY = 0,
|
||||
/// write only
|
||||
O_WRONLY = 1,
|
||||
/// read write
|
||||
O_RDWR = 2,
|
||||
}
|
||||
|
||||
impl AccessMode {
|
||||
pub fn is_readable(&self) -> bool {
|
||||
match *self {
|
||||
AccessMode::O_RDONLY | AccessMode::O_RDWR => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_writable(&self) -> bool {
|
||||
match *self {
|
||||
AccessMode::O_WRONLY | AccessMode::O_RDWR => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rights> for AccessMode {
|
||||
fn from(rights: Rights) -> AccessMode {
|
||||
if rights.contains(Rights::READ) && rights.contains(Rights::WRITE) {
|
||||
AccessMode::O_RDWR
|
||||
} else if rights.contains(Rights::READ) {
|
||||
AccessMode::O_RDONLY
|
||||
} else if rights.contains(Rights::WRITE) {
|
||||
AccessMode::O_WRONLY
|
||||
} else {
|
||||
panic!("invalid rights");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AccessMode> for Rights {
|
||||
fn from(access_mode: AccessMode) -> Rights {
|
||||
match access_mode {
|
||||
AccessMode::O_RDONLY => Rights::READ,
|
||||
AccessMode::O_WRONLY => Rights::WRITE,
|
||||
AccessMode::O_RDWR => Rights::READ | Rights::WRITE,
|
||||
}
|
||||
}
|
||||
}
|
31
src/services/libs/jinux-std/src/fs/utils/dirent_writer.rs
Normal file
31
src/services/libs/jinux-std/src/fs/utils/dirent_writer.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use super::InodeType;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// DirentWriterContext is a wrapper of DirentWriter with directory position
|
||||
/// After a successful write, the position increases correspondingly
|
||||
pub struct DirentWriterContext<'a> {
|
||||
pos: usize,
|
||||
writer: &'a mut dyn DirentWriter,
|
||||
}
|
||||
|
||||
impl<'a> DirentWriterContext<'a> {
|
||||
pub fn new(pos: usize, writer: &'a mut dyn DirentWriter) -> Self {
|
||||
Self { pos, writer }
|
||||
}
|
||||
|
||||
pub fn write_entry(&mut self, name: &str, ino: u64, type_: InodeType) -> Result<usize> {
|
||||
let written_len = self.writer.write_entry(name, ino, type_)?;
|
||||
self.pos += 1;
|
||||
Ok(written_len)
|
||||
}
|
||||
|
||||
pub fn pos(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
}
|
||||
|
||||
/// DirentWriter is used to write directory entry,
|
||||
/// the object which implements it can decide how to format the data
|
||||
pub trait DirentWriter: Sync + Send {
|
||||
fn write_entry(&mut self, name: &str, ino: u64, type_: InodeType) -> Result<usize>;
|
||||
}
|
27
src/services/libs/jinux-std/src/fs/utils/fs.rs
Normal file
27
src/services/libs/jinux-std/src/fs/utils/fs.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use super::Inode;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SuperBlock {
|
||||
pub magic: usize,
|
||||
pub bsize: usize,
|
||||
pub blocks: usize,
|
||||
pub bfree: usize,
|
||||
pub bavail: usize,
|
||||
pub files: usize,
|
||||
pub ffree: usize,
|
||||
pub fsid: usize,
|
||||
pub namelen: usize,
|
||||
pub frsize: usize,
|
||||
pub flags: usize,
|
||||
}
|
||||
|
||||
pub trait FileSystem: Sync + Send {
|
||||
fn sync(&self) -> Result<()>;
|
||||
|
||||
fn root_inode(&self) -> Arc<dyn Inode>;
|
||||
|
||||
fn sb(&self) -> SuperBlock;
|
||||
}
|
137
src/services/libs/jinux-std/src/fs/utils/inode.rs
Normal file
137
src/services/libs/jinux-std/src/fs/utils/inode.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use bitflags::bitflags;
|
||||
use core::any::Any;
|
||||
|
||||
use super::{DirentWriterContext, FileSystem};
|
||||
use crate::fs::ioctl::IoctlCmd;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum InodeType {
|
||||
File = 1,
|
||||
Dir = 2,
|
||||
SymLink = 3,
|
||||
CharDevice = 4,
|
||||
BlockDevice = 5,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct InodeMode: u16 {
|
||||
/// set-user-ID
|
||||
const S_ISUID = 0o4000;
|
||||
/// set-group-ID
|
||||
const S_ISGID = 0o2000;
|
||||
/// sticky bit
|
||||
const S_ISVTX = 0o1000;
|
||||
/// read by owner
|
||||
const S_IRUSR = 0o0400;
|
||||
/// write by owner
|
||||
const S_IWUSR = 0o0200;
|
||||
/// execute/search by owner
|
||||
const S_IXUSR = 0o0100;
|
||||
/// read by group
|
||||
const S_IRGRP = 0o0040;
|
||||
/// write by group
|
||||
const S_IWGRP = 0o0020;
|
||||
/// execute/search by group
|
||||
const S_IXGRP = 0o0010;
|
||||
/// read by others
|
||||
const S_IROTH = 0o0004;
|
||||
/// write by others
|
||||
const S_IWOTH = 0o0002;
|
||||
/// execute/search by others
|
||||
const S_IXOTH = 0o0001;
|
||||
}
|
||||
}
|
||||
|
||||
impl InodeMode {
|
||||
pub fn is_readable(&self) -> bool {
|
||||
self.contains(Self::S_IRUSR)
|
||||
}
|
||||
|
||||
pub fn is_writable(&self) -> bool {
|
||||
self.contains(Self::S_IWUSR)
|
||||
}
|
||||
|
||||
pub fn is_executable(&self) -> bool {
|
||||
self.contains(Self::S_IXUSR)
|
||||
}
|
||||
|
||||
pub fn has_sticky_bit(&self) -> bool {
|
||||
self.contains(Self::S_ISVTX)
|
||||
}
|
||||
|
||||
pub fn has_set_uid(&self) -> bool {
|
||||
self.contains(Self::S_ISUID)
|
||||
}
|
||||
|
||||
pub fn has_set_gid(&self) -> bool {
|
||||
self.contains(Self::S_ISGID)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Metadata {
|
||||
pub dev: usize,
|
||||
pub ino: usize,
|
||||
pub size: usize,
|
||||
pub blk_size: usize,
|
||||
pub blocks: usize,
|
||||
pub atime: Timespec,
|
||||
pub mtime: Timespec,
|
||||
pub ctime: Timespec,
|
||||
pub type_: InodeType,
|
||||
pub mode: InodeMode,
|
||||
pub nlinks: usize,
|
||||
pub uid: usize,
|
||||
pub gid: usize,
|
||||
pub rdev: usize,
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Timespec {
|
||||
pub sec: i64,
|
||||
pub nsec: i64,
|
||||
}
|
||||
|
||||
pub trait Inode: Any + Sync + Send {
|
||||
fn resize(&self, new_size: usize) -> Result<()>;
|
||||
|
||||
fn metadata(&self) -> Metadata;
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
|
||||
|
||||
fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>>;
|
||||
|
||||
fn readdir(&self, ctx: &mut DirentWriterContext) -> Result<usize>;
|
||||
|
||||
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()>;
|
||||
|
||||
fn unlink(&self, name: &str) -> Result<()>;
|
||||
|
||||
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>>;
|
||||
|
||||
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()>;
|
||||
|
||||
fn read_link(&self) -> Result<String>;
|
||||
|
||||
fn write_link(&self, target: &str) -> Result<()>;
|
||||
|
||||
fn ioctl(&self, cmd: &IoctlCmd) -> Result<()>;
|
||||
|
||||
fn sync(&self) -> Result<()>;
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem>;
|
||||
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
impl dyn Inode {
|
||||
pub fn downcast_ref<T: Inode>(&self) -> Option<&T> {
|
||||
self.as_any_ref().downcast_ref::<T>()
|
||||
}
|
||||
}
|
20
src/services/libs/jinux-std/src/fs/utils/mod.rs
Normal file
20
src/services/libs/jinux-std/src/fs/utils/mod.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! VFS components
|
||||
|
||||
pub use access_mode::AccessMode;
|
||||
pub use dirent_writer::{DirentWriter, DirentWriterContext};
|
||||
pub use fs::{FileSystem, SuperBlock};
|
||||
pub use inode::{Inode, InodeMode, InodeType, Metadata, Timespec};
|
||||
pub use status_flags::StatusFlags;
|
||||
|
||||
mod access_mode;
|
||||
mod dirent_writer;
|
||||
mod fs;
|
||||
mod inode;
|
||||
mod status_flags;
|
||||
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||
pub enum SeekFrom {
|
||||
Start(u64),
|
||||
End(i64),
|
||||
Current(i64),
|
||||
}
|
23
src/services/libs/jinux-std/src/fs/utils/status_flags.rs
Normal file
23
src/services/libs/jinux-std/src/fs/utils/status_flags.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
pub struct StatusFlags: u32 {
|
||||
/// append on each write
|
||||
const O_APPEND = 1 << 10;
|
||||
/// non block
|
||||
const O_NONBLOCK = 1 << 11;
|
||||
/// synchronized I/O, data
|
||||
const O_DSYNC = 1 << 12;
|
||||
/// signal-driven I/O
|
||||
const O_ASYNC = 1 << 13;
|
||||
/// direct I/O
|
||||
const O_DIRECT = 1 << 14;
|
||||
/// on x86_64, O_LARGEFILE is 0
|
||||
/// not update st_atime
|
||||
const O_NOATIME = 1 << 18;
|
||||
/// synchronized I/O, data and metadata
|
||||
const O_SYNC = 1 << 20;
|
||||
/// equivalent of POSIX.1's O_EXEC
|
||||
const O_PATH = 1 << 21;
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ pub(crate) use core::ffi::CStr;
|
||||
pub(crate) use jinux_frame::config::PAGE_SIZE;
|
||||
pub(crate) use jinux_frame::vm::Vaddr;
|
||||
pub(crate) use jinux_frame::{debug, error, info, print, println, trace, warn};
|
||||
pub(crate) use spin::Mutex;
|
||||
pub(crate) use spin::{Mutex, RwLock};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! current {
|
||||
|
@ -47,3 +47,5 @@ typeflags! {
|
||||
|
||||
/// The full set of access rights.
|
||||
pub type Full = TRights![Dup, Read, Write, Exec, Signal];
|
||||
pub type ReadOp = TRights![Read];
|
||||
pub type WriteOp = TRights![Write];
|
||||
|
@ -16,6 +16,6 @@ pub fn sys_ioctl(fd: FileDescripter, cmd: u32, arg: Vaddr) -> Result<SyscallRetu
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let file = file_table.get_file(fd)?;
|
||||
let res = file.ioctl(ioctl_cmd, arg)?;
|
||||
let res = file.as_file().unwrap().ioctl(ioctl_cmd, arg)?;
|
||||
return Ok(SyscallReturn::Return(res as _));
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::fs::file::File;
|
||||
use crate::fs::file::FileDescripter;
|
||||
use crate::fs::file_handle::FileHandle;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
@ -41,7 +42,7 @@ pub fn sys_openat(
|
||||
}
|
||||
|
||||
if dirfd == AT_FDCWD && pathname == CString::new("/dev/tty")? {
|
||||
let tty_file = get_console().clone() as Arc<dyn File>;
|
||||
let tty_file = FileHandle::new_file(get_console().clone() as Arc<dyn File>);
|
||||
let current = current!();
|
||||
let mut file_table = current.file_table().lock();
|
||||
let fd = file_table.insert(tty_file);
|
||||
|
@ -39,7 +39,7 @@ pub fn sys_poll(fds: Vaddr, nfds: c_nfds, timeout: i32) -> Result<SyscallReturn>
|
||||
match file {
|
||||
Err(_) => return Some(Err(Error::new(Errno::EBADF))),
|
||||
Ok(file) => {
|
||||
let file_events = file.poll();
|
||||
let file_events = file.as_file().unwrap().poll();
|
||||
let polled_events = pollfd.events.intersection(file_events);
|
||||
if !polled_events.is_empty() {
|
||||
ready_files += 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user