arceos_posix_api/imp/
stdio.rsuse axerrno::AxResult;
use axio::{BufReader, prelude::*};
use axsync::Mutex;
#[cfg(feature = "fd")]
use {alloc::sync::Arc, axerrno::LinuxError, axerrno::LinuxResult, axio::PollState};
fn console_read_bytes(buf: &mut [u8]) -> AxResult<usize> {
let len = axhal::console::read_bytes(buf);
for c in &mut buf[..len] {
if *c == b'\r' {
*c = b'\n';
}
}
Ok(len)
}
fn console_write_bytes(buf: &[u8]) -> AxResult<usize> {
axhal::console::write_bytes(buf);
Ok(buf.len())
}
struct StdinRaw;
struct StdoutRaw;
impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
let mut read_len = 0;
while read_len < buf.len() {
let len = console_read_bytes(buf[read_len..].as_mut())?;
if len == 0 {
break;
}
read_len += len;
}
Ok(read_len)
}
}
impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> AxResult<usize> {
console_write_bytes(buf)
}
fn flush(&mut self) -> AxResult {
Ok(())
}
}
pub struct Stdin {
inner: &'static Mutex<BufReader<StdinRaw>>,
}
impl Stdin {
fn read_blocked(&self, buf: &mut [u8]) -> AxResult<usize> {
let read_len = self.inner.lock().read(buf)?;
if buf.is_empty() || read_len > 0 {
return Ok(read_len);
}
loop {
let read_len = self.inner.lock().read(buf)?;
if read_len > 0 {
return Ok(read_len);
}
crate::sys_sched_yield();
}
}
}
impl Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
self.read_blocked(buf)
}
}
pub struct Stdout {
inner: &'static Mutex<StdoutRaw>,
}
impl Write for Stdout {
fn write(&mut self, buf: &[u8]) -> AxResult<usize> {
self.inner.lock().write(buf)
}
fn flush(&mut self) -> AxResult {
self.inner.lock().flush()
}
}
pub fn stdin() -> Stdin {
static INSTANCE: Mutex<BufReader<StdinRaw>> = Mutex::new(BufReader::new(StdinRaw));
Stdin { inner: &INSTANCE }
}
pub fn stdout() -> Stdout {
static INSTANCE: Mutex<StdoutRaw> = Mutex::new(StdoutRaw);
Stdout { inner: &INSTANCE }
}
#[cfg(feature = "fd")]
impl super::fd_ops::FileLike for Stdin {
fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
Ok(self.read_blocked(buf)?)
}
fn write(&self, _buf: &[u8]) -> LinuxResult<usize> {
Err(LinuxError::EPERM)
}
fn stat(&self) -> LinuxResult<crate::ctypes::stat> {
let st_mode = 0o20000 | 0o440u32; Ok(crate::ctypes::stat {
st_ino: 1,
st_nlink: 1,
st_mode,
..Default::default()
})
}
fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
self
}
fn poll(&self) -> LinuxResult<PollState> {
Ok(PollState {
readable: true,
writable: true,
})
}
fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
Ok(())
}
}
#[cfg(feature = "fd")]
impl super::fd_ops::FileLike for Stdout {
fn read(&self, _buf: &mut [u8]) -> LinuxResult<usize> {
Err(LinuxError::EPERM)
}
fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
Ok(self.inner.lock().write(buf)?)
}
fn stat(&self) -> LinuxResult<crate::ctypes::stat> {
let st_mode = 0o20000 | 0o220u32; Ok(crate::ctypes::stat {
st_ino: 1,
st_nlink: 1,
st_mode,
..Default::default()
})
}
fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
self
}
fn poll(&self) -> LinuxResult<PollState> {
Ok(PollState {
readable: true,
writable: true,
})
}
fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
Ok(())
}
}