Implement dummy NamedPipe
This commit is contained in:
parent
ea64ddfde5
commit
715733f551
|
|
@ -73,12 +73,21 @@ impl FsResolver {
|
|||
let inode_handle = match self.lookup_inner(path, follow_tail_link) {
|
||||
Ok(dentry) => {
|
||||
let inode = dentry.inode();
|
||||
if inode.type_() == InodeType::SymLink
|
||||
&& creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||
&& !status_flags.contains(StatusFlags::O_PATH)
|
||||
{
|
||||
return_errno_with_message!(Errno::ELOOP, "file is a symlink");
|
||||
match inode.type_() {
|
||||
InodeType::NamedPipe => {
|
||||
warn!("NamedPipe doesn't support additional operation when opening.");
|
||||
debug!("Open NamedPipe. creation_flags:{:?}, status_flags:{:?}, access_mode:{:?}, inode_mode:{:?}",creation_flags,status_flags,access_mode,inode_mode);
|
||||
}
|
||||
InodeType::SymLink => {
|
||||
if creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||
&& !status_flags.contains(StatusFlags::O_PATH)
|
||||
{
|
||||
return_errno_with_message!(Errno::ELOOP, "file is a symlink");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if creation_flags.contains(CreationFlags::O_CREAT)
|
||||
&& creation_flags.contains(CreationFlags::O_EXCL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ pub mod file_handle;
|
|||
pub mod file_table;
|
||||
pub mod fs_resolver;
|
||||
pub mod inode_handle;
|
||||
pub mod named_pipe;
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod procfs;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{
|
||||
file_handle::FileLike,
|
||||
pipe::{self, PipeReader, PipeWriter},
|
||||
utils::{AccessMode, Metadata},
|
||||
};
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
prelude::*,
|
||||
process::signal::{Pollable, Poller},
|
||||
};
|
||||
|
||||
pub struct NamedPipe {
|
||||
reader: Arc<PipeReader>,
|
||||
writer: Arc<PipeWriter>,
|
||||
}
|
||||
|
||||
impl NamedPipe {
|
||||
pub fn new() -> Result<Self> {
|
||||
let (reader, writer) = pipe::new_pair()?;
|
||||
|
||||
Ok(Self { reader, writer })
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize) -> Result<Self> {
|
||||
let (reader, writer) = pipe::new_pair_with_capacity(capacity)?;
|
||||
|
||||
Ok(Self { reader, writer })
|
||||
}
|
||||
}
|
||||
|
||||
impl Pollable for NamedPipe {
|
||||
fn poll(&self, _mask: IoEvents, _poller: Option<&mut Poller>) -> IoEvents {
|
||||
warn!("Named pipe doesn't support poll now, return IoEvents::empty for now.");
|
||||
IoEvents::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl FileLike for NamedPipe {
|
||||
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
self.reader.read(writer)
|
||||
}
|
||||
|
||||
fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
self.writer.write(reader)
|
||||
}
|
||||
|
||||
fn access_mode(&self) -> AccessMode {
|
||||
AccessMode::O_RDWR
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.reader.metadata()
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ use atomic::Ordering;
|
|||
|
||||
use super::{
|
||||
file_handle::FileLike,
|
||||
utils::{AccessMode, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags},
|
||||
utils::{AccessMode, Channel, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags},
|
||||
};
|
||||
use crate::{
|
||||
events::{IoEvents, Observer},
|
||||
|
|
@ -18,6 +18,26 @@ use crate::{
|
|||
time::clocks::RealTimeCoarseClock,
|
||||
};
|
||||
|
||||
const DEFAULT_PIPE_BUF_SIZE: usize = 65536;
|
||||
|
||||
pub fn new_pair() -> Result<(Arc<PipeReader>, Arc<PipeWriter>)> {
|
||||
let (producer, consumer) = Channel::with_capacity(DEFAULT_PIPE_BUF_SIZE).split();
|
||||
|
||||
Ok((
|
||||
PipeReader::new(consumer, StatusFlags::empty())?,
|
||||
PipeWriter::new(producer, StatusFlags::empty())?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new_pair_with_capacity(capacity: usize) -> Result<(Arc<PipeReader>, Arc<PipeWriter>)> {
|
||||
let (producer, consumer) = Channel::with_capacity(capacity).split();
|
||||
|
||||
Ok((
|
||||
PipeReader::new(consumer, StatusFlags::empty())?,
|
||||
PipeWriter::new(producer, StatusFlags::empty())?,
|
||||
))
|
||||
}
|
||||
|
||||
pub struct PipeReader {
|
||||
consumer: Consumer<u8>,
|
||||
status_flags: AtomicU32,
|
||||
|
|
@ -228,7 +248,7 @@ mod test {
|
|||
W: Fn(Arc<PipeWriter>) + Sync + Send + 'static,
|
||||
R: Fn(Arc<PipeReader>) + Sync + Send + 'static,
|
||||
{
|
||||
let channel = Channel::new(1);
|
||||
let channel = Channel::with_capacity(1);
|
||||
let (writer, readr) = channel.split();
|
||||
|
||||
let writer = PipeWriter::new(writer, StatusFlags::empty()).unwrap();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ use crate::{
|
|||
events::IoEvents,
|
||||
fs::{
|
||||
device::Device,
|
||||
file_handle::FileLike,
|
||||
named_pipe::NamedPipe,
|
||||
utils::{
|
||||
CStr256, DirentVisitor, Extension, FallocMode, FileSystem, FsFlags, Inode, InodeMode,
|
||||
InodeType, IoctlCmd, Metadata, MknodType, PageCache, PageCacheBackend, SuperBlock,
|
||||
|
|
@ -151,6 +153,13 @@ impl Node {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_named_pipe(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||
Self {
|
||||
inner: Inner::NamedPipe(NamedPipe::new().unwrap()),
|
||||
metadata: InodeMeta::new(mode, uid, gid),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inc_size(&mut self) {
|
||||
self.metadata.size += 1;
|
||||
self.metadata.blocks = (self.metadata.size + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||
|
|
@ -253,6 +262,7 @@ enum Inner {
|
|||
SymLink(String),
|
||||
Device(Arc<dyn Device>),
|
||||
Socket,
|
||||
NamedPipe(NamedPipe),
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
|
|
@ -472,6 +482,17 @@ impl RamInode {
|
|||
})
|
||||
}
|
||||
|
||||
fn new_named_pipe(fs: &Arc<RamFS>, mode: InodeMode, uid: Uid, gid: Gid) -> Arc<Self> {
|
||||
Arc::new_cyclic(|weak_self| RamInode {
|
||||
node: RwMutex::new(Node::new_named_pipe(mode, uid, gid)),
|
||||
ino: fs.alloc_id(),
|
||||
typ: InodeType::NamedPipe,
|
||||
this: weak_self.clone(),
|
||||
fs: Arc::downgrade(fs),
|
||||
extension: Extension::new(),
|
||||
})
|
||||
}
|
||||
|
||||
fn find(&self, name: &str) -> Result<Arc<Self>> {
|
||||
if self.typ != InodeType::Dir {
|
||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||
|
|
@ -518,20 +539,20 @@ impl Inode for RamInode {
|
|||
let read_len = {
|
||||
let self_inode = self.node.read();
|
||||
|
||||
if let Some(device) = self_inode.inner.as_device() {
|
||||
device.read(writer)?
|
||||
} else {
|
||||
let Some(page_cache) = self_inode.inner.as_file() else {
|
||||
return_errno_with_message!(Errno::EISDIR, "read is not supported");
|
||||
};
|
||||
let (offset, read_len) = {
|
||||
let file_size = self_inode.metadata.size;
|
||||
let start = file_size.min(offset);
|
||||
let end = file_size.min(offset + writer.avail());
|
||||
(start, end - start)
|
||||
};
|
||||
page_cache.pages().read(offset, writer)?;
|
||||
read_len
|
||||
match &self_inode.inner {
|
||||
Inner::File(page_cache) => {
|
||||
let (offset, read_len) = {
|
||||
let file_size = self_inode.metadata.size;
|
||||
let start = file_size.min(offset);
|
||||
let end = file_size.min(offset + writer.avail());
|
||||
(start, end - start)
|
||||
};
|
||||
page_cache.pages().read(offset, writer)?;
|
||||
read_len
|
||||
}
|
||||
Inner::Device(device) => device.read(writer)?,
|
||||
Inner::NamedPipe(named_pipe) => named_pipe.read(writer)?,
|
||||
_ => return_errno_with_message!(Errno::EISDIR, "read is not supported"),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -548,34 +569,36 @@ impl Inode for RamInode {
|
|||
let write_len = reader.remain();
|
||||
let self_inode = self.node.upread();
|
||||
|
||||
if let Some(device) = self_inode.inner.as_device() {
|
||||
let device_written_len = device.write(reader)?;
|
||||
let mut self_inode = self_inode.upgrade();
|
||||
let now = now();
|
||||
self_inode.set_mtime(now);
|
||||
self_inode.set_ctime(now);
|
||||
return Ok(device_written_len);
|
||||
}
|
||||
match &self_inode.inner {
|
||||
Inner::File(page_cache) => {
|
||||
let file_size = self_inode.metadata.size;
|
||||
let new_size = offset + write_len;
|
||||
let should_expand_size = new_size > file_size;
|
||||
if should_expand_size {
|
||||
page_cache.resize(new_size)?;
|
||||
}
|
||||
page_cache.pages().write(offset, reader)?;
|
||||
|
||||
let Some(page_cache) = self_inode.inner.as_file() else {
|
||||
return_errno_with_message!(Errno::EISDIR, "write is not supported");
|
||||
let mut self_inode = self_inode.upgrade();
|
||||
let now = now();
|
||||
self_inode.set_mtime(now);
|
||||
self_inode.set_ctime(now);
|
||||
if should_expand_size {
|
||||
self_inode.resize(new_size);
|
||||
}
|
||||
}
|
||||
Inner::Device(device) => {
|
||||
device.write(reader)?;
|
||||
let mut self_inode = self_inode.upgrade();
|
||||
let now = now();
|
||||
self_inode.set_mtime(now);
|
||||
self_inode.set_ctime(now);
|
||||
}
|
||||
Inner::NamedPipe(named_pipe) => {
|
||||
named_pipe.write(reader)?;
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EISDIR, "write is not supported"),
|
||||
};
|
||||
let file_size = self_inode.metadata.size;
|
||||
let new_size = offset + write_len;
|
||||
let should_expand_size = new_size > file_size;
|
||||
if should_expand_size {
|
||||
page_cache.resize(new_size)?;
|
||||
}
|
||||
page_cache.pages().write(offset, reader)?;
|
||||
|
||||
let mut self_inode = self_inode.upgrade();
|
||||
let now = now();
|
||||
self_inode.set_mtime(now);
|
||||
self_inode.set_ctime(now);
|
||||
if should_expand_size {
|
||||
self_inode.resize(new_size);
|
||||
}
|
||||
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
|
|
@ -698,7 +721,12 @@ impl Inode for RamInode {
|
|||
device,
|
||||
)
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EPERM, "unimplemented file types"),
|
||||
MknodType::NamedPipeNode => RamInode::new_named_pipe(
|
||||
&self.fs.upgrade().unwrap(),
|
||||
mode,
|
||||
Uid::new_root(),
|
||||
Gid::new_root(),
|
||||
),
|
||||
};
|
||||
|
||||
let mut self_inode = self_inode.upgrade();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl<T> Channel<T> {
|
|||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the given capacity is zero.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
let common = Arc::new(Common::new(capacity));
|
||||
|
||||
let producer = Producer(Fifo::new(common.clone()));
|
||||
|
|
@ -391,7 +391,7 @@ mod test {
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct NonCopy(Arc<usize>);
|
||||
|
||||
let channel = Channel::new(16);
|
||||
let channel = Channel::with_capacity(16);
|
||||
let (producer, consumer) = channel.split();
|
||||
|
||||
let data = NonCopy(Arc::new(99));
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ impl Connected {
|
|||
addr: Option<UnixSocketAddrBound>,
|
||||
peer_addr: Option<UnixSocketAddrBound>,
|
||||
) -> (Connected, Connected) {
|
||||
let (writer_this, reader_peer) = Channel::new(DAFAULT_BUF_SIZE).split();
|
||||
let (writer_peer, reader_this) = Channel::new(DAFAULT_BUF_SIZE).split();
|
||||
let (writer_this, reader_peer) = Channel::with_capacity(DAFAULT_BUF_SIZE).split();
|
||||
let (writer_peer, reader_this) = Channel::with_capacity(DAFAULT_BUF_SIZE).split();
|
||||
|
||||
let this = Connected {
|
||||
addr: addr.clone(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
fs::{
|
||||
file_table::FileDesc,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
utils::{InodeMode, InodeType},
|
||||
utils::{InodeMode, InodeType, MknodType},
|
||||
},
|
||||
prelude::*,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
|
|
@ -53,7 +53,10 @@ pub fn sys_mknodat(
|
|||
let device_inode = get_device(dev)?;
|
||||
let _ = dir_dentry.mknod(&name, inode_mode, device_inode.into())?;
|
||||
}
|
||||
InodeType::NamedPipe | InodeType::Socket => {
|
||||
InodeType::NamedPipe => {
|
||||
let _ = dir_dentry.mknod(&name, inode_mode, MknodType::NamedPipeNode)?;
|
||||
}
|
||||
InodeType::Socket => {
|
||||
return_errno_with_message!(Errno::EINVAL, "unsupported file types")
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EPERM, "unimplemented file types"),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use super::SyscallReturn;
|
|||
use crate::{
|
||||
fs::{
|
||||
file_table::{FdFlags, FileDesc},
|
||||
pipe::{PipeReader, PipeWriter},
|
||||
utils::{Channel, CreationFlags, StatusFlags},
|
||||
pipe,
|
||||
utils::CreationFlags,
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
|
|
@ -13,16 +13,7 @@ use crate::{
|
|||
pub fn sys_pipe2(fds: Vaddr, flags: u32, ctx: &Context) -> Result<SyscallReturn> {
|
||||
debug!("flags: {:?}", flags);
|
||||
|
||||
let (pipe_reader, pipe_writer) = {
|
||||
let (producer, consumer) = Channel::new(PIPE_BUF_SIZE).split();
|
||||
|
||||
let status_flags = StatusFlags::from_bits_truncate(flags);
|
||||
|
||||
(
|
||||
PipeReader::new(consumer, status_flags)?,
|
||||
PipeWriter::new(producer, status_flags)?,
|
||||
)
|
||||
};
|
||||
let (pipe_reader, pipe_writer) = pipe::new_pair()?;
|
||||
|
||||
let fd_flags = if CreationFlags::from_bits_truncate(flags).contains(CreationFlags::O_CLOEXEC) {
|
||||
FdFlags::CLOEXEC
|
||||
|
|
@ -57,5 +48,3 @@ struct PipeFds {
|
|||
reader_fd: FileDesc,
|
||||
writer_fd: FileDesc,
|
||||
}
|
||||
|
||||
const PIPE_BUF_SIZE: usize = 65536;
|
||||
|
|
|
|||
Loading…
Reference in New Issue