mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 01:43:22 +00:00
Add support for DevFS
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
cc2ab9d5d4
commit
6f321ad7b7
17
services/libs/jinux-std/src/device/mod.rs
Normal file
17
services/libs/jinux-std/src/device/mod.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
mod null;
|
||||||
|
pub mod tty;
|
||||||
|
mod zero;
|
||||||
|
|
||||||
|
use crate::fs::device::{add_node, Device, DeviceId, DeviceType};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Init the device node in fs, must be called after mounting rootfs.
|
||||||
|
pub fn init() -> Result<()> {
|
||||||
|
let null = Arc::new(null::Null);
|
||||||
|
add_node(null, "null")?;
|
||||||
|
let zero = Arc::new(zero::Zero);
|
||||||
|
add_node(zero, "zero")?;
|
||||||
|
let tty = tty::get_n_tty().clone();
|
||||||
|
add_node(tty, "tty")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
23
services/libs/jinux-std/src/device/null.rs
Normal file
23
services/libs/jinux-std/src/device/null.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use super::*;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub struct Null;
|
||||||
|
|
||||||
|
impl Device for Null {
|
||||||
|
fn type_(&self) -> DeviceType {
|
||||||
|
DeviceType::CharDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> DeviceId {
|
||||||
|
// Same value with Linux
|
||||||
|
DeviceId::new(1, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,7 @@
|
|||||||
use self::line_discipline::LineDiscipline;
|
use self::line_discipline::LineDiscipline;
|
||||||
|
use super::*;
|
||||||
use crate::driver::tty::TtyDriver;
|
use crate::driver::tty::TtyDriver;
|
||||||
use crate::fs::utils::{InodeMode, InodeType, IoEvents, Metadata};
|
use crate::fs::utils::{IoEvents, IoctlCmd, Poller};
|
||||||
use crate::fs::{
|
|
||||||
file_handle::FileLike,
|
|
||||||
utils::{IoctlCmd, Poller},
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::Pgid;
|
use crate::process::Pgid;
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
@ -51,7 +48,16 @@ impl Tty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileLike for Tty {
|
impl Device for Tty {
|
||||||
|
fn type_(&self) -> DeviceType {
|
||||||
|
DeviceType::CharDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> DeviceId {
|
||||||
|
// Same value with Linux
|
||||||
|
DeviceId::new(5, 0)
|
||||||
|
}
|
||||||
|
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
self.ldisc.read(buf)
|
self.ldisc.read(buf)
|
||||||
}
|
}
|
||||||
@ -110,25 +116,6 @@ impl FileLike for Tty {
|
|||||||
_ => todo!(),
|
_ => 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(0o666),
|
|
||||||
nlinks: 1,
|
|
||||||
uid: 0,
|
|
||||||
gid: 0,
|
|
||||||
rdev: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME: should we maintain a static console?
|
/// FIXME: should we maintain a static console?
|
26
services/libs/jinux-std/src/device/zero.rs
Normal file
26
services/libs/jinux-std/src/device/zero.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use super::*;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub struct Zero;
|
||||||
|
|
||||||
|
impl Device for Zero {
|
||||||
|
fn type_(&self) -> DeviceType {
|
||||||
|
DeviceType::CharDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> DeviceId {
|
||||||
|
// Same value with Linux
|
||||||
|
DeviceId::new(1, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
for byte in buf.iter_mut() {
|
||||||
|
*byte = 0;
|
||||||
|
}
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
pub use jinux_frame::arch::x86::device::serial::register_serial_input_callback;
|
pub use jinux_frame::arch::x86::device::serial::register_serial_input_callback;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
device::tty::{get_n_tty, Tty},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
tty::{get_n_tty, Tty},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
143
services/libs/jinux-std/src/fs/device.rs
Normal file
143
services/libs/jinux-std/src/fs/device.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
||||||
|
use crate::fs::utils::Dentry;
|
||||||
|
use crate::fs::utils::{InodeMode, InodeType, IoEvents, IoctlCmd, Poller};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// The abstract of device
|
||||||
|
pub trait Device: Sync + Send {
|
||||||
|
/// Return the device type.
|
||||||
|
fn type_(&self) -> DeviceType;
|
||||||
|
|
||||||
|
/// Return the device ID.
|
||||||
|
fn id(&self) -> DeviceId;
|
||||||
|
|
||||||
|
/// Read from the device.
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize>;
|
||||||
|
|
||||||
|
/// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Device type
|
||||||
|
pub enum DeviceType {
|
||||||
|
CharDevice,
|
||||||
|
BlockDevice,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Device Id
|
||||||
|
pub struct DeviceId(u64);
|
||||||
|
|
||||||
|
impl DeviceId {
|
||||||
|
pub fn new(major: u32, minor: u32) -> Self {
|
||||||
|
let major = major as u64;
|
||||||
|
let minor = minor as u64;
|
||||||
|
Self(
|
||||||
|
(major & 0xffff_f000) << 32
|
||||||
|
| (major & 0x0000_0fff) << 8
|
||||||
|
| (minor & 0xffff_ff00) << 12
|
||||||
|
| (minor & 0x0000_00ff),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn major(&self) -> u32 {
|
||||||
|
((self.0 >> 32) & 0xffff_f000 | (self.0 >> 8) & 0x0000_0fff) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn minor(&self) -> u32 {
|
||||||
|
((self.0 >> 12) & 0xffff_ff00 | self.0 & 0x0000_00ff) as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u64> for DeviceId {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a device node to FS for the device.
|
||||||
|
///
|
||||||
|
/// If the parent path is not existing, `mkdir -p` the parent path.
|
||||||
|
/// This function is used in registering device.
|
||||||
|
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
|
||||||
|
let mut dentry = {
|
||||||
|
let fs_resolver = FsResolver::new();
|
||||||
|
fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?
|
||||||
|
};
|
||||||
|
let mut relative_path = {
|
||||||
|
let relative_path = path.trim_start_matches('/');
|
||||||
|
if relative_path.is_empty() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid device path");
|
||||||
|
}
|
||||||
|
relative_path
|
||||||
|
};
|
||||||
|
|
||||||
|
while !relative_path.is_empty() {
|
||||||
|
let (next_name, path_remain) = if let Some((prefix, suffix)) = relative_path.split_once('/')
|
||||||
|
{
|
||||||
|
(prefix, suffix.trim_start_matches('/'))
|
||||||
|
} else {
|
||||||
|
(relative_path, "")
|
||||||
|
};
|
||||||
|
|
||||||
|
match dentry.lookup(next_name) {
|
||||||
|
Ok(next_dentry) => {
|
||||||
|
if path_remain.is_empty() {
|
||||||
|
return_errno_with_message!(Errno::EEXIST, "device node is existing");
|
||||||
|
}
|
||||||
|
dentry = next_dentry;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
if path_remain.is_empty() {
|
||||||
|
// Create the device node
|
||||||
|
dentry = dentry.mknod(
|
||||||
|
next_name,
|
||||||
|
InodeMode::from_bits_truncate(0o666),
|
||||||
|
device.clone(),
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
// Mkdir parent path
|
||||||
|
dentry = dentry.create(
|
||||||
|
next_name,
|
||||||
|
InodeType::Dir,
|
||||||
|
InodeMode::from_bits_truncate(0o755),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relative_path = path_remain;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(dentry)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete the device node from FS for the device.
|
||||||
|
///
|
||||||
|
/// This function is used in unregistering device.
|
||||||
|
pub fn delete_node(path: &str) -> Result<()> {
|
||||||
|
let abs_path = {
|
||||||
|
let device_path = path.trim_start_matches('/');
|
||||||
|
if device_path.is_empty() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid device path");
|
||||||
|
}
|
||||||
|
String::from("/dev") + "/" + device_path
|
||||||
|
};
|
||||||
|
|
||||||
|
let (parent_dentry, name) = {
|
||||||
|
let fs_resolver = FsResolver::new();
|
||||||
|
fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())?
|
||||||
|
};
|
||||||
|
|
||||||
|
parent_dentry.unlink(&name)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -3,7 +3,6 @@
|
|||||||
use crate::events::Observer;
|
use crate::events::Observer;
|
||||||
use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags};
|
use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::tty::get_n_tty;
|
|
||||||
|
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
|
|
||||||
@ -18,14 +17,7 @@ pub trait FileLike: Send + Sync + Any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
match cmd {
|
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
||||||
IoctlCmd::TCGETS => {
|
|
||||||
// FIXME: only a work around
|
|
||||||
let tty = get_n_tty();
|
|
||||||
tty.ioctl(cmd, arg)
|
|
||||||
}
|
|
||||||
_ => panic!("Ioctl unsupported"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self, _mask: IoEvents, _poller: Option<&Poller>) -> IoEvents {
|
fn poll(&self, _mask: IoEvents, _poller: Option<&Poller>) -> IoEvents {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use alloc::str;
|
use alloc::str;
|
||||||
use alloc::string::String;
|
|
||||||
|
|
||||||
use super::file_table::FileDescripter;
|
use super::file_table::FileDescripter;
|
||||||
use super::inode_handle::InodeHandle;
|
use super::inode_handle::InodeHandle;
|
||||||
@ -12,19 +11,21 @@ use super::utils::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RAM_FS: Arc<dyn FileSystem> = RamFS::new();
|
static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new(true);
|
||||||
static ref ROOT_DENTRY: Arc<Dentry> = {
|
static ref ROOT_DENTRY: Arc<Dentry> = {
|
||||||
fn init() -> Result<Arc<Dentry>> {
|
let vnode = Vnode::new(ROOT_FS.root_inode()).unwrap();
|
||||||
let root_vnode = Vnode::new(RAM_FS.root_inode())?;
|
Dentry::new_root(vnode)
|
||||||
Ok(Dentry::new_root(root_vnode))
|
|
||||||
}
|
|
||||||
init().unwrap()
|
|
||||||
};
|
};
|
||||||
static ref PROC_FS: Arc<dyn FileSystem> = ProcFS::new();
|
static ref PROC_FS: Arc<dyn FileSystem> = ProcFS::new();
|
||||||
static ref PROC_DENTRY: Arc<Dentry> = {
|
static ref PROC_DENTRY: Arc<Dentry> = {
|
||||||
let vnode = Vnode::new(PROC_FS.root_inode()).unwrap();
|
let vnode = Vnode::new(PROC_FS.root_inode()).unwrap();
|
||||||
Dentry::new_root(vnode)
|
Dentry::new_root(vnode)
|
||||||
};
|
};
|
||||||
|
static ref DEV_FS: Arc<dyn FileSystem> = RamFS::new(false);
|
||||||
|
static ref DEV_DENTRY: Arc<Dentry> = {
|
||||||
|
let vnode = Vnode::new(DEV_FS.root_inode()).unwrap();
|
||||||
|
Dentry::new_root(vnode)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FsResolver {
|
pub struct FsResolver {
|
||||||
@ -141,6 +142,13 @@ impl FsResolver {
|
|||||||
path.trim_start_matches('/'),
|
path.trim_start_matches('/'),
|
||||||
follow_tail_link,
|
follow_tail_link,
|
||||||
)?
|
)?
|
||||||
|
} else if path.starts_with("/dev") {
|
||||||
|
let path = path.strip_prefix("/dev").unwrap();
|
||||||
|
self.lookup_from_parent(
|
||||||
|
&DEV_DENTRY,
|
||||||
|
path.trim_start_matches('/'),
|
||||||
|
follow_tail_link,
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
self.lookup_from_parent(
|
self.lookup_from_parent(
|
||||||
&self.root,
|
&self.root,
|
||||||
|
@ -76,6 +76,10 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
self.dentry().vnode().poll(mask, poller)
|
self.dentry().vnode().poll(mask, poller)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
self.dentry().vnode().ioctl(cmd, arg)
|
||||||
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.dentry().vnode().metadata()
|
self.dentry().vnode().metadata()
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ use core::sync::atomic::{AtomicU32, Ordering};
|
|||||||
|
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, Metadata, Poller, SeekFrom, StatusFlags,
|
AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom,
|
||||||
|
StatusFlags,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Rights;
|
use crate::rights::Rights;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod device;
|
||||||
pub mod epoll;
|
pub mod epoll;
|
||||||
pub mod file_handle;
|
pub mod file_handle;
|
||||||
pub mod file_table;
|
pub mod file_table;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
|
||||||
use jinux_util::slot_vec::SlotVec;
|
use jinux_util::slot_vec::SlotVec;
|
||||||
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::device::Device;
|
||||||
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
use crate::fs::utils::{DirentVisitor, FileSystem, Inode, InodeMode, InodeType, Metadata};
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::{ProcFS, ProcInodeInfo};
|
use super::{ProcFS, ProcInodeInfo};
|
||||||
@ -78,23 +76,16 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
|||||||
|
|
||||||
fn set_mtime(&self, _time: Duration) {}
|
fn set_mtime(&self, _time: Duration) {}
|
||||||
|
|
||||||
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
|
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
Err(Error::new(Errno::EISDIR))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
|
fn mknod(
|
||||||
Err(Error::new(Errno::EISDIR))
|
&self,
|
||||||
}
|
_name: &str,
|
||||||
|
_mode: InodeMode,
|
||||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
|
_device: Arc<dyn Device>,
|
||||||
Err(Error::new(Errno::EISDIR))
|
) -> Result<Arc<dyn Inode>> {
|
||||||
}
|
|
||||||
|
|
||||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
|
|
||||||
Err(Error::new(Errno::EISDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mknod(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
|
||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,18 +177,6 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
|||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String> {
|
|
||||||
Err(Error::new(Errno::EISDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_link(&self, _target: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::EISDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ioctl(&self, _cmd: &IoctlCmd) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::EISDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sync(&self) -> Result<()> {
|
fn sync(&self) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{FileSystem, Inode, InodeMode, IoctlCmd, Metadata};
|
||||||
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::{ProcFS, ProcInodeInfo};
|
use super::{ProcFS, ProcInodeInfo};
|
||||||
@ -72,34 +70,6 @@ impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
|||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mknod(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readdir_at(&self, _offset: usize, _visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn link(&self, _old: &Arc<dyn Inode>, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlink(&self, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rmdir(&self, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lookup(&self, _name: &str) -> Result<Arc<dyn Inode>> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rename(&self, _old_name: &str, _target: &Arc<dyn Inode>, _new_name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String> {
|
fn read_link(&self) -> Result<String> {
|
||||||
Err(Error::new(Errno::EINVAL))
|
Err(Error::new(Errno::EINVAL))
|
||||||
}
|
}
|
||||||
@ -108,7 +78,7 @@ impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
|||||||
Err(Error::new(Errno::EINVAL))
|
Err(Error::new(Errno::EINVAL))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, _cmd: &IoctlCmd) -> Result<()> {
|
fn ioctl(&self, _cmd: IoctlCmd, _arg: usize) -> Result<i32> {
|
||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{FileSystem, Inode, InodeMode, IoctlCmd, Metadata};
|
||||||
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::{ProcFS, ProcInodeInfo};
|
use super::{ProcFS, ProcInodeInfo};
|
||||||
@ -67,34 +65,6 @@ impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
|||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mknod(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readdir_at(&self, _offset: usize, _visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn link(&self, _old: &Arc<dyn Inode>, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlink(&self, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rmdir(&self, _name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lookup(&self, _name: &str) -> Result<Arc<dyn Inode>> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rename(&self, _old_name: &str, _target: &Arc<dyn Inode>, _new_name: &str) -> Result<()> {
|
|
||||||
Err(Error::new(Errno::ENOTDIR))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String> {
|
fn read_link(&self) -> Result<String> {
|
||||||
self.inner.read_link()
|
self.inner.read_link()
|
||||||
}
|
}
|
||||||
@ -103,7 +73,7 @@ impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
|||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, _cmd: &IoctlCmd) -> Result<()> {
|
fn ioctl(&self, _cmd: IoctlCmd, _arg: usize) -> Result<i32> {
|
||||||
Err(Error::new(Errno::EPERM))
|
Err(Error::new(Errno::EPERM))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,28 +8,40 @@ use jinux_util::slot_vec::SlotVec;
|
|||||||
use spin::{RwLock, RwLockWriteGuard};
|
use spin::{RwLock, RwLockWriteGuard};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::fs::device::Device;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata,
|
||||||
|
Poller, SuperBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A volatile file system whose data and metadata exists only in memory.
|
||||||
pub struct RamFS {
|
pub struct RamFS {
|
||||||
metadata: RwLock<SuperBlock>,
|
metadata: RwLock<SuperBlock>,
|
||||||
root: Arc<RamInode>,
|
root: Arc<RamInode>,
|
||||||
inode_allocator: AtomicUsize,
|
inode_allocator: AtomicUsize,
|
||||||
|
flags: FsFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RamFS {
|
impl RamFS {
|
||||||
pub fn new() -> Arc<Self> {
|
pub fn new(use_pagecache: bool) -> Arc<Self> {
|
||||||
let sb = SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX);
|
let sb = SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX);
|
||||||
let root = Arc::new(RamInode(RwLock::new(Inode_::new_dir(
|
let root = Arc::new(RamInode(RwLock::new(Inode_::new_dir(
|
||||||
ROOT_INO,
|
ROOT_INO,
|
||||||
InodeMode::from_bits_truncate(0o755),
|
InodeMode::from_bits_truncate(0o755),
|
||||||
&sb,
|
&sb,
|
||||||
))));
|
))));
|
||||||
|
let flags = {
|
||||||
|
let mut flags = FsFlags::DENTRY_UNEVICTABLE;
|
||||||
|
if !use_pagecache {
|
||||||
|
flags |= FsFlags::NO_PAGECACHE;
|
||||||
|
}
|
||||||
|
flags
|
||||||
|
};
|
||||||
let ramfs = Arc::new(Self {
|
let ramfs = Arc::new(Self {
|
||||||
metadata: RwLock::new(sb),
|
metadata: RwLock::new(sb),
|
||||||
root,
|
root,
|
||||||
inode_allocator: AtomicUsize::new(ROOT_INO + 1),
|
inode_allocator: AtomicUsize::new(ROOT_INO + 1),
|
||||||
|
flags,
|
||||||
});
|
});
|
||||||
let mut root = ramfs.root.0.write();
|
let mut root = ramfs.root.0.write();
|
||||||
root.inner
|
root.inner
|
||||||
@ -64,7 +76,7 @@ impl FileSystem for RamFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> FsFlags {
|
fn flags(&self) -> FsFlags {
|
||||||
FsFlags::DENTRY_UNEVICTABLE
|
self.flags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +117,22 @@ impl Inode_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_device(
|
||||||
|
ino: usize,
|
||||||
|
mode: InodeMode,
|
||||||
|
sb: &SuperBlock,
|
||||||
|
device: Arc<dyn Device>,
|
||||||
|
) -> Self {
|
||||||
|
let type_ = device.type_();
|
||||||
|
let rdev = device.id().into();
|
||||||
|
Self {
|
||||||
|
inner: Inner::Device(device),
|
||||||
|
metadata: Metadata::new_device(ino, mode, sb, type_, rdev),
|
||||||
|
this: Weak::default(),
|
||||||
|
fs: Weak::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn inc_size(&mut self) {
|
pub fn inc_size(&mut self) {
|
||||||
self.metadata.size += 1;
|
self.metadata.size += 1;
|
||||||
self.metadata.blocks = (self.metadata.size + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
self.metadata.blocks = (self.metadata.size + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||||
@ -126,6 +154,7 @@ enum Inner {
|
|||||||
Dir(DirEntry),
|
Dir(DirEntry),
|
||||||
File,
|
File,
|
||||||
SymLink(Str256),
|
SymLink(Str256),
|
||||||
|
Device(Arc<dyn Device>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
@ -156,6 +185,13 @@ impl Inner {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_device(&self) -> Option<&Arc<dyn Device>> {
|
||||||
|
match self {
|
||||||
|
Inner::Device(device) => Some(device),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DirEntry {
|
struct DirEntry {
|
||||||
@ -320,11 +356,17 @@ impl Inode for RamInode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
if let Some(device) = self.0.read().inner.as_device() {
|
||||||
|
return device.read(buf);
|
||||||
|
}
|
||||||
return_errno_with_message!(Errno::EOPNOTSUPP, "direct read is not supported");
|
return_errno_with_message!(Errno::EOPNOTSUPP, "direct read is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
|
if let Some(device) = self.0.read().inner.as_device() {
|
||||||
|
return device.write(buf);
|
||||||
|
}
|
||||||
return_errno_with_message!(Errno::EOPNOTSUPP, "direct write is not supported");
|
return_errno_with_message!(Errno::EOPNOTSUPP, "direct write is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +394,41 @@ impl Inode for RamInode {
|
|||||||
self.0.write().metadata.mtime = time;
|
self.0.write().metadata.mtime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
fn mknod(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
mode: InodeMode,
|
||||||
|
device: Arc<dyn Device>,
|
||||||
|
) -> Result<Arc<dyn Inode>> {
|
||||||
|
if self.0.read().metadata.type_ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
|
let mut self_inode = self.0.write();
|
||||||
|
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
||||||
|
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
||||||
|
}
|
||||||
|
let device_inode = {
|
||||||
|
let fs = self_inode.fs.upgrade().unwrap();
|
||||||
|
let device_inode = Arc::new(RamInode(RwLock::new(Inode_::new_device(
|
||||||
|
fs.alloc_id(),
|
||||||
|
mode,
|
||||||
|
&fs.sb(),
|
||||||
|
device,
|
||||||
|
))));
|
||||||
|
device_inode.0.write().fs = self_inode.fs.clone();
|
||||||
|
device_inode.0.write().this = Arc::downgrade(&device_inode);
|
||||||
|
device_inode
|
||||||
|
};
|
||||||
|
self_inode
|
||||||
|
.inner
|
||||||
|
.as_direntry_mut()
|
||||||
|
.unwrap()
|
||||||
|
.append_entry(name, device_inode.clone());
|
||||||
|
self_inode.inc_size();
|
||||||
|
Ok(device_inode)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
if self.0.read().metadata.type_ != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
@ -631,12 +707,24 @@ impl Inode for RamInode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
if let Some(device) = self.0.read().inner.as_device() {
|
||||||
|
device.poll(mask, poller)
|
||||||
|
} else {
|
||||||
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
|
events & mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||||
Weak::upgrade(&self.0.read().fs).unwrap()
|
Weak::upgrade(&self.0.read().fs).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
return_errno!(Errno::ENOSYS);
|
if let Some(device) = self.0.read().inner.as_device() {
|
||||||
|
return device.ioctl(cmd, arg);
|
||||||
|
}
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use crate::device::tty::{get_n_tty, Tty};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::tty::{get_n_tty, Tty};
|
|
||||||
|
|
||||||
|
use super::device::Device;
|
||||||
use super::file_handle::FileLike;
|
use super::file_handle::FileLike;
|
||||||
use super::file_table::FileDescripter;
|
use super::file_table::FileDescripter;
|
||||||
use super::utils::{InodeMode, InodeType, IoEvents, Metadata, Poller, SeekFrom};
|
use super::utils::{InodeMode, InodeType, IoEvents, Metadata, Poller, SeekFrom};
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::fs::device::Device;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
@ -76,7 +78,26 @@ impl Dentry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let child = {
|
let child = {
|
||||||
let vnode = self.vnode.mknod(name, type_, mode)?;
|
let vnode = self.vnode.create(name, type_, mode)?;
|
||||||
|
let dentry = Dentry::new(name, Some(self.this()), vnode);
|
||||||
|
children.insert_dentry(&dentry);
|
||||||
|
dentry
|
||||||
|
};
|
||||||
|
Ok(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a dentry by making a device inode.
|
||||||
|
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
|
||||||
|
if self.vnode.inode_type() != InodeType::Dir {
|
||||||
|
return_errno!(Errno::ENOTDIR);
|
||||||
|
}
|
||||||
|
let mut children = self.children.lock();
|
||||||
|
if children.find_dentry(name).is_some() {
|
||||||
|
return_errno!(Errno::EEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = {
|
||||||
|
let vnode = self.vnode.mknod(name, mode, device)?;
|
||||||
let dentry = Dentry::new(name, Some(self.this()), vnode);
|
let dentry = Dentry::new(name, Some(self.this()), vnode);
|
||||||
children.insert_dentry(&dentry);
|
children.insert_dentry(&dentry);
|
||||||
dentry
|
dentry
|
||||||
|
@ -6,6 +6,7 @@ use core::time::Duration;
|
|||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use super::{DirentVisitor, FileSystem, IoEvents, IoctlCmd, Poller, SuperBlock};
|
use super::{DirentVisitor, FileSystem, IoEvents, IoctlCmd, Poller, SuperBlock};
|
||||||
|
use crate::fs::device::{Device, DeviceType};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
@ -20,6 +21,15 @@ pub enum InodeType {
|
|||||||
Socket = 0o140000,
|
Socket = 0o140000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<DeviceType> for InodeType {
|
||||||
|
fn from(type_: DeviceType) -> InodeType {
|
||||||
|
match type_ {
|
||||||
|
DeviceType::CharDevice => InodeType::CharDevice,
|
||||||
|
DeviceType::BlockDevice => InodeType::BlockDevice,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct InodeMode: u16 {
|
pub struct InodeMode: u16 {
|
||||||
/// set-user-ID
|
/// set-user-ID
|
||||||
@ -77,7 +87,7 @@ impl InodeMode {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
pub dev: usize,
|
pub dev: u64,
|
||||||
pub ino: usize,
|
pub ino: usize,
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
pub blk_size: usize,
|
pub blk_size: usize,
|
||||||
@ -90,7 +100,7 @@ pub struct Metadata {
|
|||||||
pub nlinks: usize,
|
pub nlinks: usize,
|
||||||
pub uid: usize,
|
pub uid: usize,
|
||||||
pub gid: usize,
|
pub gid: usize,
|
||||||
pub rdev: usize,
|
pub rdev: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Metadata {
|
impl Metadata {
|
||||||
@ -150,6 +160,30 @@ impl Metadata {
|
|||||||
rdev: 0,
|
rdev: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn new_device(
|
||||||
|
ino: usize,
|
||||||
|
mode: InodeMode,
|
||||||
|
sb: &SuperBlock,
|
||||||
|
type_: DeviceType,
|
||||||
|
rdev: u64,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
dev: 0,
|
||||||
|
ino,
|
||||||
|
size: 0,
|
||||||
|
blk_size: sb.bsize,
|
||||||
|
blocks: 0,
|
||||||
|
atime: Default::default(),
|
||||||
|
mtime: Default::default(),
|
||||||
|
ctime: Default::default(),
|
||||||
|
type_: InodeType::from(type_),
|
||||||
|
mode,
|
||||||
|
nlinks: 1,
|
||||||
|
uid: 0,
|
||||||
|
gid: 0,
|
||||||
|
rdev,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Inode: Any + Sync + Send {
|
pub trait Inode: Any + Sync + Send {
|
||||||
@ -167,33 +201,65 @@ pub trait Inode: Any + Sync + Send {
|
|||||||
|
|
||||||
fn set_mtime(&self, time: Duration);
|
fn set_mtime(&self, time: Duration);
|
||||||
|
|
||||||
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()>;
|
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn write_page(&self, idx: usize, frame: &VmFrame) -> Result<()>;
|
fn write_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
|
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
|
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>>;
|
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize>;
|
fn mknod(&self, name: &str, mode: InodeMode, dev: Arc<dyn Device>) -> Result<Arc<dyn Inode>> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()>;
|
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn unlink(&self, name: &str) -> Result<()>;
|
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn rmdir(&self, name: &str) -> Result<()>;
|
fn unlink(&self, name: &str) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>>;
|
fn rmdir(&self, name: &str) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()>;
|
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String>;
|
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::ENOTDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn write_link(&self, target: &str) -> Result<()>;
|
fn read_link(&self) -> Result<String> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &IoctlCmd) -> Result<()>;
|
fn write_link(&self, target: &str) -> Result<()> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
Err(Error::new(Errno::EISDIR))
|
||||||
|
}
|
||||||
|
|
||||||
fn sync(&self) -> Result<()>;
|
fn sync(&self) -> Result<()>;
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use super::{
|
use super::{
|
||||||
DirentVisitor, FsFlags, Inode, InodeMode, InodeType, IoEvents, Metadata, PageCache, Poller,
|
DirentVisitor, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, PageCache,
|
||||||
|
Poller,
|
||||||
};
|
};
|
||||||
|
use crate::fs::device::Device;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
use crate::vm::vmo::Vmo;
|
use crate::vm::vmo::Vmo;
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmIo;
|
use jinux_frame::vm::VmIo;
|
||||||
@ -145,8 +148,13 @@ impl Vnode {
|
|||||||
inner.inode.read_at(0, &mut buf[..file_len])
|
inner.inode.read_at(0, &mut buf[..file_len])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Self> {
|
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Self> {
|
||||||
let inode = self.inner.read().inode.mknod(name, type_, mode)?;
|
let inode = self.inner.read().inode.create(name, type_, mode)?;
|
||||||
|
Self::new(inode)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Self> {
|
||||||
|
let inode = self.inner.read().inode.mknod(name, mode, device)?;
|
||||||
Self::new(inode)
|
Self::new(inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +198,10 @@ impl Vnode {
|
|||||||
self.inner.read().inode.poll(mask, poller)
|
self.inner.read().inode.poll(mask, poller)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
self.inner.read().inode.ioctl(cmd, arg)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> Metadata {
|
pub fn metadata(&self) -> Metadata {
|
||||||
self.inner.read().inode.metadata()
|
self.inner.read().inode.metadata()
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ extern crate lru;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate controlled;
|
extern crate controlled;
|
||||||
|
|
||||||
|
pub mod device;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
@ -41,7 +42,6 @@ pub mod rights;
|
|||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod tty;
|
|
||||||
mod util;
|
mod util;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ pub fn init(ramdisk: &[u8]) {
|
|||||||
driver::init();
|
driver::init();
|
||||||
process::fifo_scheduler::init();
|
process::fifo_scheduler::init();
|
||||||
fs::initramfs::init(ramdisk).unwrap();
|
fs::initramfs::init(ramdisk).unwrap();
|
||||||
|
device::init().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_thread() {
|
fn init_thread() {
|
||||||
|
@ -11,13 +11,13 @@ use self::signal::sig_queues::SigQueues;
|
|||||||
use self::signal::signals::kernel::KernelSignal;
|
use self::signal::signals::kernel::KernelSignal;
|
||||||
use self::signal::signals::Signal;
|
use self::signal::signals::Signal;
|
||||||
use self::status::ProcessStatus;
|
use self::status::ProcessStatus;
|
||||||
|
use crate::device::tty::get_n_tty;
|
||||||
use crate::fs::file_table::FileTable;
|
use crate::fs::file_table::FileTable;
|
||||||
use crate::fs::fs_resolver::FsResolver;
|
use crate::fs::fs_resolver::FsResolver;
|
||||||
use crate::fs::utils::FileCreationMask;
|
use crate::fs::utils::FileCreationMask;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
use crate::thread::{allocate_tid, thread_table, Thread};
|
use crate::thread::{allocate_tid, thread_table, Thread};
|
||||||
use crate::tty::get_n_tty;
|
|
||||||
use crate::vm::vmar::Vmar;
|
use crate::vm::vmar::Vmar;
|
||||||
use jinux_frame::sync::WaitQueue;
|
use jinux_frame::sync::WaitQueue;
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ use crate::fs::{
|
|||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||||
use crate::tty::get_n_tty;
|
|
||||||
use crate::util::read_cstring_from_user;
|
use crate::util::read_cstring_from_user;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
@ -46,14 +45,6 @@ pub fn sys_openat(
|
|||||||
return Ok(SyscallReturn::Return(fd as _));
|
return Ok(SyscallReturn::Return(fd as _));
|
||||||
}
|
}
|
||||||
|
|
||||||
if dirfd == AT_FDCWD && pathname == CString::new("/dev/tty")? {
|
|
||||||
let tty_file = get_n_tty().clone();
|
|
||||||
let current = current!();
|
|
||||||
let mut file_table = current.file_table().lock();
|
|
||||||
let fd = file_table.insert(tty_file);
|
|
||||||
return Ok(SyscallReturn::Return(fd as _));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The common path
|
// The common path
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let file_handle = {
|
let file_handle = {
|
||||||
|
@ -81,7 +81,7 @@ pub const S_IFLNK: u32 = 0o120000;
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Stat {
|
pub struct Stat {
|
||||||
/// ID of device containing file
|
/// ID of device containing file
|
||||||
st_dev: usize,
|
st_dev: u64,
|
||||||
/// Inode number
|
/// Inode number
|
||||||
st_ino: usize,
|
st_ino: usize,
|
||||||
/// Number of hard links
|
/// Number of hard links
|
||||||
@ -95,7 +95,7 @@ pub struct Stat {
|
|||||||
/// Padding bytes
|
/// Padding bytes
|
||||||
__pad0: u32,
|
__pad0: u32,
|
||||||
/// Device ID (if special file)
|
/// Device ID (if special file)
|
||||||
st_rdev: usize,
|
st_rdev: u64,
|
||||||
/// Total size, in bytes
|
/// Total size, in bytes
|
||||||
st_size: isize,
|
st_size: isize,
|
||||||
/// Block size for filesystem I/O
|
/// Block size for filesystem I/O
|
||||||
@ -122,7 +122,7 @@ impl From<Metadata> for Stat {
|
|||||||
st_uid: info.uid as u32,
|
st_uid: info.uid as u32,
|
||||||
st_gid: info.gid as u32,
|
st_gid: info.gid as u32,
|
||||||
__pad0: 0,
|
__pad0: 0,
|
||||||
st_rdev: 0,
|
st_rdev: info.rdev,
|
||||||
st_size: info.size as isize,
|
st_size: info.size as isize,
|
||||||
st_blksize: info.blk_size as isize,
|
st_blksize: info.blk_size as isize,
|
||||||
st_blocks: (info.blocks * (info.blk_size / 512)) as isize, // Number of 512B blocks
|
st_blocks: (info.blocks * (info.blk_size / 512)) as isize, // Number of 512B blocks
|
||||||
|
Reference in New Issue
Block a user