mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Add trait FileIo and refactor current devices
This commit is contained in:
parent
43fd1a52fa
commit
001326110e
@ -12,6 +12,8 @@ pub use pty::{PtyMaster, PtySlave};
|
|||||||
pub use random::Random;
|
pub use random::Random;
|
||||||
pub use urandom::Urandom;
|
pub use urandom::Urandom;
|
||||||
|
|
||||||
|
use self::tty::get_n_tty;
|
||||||
|
|
||||||
/// Init the device node in fs, must be called after mounting rootfs.
|
/// Init the device node in fs, must be called after mounting rootfs.
|
||||||
pub fn init() -> Result<()> {
|
pub fn init() -> Result<()> {
|
||||||
let null = Arc::new(null::Null);
|
let null = Arc::new(null::Null);
|
||||||
@ -19,7 +21,9 @@ pub fn init() -> Result<()> {
|
|||||||
let zero = Arc::new(zero::Zero);
|
let zero = Arc::new(zero::Zero);
|
||||||
add_node(zero, "zero")?;
|
add_node(zero, "zero")?;
|
||||||
tty::init();
|
tty::init();
|
||||||
let tty = tty::get_n_tty().clone();
|
let console = get_n_tty().clone();
|
||||||
|
add_node(console, "console")?;
|
||||||
|
let tty = Arc::new(tty::TtyDevice);
|
||||||
add_node(tty, "tty")?;
|
add_node(tty, "tty")?;
|
||||||
let random = Arc::new(random::Random);
|
let random = Arc::new(random::Random);
|
||||||
add_node(random, "random")?;
|
add_node(random, "random")?;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub struct Null;
|
pub struct Null;
|
||||||
|
|
||||||
@ -12,7 +15,9 @@ impl Device for Null {
|
|||||||
// Same value with Linux
|
// Same value with Linux
|
||||||
DeviceId::new(1, 3)
|
DeviceId::new(1, 3)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileIo for Null {
|
||||||
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
@ -20,4 +25,9 @@ impl Device for Null {
|
|||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
|
events & mask
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::{Device, DeviceId, DeviceType};
|
use crate::fs::device::{Device, DeviceId, DeviceType};
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub struct Random;
|
pub struct Random;
|
||||||
|
|
||||||
@ -19,7 +22,9 @@ impl Device for Random {
|
|||||||
// The same value as Linux
|
// The same value as Linux
|
||||||
DeviceId::new(1, 8)
|
DeviceId::new(1, 8)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileIo for Random {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
Self::getrandom(buf)
|
Self::getrandom(buf)
|
||||||
}
|
}
|
||||||
@ -27,6 +32,11 @@ impl Device for Random {
|
|||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
|
events & mask
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<getrandom::Error> for Error {
|
impl From<getrandom::Error> for Error {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::{Device, DeviceId, DeviceType};
|
use crate::fs::device::{Device, DeviceId, DeviceType};
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub struct Urandom;
|
pub struct Urandom;
|
||||||
|
|
||||||
@ -19,7 +22,9 @@ impl Device for Urandom {
|
|||||||
// The same value as Linux
|
// The same value as Linux
|
||||||
DeviceId::new(1, 9)
|
DeviceId::new(1, 9)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileIo for Urandom {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
Self::getrandom(buf)
|
Self::getrandom(buf)
|
||||||
}
|
}
|
||||||
@ -27,4 +32,9 @@ impl Device for Urandom {
|
|||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
|
events & mask
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub struct Zero;
|
pub struct Zero;
|
||||||
|
|
||||||
@ -12,7 +15,9 @@ impl Device for Zero {
|
|||||||
// Same value with Linux
|
// Same value with Linux
|
||||||
DeviceId::new(1, 5)
|
DeviceId::new(1, 5)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileIo for Zero {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
for byte in buf.iter_mut() {
|
for byte in buf.iter_mut() {
|
||||||
*byte = 0;
|
*byte = 0;
|
||||||
@ -23,4 +28,9 @@ impl Device for Zero {
|
|||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
|
events & mask
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,21 @@
|
|||||||
use crate::events::IoEvents;
|
|
||||||
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
||||||
use crate::fs::utils::Dentry;
|
use crate::fs::utils::Dentry;
|
||||||
use crate::fs::utils::{InodeMode, InodeType, IoctlCmd};
|
use crate::fs::utils::{InodeMode, InodeType};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::Poller;
|
|
||||||
|
use super::inode_handle::FileIo;
|
||||||
|
|
||||||
/// The abstract of device
|
/// The abstract of device
|
||||||
pub trait Device: Sync + Send {
|
pub trait Device: Sync + Send + FileIo {
|
||||||
/// Return the device type.
|
/// Return the device type.
|
||||||
fn type_(&self) -> DeviceType;
|
fn type_(&self) -> DeviceType;
|
||||||
|
|
||||||
/// Return the device ID.
|
/// Return the device ID.
|
||||||
fn id(&self) -> DeviceId;
|
fn id(&self) -> DeviceId;
|
||||||
|
|
||||||
/// Read from the device.
|
/// Open a device.
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize>;
|
fn open(&self) -> Result<Option<Arc<dyn FileIo>>> {
|
||||||
|
Ok(None)
|
||||||
/// Write to the device.
|
|
||||||
fn write(&self, buf: &[u8]) -> Result<usize>;
|
|
||||||
|
|
||||||
/// Poll on the device.
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
|
||||||
let events = IoEvents::IN | IoEvents::OUT;
|
|
||||||
events & mask
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ioctl on the device.
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
use crate::events::IoEvents;
|
|
||||||
use crate::fs::file_handle::FileLike;
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::process::signal::Poller;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use crate::device::PtyMaster;
|
|
||||||
|
|
||||||
/// Pty master inode for the master device.
|
|
||||||
pub struct PtyMasterInode(Arc<PtyMaster>);
|
|
||||||
|
|
||||||
impl PtyMasterInode {
|
|
||||||
pub fn new(device: Arc<PtyMaster>) -> Arc<Self> {
|
|
||||||
Arc::new(Self(device))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for PtyMasterInode {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// Remove the slave from fs.
|
|
||||||
let fs = self.0.ptmx().fs();
|
|
||||||
let devpts = fs.downcast_ref::<DevPts>().unwrap();
|
|
||||||
|
|
||||||
let index = self.0.index();
|
|
||||||
devpts.remove_slave(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Inode for PtyMasterInode {
|
|
||||||
/// Do not cache dentry in DCACHE.
|
|
||||||
///
|
|
||||||
/// Each file descriptor obtained by opening "/dev/ptmx" is an independent pty master
|
|
||||||
/// with its own associated pty slave.
|
|
||||||
fn is_dentry_cacheable(&self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.0.ptmx().metadata().size
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&self, new_size: usize) {}
|
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
|
||||||
self.0.ptmx().metadata()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_(&self) -> InodeType {
|
|
||||||
self.0.ptmx().metadata().type_
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode(&self) -> InodeMode {
|
|
||||||
self.0.ptmx().metadata().mode
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_mode(&self, mode: InodeMode) {}
|
|
||||||
|
|
||||||
fn atime(&self) -> Duration {
|
|
||||||
self.0.ptmx().metadata().atime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_atime(&self, time: Duration) {}
|
|
||||||
|
|
||||||
fn mtime(&self) -> Duration {
|
|
||||||
self.0.ptmx().metadata().mtime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_mtime(&self, time: Duration) {}
|
|
||||||
|
|
||||||
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
|
||||||
self.0.read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
|
||||||
self.0.read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
|
||||||
self.0.write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
|
||||||
self.0.write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
|
||||||
self.0.ioctl(cmd, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
|
||||||
self.0.poll(mask, poller)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
|
||||||
self.0.ptmx().fs()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::device::PtyMaster;
|
||||||
use crate::fs::device::{Device, DeviceId, DeviceType};
|
use crate::fs::device::{Device, DeviceId, DeviceType};
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
||||||
@ -9,11 +10,9 @@ use core::time::Duration;
|
|||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
use jinux_util::{id_allocator::IdAlloc, slot_vec::SlotVec};
|
use jinux_util::{id_allocator::IdAlloc, slot_vec::SlotVec};
|
||||||
|
|
||||||
use self::master::PtyMasterInode;
|
|
||||||
use self::ptmx::Ptmx;
|
use self::ptmx::Ptmx;
|
||||||
use self::slave::PtySlaveInode;
|
use self::slave::PtySlaveInode;
|
||||||
|
|
||||||
mod master;
|
|
||||||
mod ptmx;
|
mod ptmx;
|
||||||
mod slave;
|
mod slave;
|
||||||
|
|
||||||
@ -52,7 +51,7 @@ impl DevPts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create the master and slave pair.
|
/// Create the master and slave pair.
|
||||||
fn create_master_slave_pair(&self) -> Result<(Arc<PtyMasterInode>, Arc<PtySlaveInode>)> {
|
fn create_master_slave_pair(&self) -> Result<(Arc<PtyMaster>, Arc<PtySlaveInode>)> {
|
||||||
let index = self
|
let index = self
|
||||||
.index_alloc
|
.index_alloc
|
||||||
.lock()
|
.lock()
|
||||||
@ -61,17 +60,16 @@ impl DevPts {
|
|||||||
|
|
||||||
let (master, slave) = crate::device::new_pty_pair(index as u32, self.root.ptmx.clone())?;
|
let (master, slave) = crate::device::new_pty_pair(index as u32, self.root.ptmx.clone())?;
|
||||||
|
|
||||||
let master_inode = PtyMasterInode::new(master);
|
|
||||||
let slave_inode = PtySlaveInode::new(slave, self.this.clone());
|
let slave_inode = PtySlaveInode::new(slave, self.this.clone());
|
||||||
self.root.add_slave(index.to_string(), slave_inode.clone());
|
self.root.add_slave(index.to_string(), slave_inode.clone());
|
||||||
|
|
||||||
Ok((master_inode, slave_inode))
|
Ok((master, slave_inode))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the slave from fs.
|
/// Remove the slave from fs.
|
||||||
///
|
///
|
||||||
/// This is called when the master is being dropped.
|
/// This is called when the master is being dropped.
|
||||||
fn remove_slave(&self, index: u32) -> Option<Arc<PtySlaveInode>> {
|
pub fn remove_slave(&self, index: u32) -> Option<Arc<PtySlaveInode>> {
|
||||||
let removed_slave = self.root.remove_slave(&index.to_string());
|
let removed_slave = self.root.remove_slave(&index.to_string());
|
||||||
if removed_slave.is_some() {
|
if removed_slave.is_some() {
|
||||||
self.index_alloc.lock().free(index as usize);
|
self.index_alloc.lock().free(index as usize);
|
||||||
@ -241,7 +239,7 @@ impl Inode for RootInode {
|
|||||||
let inode = match name {
|
let inode = match name {
|
||||||
"." | ".." => self.fs().root_inode(),
|
"." | ".." => self.fs().root_inode(),
|
||||||
// Call the "open" method of ptmx to create a master and slave pair.
|
// Call the "open" method of ptmx to create a master and slave pair.
|
||||||
"ptmx" => self.ptmx.open()?,
|
"ptmx" => self.ptmx.clone(),
|
||||||
slave => self
|
slave => self
|
||||||
.slaves
|
.slaves
|
||||||
.read()
|
.read()
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
|
use crate::device::PtyMaster;
|
||||||
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -14,12 +18,14 @@ const PTMX_MINOR_NUM: u32 = 2;
|
|||||||
pub struct Ptmx {
|
pub struct Ptmx {
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
fs: Weak<DevPts>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Inner(Weak<DevPts>);
|
||||||
|
|
||||||
impl Ptmx {
|
impl Ptmx {
|
||||||
pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> {
|
pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> {
|
||||||
let inner = Inner;
|
let inner = Inner(fs);
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
metadata: Metadata::new_device(
|
metadata: Metadata::new_device(
|
||||||
PTMX_INO,
|
PTMX_INO,
|
||||||
@ -28,20 +34,19 @@ impl Ptmx {
|
|||||||
&inner,
|
&inner,
|
||||||
),
|
),
|
||||||
inner,
|
inner,
|
||||||
fs,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The open method for ptmx.
|
/// The open method for ptmx.
|
||||||
///
|
///
|
||||||
/// Creates a master and slave pair and returns the master inode.
|
/// Creates a master and slave pair and returns the master inode.
|
||||||
pub fn open(&self) -> Result<Arc<PtyMasterInode>> {
|
pub fn open(&self) -> Result<Arc<PtyMaster>> {
|
||||||
let (master, _) = self.devpts().create_master_slave_pair()?;
|
let (master, _) = self.devpts().create_master_slave_pair()?;
|
||||||
Ok(master)
|
Ok(master)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn devpts(&self) -> Arc<DevPts> {
|
pub fn devpts(&self) -> Arc<DevPts> {
|
||||||
self.fs.upgrade().unwrap()
|
self.inner.0.upgrade().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_type(&self) -> DeviceType {
|
pub fn device_type(&self) -> DeviceType {
|
||||||
@ -121,13 +126,10 @@ impl Inode for Ptmx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
Some(Arc::new(self.inner))
|
Some(Arc::new(self.inner.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct Inner;
|
|
||||||
|
|
||||||
impl Device for Inner {
|
impl Device for Inner {
|
||||||
fn type_(&self) -> DeviceType {
|
fn type_(&self) -> DeviceType {
|
||||||
DeviceType::CharDevice
|
DeviceType::CharDevice
|
||||||
@ -137,13 +139,23 @@ impl Device for Inner {
|
|||||||
DeviceId::new(PTMX_MAJOR_NUM, PTMX_MINOR_NUM)
|
DeviceId::new(PTMX_MAJOR_NUM, PTMX_MINOR_NUM)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open(&self) -> Result<Option<Arc<dyn FileIo>>> {
|
||||||
|
let devpts = self.0.upgrade().unwrap();
|
||||||
|
let (master, _) = devpts.create_master_slave_pair()?;
|
||||||
|
Ok(Some(master as _))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileIo for Inner {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
// do nothing because it should not be used to read.
|
unreachable!()
|
||||||
Ok(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
// do nothing because it should not be used to write.
|
unreachable!()
|
||||||
Ok(buf.len())
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::events::IoEvents;
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::inode_handle::FileIo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::Poller;
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
//! Opend File Handle
|
//! Opend File Handle
|
||||||
|
|
||||||
use crate::events::Observer;
|
use crate::events::{IoEvents, Observer};
|
||||||
use crate::fs::device::Device;
|
use crate::fs::device::Device;
|
||||||
use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags};
|
use crate::fs::utils::{AccessMode, IoctlCmd, Metadata, SeekFrom, StatusFlags};
|
||||||
use crate::net::socket::Socket;
|
use crate::net::socket::Socket;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::Poller;
|
use crate::process::signal::Poller;
|
||||||
|
@ -27,7 +27,7 @@ impl FileTable {
|
|||||||
pub fn new_with_stdio() -> Self {
|
pub fn new_with_stdio() -> Self {
|
||||||
let mut table = SlotVec::new();
|
let mut table = SlotVec::new();
|
||||||
let fs_resolver = FsResolver::new();
|
let fs_resolver = FsResolver::new();
|
||||||
let tty_path = FsPath::new(AT_FDCWD, "/dev/tty").expect("cannot find tty");
|
let tty_path = FsPath::new(AT_FDCWD, "/dev/console").expect("cannot find tty");
|
||||||
let stdin = {
|
let stdin = {
|
||||||
let flags = AccessMode::O_RDONLY as u32;
|
let flags = AccessMode::O_RDONLY as u32;
|
||||||
let mode = InodeMode::S_IRUSR;
|
let mode = InodeMode::S_IRUSR;
|
||||||
|
@ -21,8 +21,16 @@ impl InodeHandle<Rights> {
|
|||||||
if access_mode.is_writable() && inode.type_() == InodeType::Dir {
|
if access_mode.is_writable() && inode.type_() == InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write");
|
return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let file_io = if let Some(device) = inode.as_device() {
|
||||||
|
device.open()?
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let inner = Arc::new(InodeHandle_ {
|
let inner = Arc::new(InodeHandle_ {
|
||||||
dentry,
|
dentry,
|
||||||
|
file_io,
|
||||||
offset: Mutex::new(0),
|
offset: Mutex::new(0),
|
||||||
access_mode,
|
access_mode,
|
||||||
status_flags: AtomicU32::new(status_flags.bits()),
|
status_flags: AtomicU32::new(status_flags.bits()),
|
||||||
@ -42,6 +50,7 @@ impl InodeHandle<Rights> {
|
|||||||
if !self.1.contains(Rights::READ) {
|
if !self.1.contains(Rights::READ) {
|
||||||
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.0.read_to_end(buf)
|
self.0.read_to_end(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,11 +84,11 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
self.dentry().inode().poll(mask, poller)
|
self.0.poll(mask, poller)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
self.dentry().inode().ioctl(cmd, arg)
|
self.0.ioctl(cmd, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
@ -109,6 +118,6 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
self.dentry().vnode().as_device()
|
self.dentry().inode().as_device()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ mod static_cap;
|
|||||||
|
|
||||||
use core::sync::atomic::{AtomicU32, Ordering};
|
use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::Device;
|
use crate::fs::device::Device;
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags,
|
AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use jinux_rights::Rights;
|
use jinux_rights::Rights;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -18,6 +20,10 @@ pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
|
|||||||
|
|
||||||
struct InodeHandle_ {
|
struct InodeHandle_ {
|
||||||
dentry: Arc<Dentry>,
|
dentry: Arc<Dentry>,
|
||||||
|
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
|
||||||
|
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
|
||||||
|
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
|
||||||
|
file_io: Option<Arc<dyn FileIo>>,
|
||||||
offset: Mutex<usize>,
|
offset: Mutex<usize>,
|
||||||
access_mode: AccessMode,
|
access_mode: AccessMode,
|
||||||
status_flags: AtomicU32,
|
status_flags: AtomicU32,
|
||||||
@ -26,6 +32,11 @@ struct InodeHandle_ {
|
|||||||
impl InodeHandle_ {
|
impl InodeHandle_ {
|
||||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
let mut offset = self.offset.lock();
|
||||||
|
|
||||||
|
if let Some(ref file_io) = self.file_io {
|
||||||
|
return file_io.read(buf);
|
||||||
|
}
|
||||||
|
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentry.inode().read_direct_at(*offset, buf)?
|
self.dentry.inode().read_direct_at(*offset, buf)?
|
||||||
} else {
|
} else {
|
||||||
@ -38,6 +49,11 @@ impl InodeHandle_ {
|
|||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
let mut offset = self.offset.lock();
|
||||||
|
|
||||||
|
if let Some(ref file_io) = self.file_io {
|
||||||
|
return file_io.write(buf);
|
||||||
|
}
|
||||||
|
|
||||||
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||||
*offset = self.dentry.inode_len();
|
*offset = self.dentry.inode_len();
|
||||||
}
|
}
|
||||||
@ -52,6 +68,10 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
||||||
|
if self.file_io.is_some() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "file io does not support read to end");
|
||||||
|
}
|
||||||
|
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentry.inode().read_direct_to_end(buf)?
|
self.dentry.inode().read_direct_to_end(buf)?
|
||||||
} else {
|
} else {
|
||||||
@ -118,6 +138,22 @@ impl InodeHandle_ {
|
|||||||
*offset += read_cnt;
|
*offset += read_cnt;
|
||||||
Ok(read_cnt)
|
Ok(read_cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
if let Some(ref file_io) = self.file_io {
|
||||||
|
return file_io.poll(mask, poller);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dentry.inode().poll(mask, poller)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
if let Some(ref file_io) = self.file_io {
|
||||||
|
return file_io.ioctl(cmd, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dentry.inode().ioctl(cmd, arg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for InodeHandle_ {
|
impl Debug for InodeHandle_ {
|
||||||
@ -137,3 +173,15 @@ impl<R> InodeHandle<R> {
|
|||||||
&self.0.dentry
|
&self.0.dentry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FileIo: Send + Sync + 'static {
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize>;
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize>;
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents;
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -91,7 +91,7 @@ impl DirOps for RootDirOps {
|
|||||||
SelfSymOps::new_inode(this_ptr.clone())
|
SelfSymOps::new_inode(this_ptr.clone())
|
||||||
} else if let Ok(pid) = name.parse::<Pid>() {
|
} else if let Ok(pid) = name.parse::<Pid>() {
|
||||||
let process_ref =
|
let process_ref =
|
||||||
process_table::pid_to_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
process_table::get_process(&pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
|
||||||
PidDirOps::new_inode(process_ref, this_ptr.clone())
|
PidDirOps::new_inode(process_ref, this_ptr.clone())
|
||||||
} else {
|
} else {
|
||||||
return_errno!(Errno::ENOENT);
|
return_errno!(Errno::ENOENT);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user