impl stdin & stdout as INode

master
WangRunji 6 years ago
parent ec0b1973a0
commit f97e8458b8

@ -1,8 +1,6 @@
use core::ops::Deref;
use alloc::string::String;
use alloc::collections::VecDeque;
use sync::Condvar;
use sync::SpinNoIrqLock as Mutex;
pub fn get_line() -> String {
let mut s = String::new();
@ -27,32 +25,6 @@ pub fn get_line() -> String {
}
}
#[derive(Default)]
pub struct InputQueue {
buf: Mutex<VecDeque<char>>,
pushed: Condvar,
}
impl InputQueue {
pub fn push(&self, c: char) {
self.buf.lock().push_back(c);
self.pushed.notify_one();
}
pub fn pop(&self) -> char {
loop {
let ret = self.buf.lock().pop_front();
match ret {
Some(c) => return c,
None => self.pushed._wait(),
}
}
}
}
lazy_static! {
pub static ref CONSOLE_INPUT: InputQueue = InputQueue::default();
}
pub fn get_char() -> char {
CONSOLE_INPUT.pop()
::fs::STDIN.pop()
}

@ -1,8 +1,10 @@
use simple_filesystem::*;
use alloc::{boxed::Box, sync::Arc};
use alloc::{boxed::Box, sync::Arc, string::String, collections::VecDeque};
#[cfg(target_arch = "x86_64")]
use arch::driver::ide;
use spin::Mutex;
use sync::Condvar;
use sync::SpinNoIrqLock as Mutex;
use core::any::Any;
// Hard link user program
#[cfg(target_arch = "riscv32")]
@ -102,3 +104,71 @@ impl BlockedDevice for ide::IDE {
self.write(block_id as u64, 1, buf).is_ok()
}
}
#[derive(Default)]
pub struct Stdin {
buf: Mutex<VecDeque<char>>,
pushed: Condvar,
}
impl Stdin {
pub fn push(&self, c: char) {
self.buf.lock().push_back(c);
self.pushed.notify_one();
}
pub fn pop(&self) -> char {
loop {
let ret = self.buf.lock().pop_front();
match ret {
Some(c) => return c,
None => self.pushed._wait(),
}
}
}
}
#[derive(Default)]
pub struct Stdout;
lazy_static! {
pub static ref STDIN: Arc<Stdin> = Arc::new(Stdin::default());
pub static ref STDOUT: Arc<Stdout> = Arc::new(Stdout::default());
}
// TODO: better way to provide default impl?
macro_rules! impl_inode {
() => {
fn info(&self) -> Result<FileInfo> { unimplemented!() }
fn sync(&self) -> Result<()> { unimplemented!() }
fn resize(&self, len: usize) -> Result<()> { unimplemented!() }
fn create(&self, name: &str, type_: FileType) -> Result<Arc<INode>> { unimplemented!() }
fn unlink(&self, name: &str) -> Result<()> { unimplemented!() }
fn link(&self, name: &str, other: &Arc<INode>) -> Result<()> { unimplemented!() }
fn rename(&self, old_name: &str, new_name: &str) -> Result<()> { unimplemented!() }
fn move_(&self, old_name: &str, target: &Arc<INode>, new_name: &str) -> Result<()> { unimplemented!() }
fn find(&self, name: &str) -> Result<Arc<INode>> { unimplemented!() }
fn get_entry(&self, id: usize) -> Result<String> { unimplemented!() }
fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
fn as_any_ref(&self) -> &Any { self }
};
}
impl INode for Stdin {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
buf[0] = self.pop() as u8;
Ok(1)
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> { unimplemented!() }
impl_inode!();
}
impl INode for Stdout {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> { unimplemented!() }
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
use core::str;
let s = str::from_utf8(buf).map_err(|_| ())?;
print!("{}", s);
Ok(buf.len())
}
impl_inode!();
}

@ -78,7 +78,7 @@ impl From<Level> for Color {
Level::Error => Color::Red,
Level::Warn => Color::Yellow,
Level::Info => Color::Blue,
Level::Debug => Color::LightRed,
Level::Debug => Color::Green,
Level::Trace => Color::DarkGray,
}
}

@ -59,27 +59,16 @@ fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
// TODO: check ptr
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
match fd {
0 => unimplemented!(),
1 | 2 => return Err(SysError::InvalidFile),
_ => { get_file(fd)?.lock().read(slice)?; }
}
Ok(0)
let len = get_file(fd)?.lock().read(slice)?;
Ok(len as i32)
}
fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
// TODO: check ptr
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
let slice = unsafe { slice::from_raw_parts(base, len) };
match fd {
0 => return Err(SysError::InvalidFile),
1 | 2 => {
let s = str::from_utf8(slice).map_err(|_| SysError::InvalidArgument)?;
print!("{}", s);
},
_ => { get_file(fd)?.lock().write(slice)?; }
}
Ok(0)
let len = get_file(fd)?.lock().write(slice)?;
Ok(len as i32)
}
fn sys_open(path: *const u8, flags: usize) -> SysResult {
@ -87,25 +76,22 @@ fn sys_open(path: *const u8, flags: usize) -> SysResult {
let path = unsafe { util::from_cstr(path) };
let flags = VfsFlags::from_ucore_flags(flags);
info!("open: path: {:?}, flags: {:?}", path, flags);
match path {
"stdin:" => return Ok(0),
"stdout:" => return Ok(1),
"stderr:" => return Ok(2),
_ => {}
}
let inode = ::fs::ROOT_INODE.lookup(path)?;
let files = &mut process().files;
let fd = (3..).find(|i| !files.contains_key(i)).unwrap();
let (fd, inode) = match path {
"stdin:" => (0, ::fs::STDIN.clone() as Arc<INode>),
"stdout:" => (1, ::fs::STDOUT.clone() as Arc<INode>),
_ => {
let fd = (3..).find(|i| !process().files.contains_key(i)).unwrap();
let inode = ::fs::ROOT_INODE.lookup(path)?;
(fd, inode)
}
};
let file = File::new(inode, flags.contains(VfsFlags::READABLE), flags.contains(VfsFlags::WRITABLE));
files.insert(fd, Arc::new(Mutex::new(file)));
process().files.insert(fd, Arc::new(Mutex::new(file)));
Ok(fd as i32)
}
fn sys_close(fd: usize) -> SysResult {
info!("close: fd: {:?}", fd);
if fd < 3 {
return Ok(0);
}
match process().files.remove(&fd) {
Some(_) => Ok(0),
None => Err(SysError::InvalidFile),

@ -22,5 +22,5 @@ pub fn error(tf: &TrapFrame) -> ! {
}
pub fn serial(c: char) {
::console::CONSOLE_INPUT.push(c);
::fs::STDIN.push(c);
}
Loading…
Cancel
Save