impl stdin & stdout as INode

master
WangRunji 6 years ago
parent ec0b1973a0
commit f97e8458b8

@ -1,8 +1,6 @@
use core::ops::Deref; use core::ops::Deref;
use alloc::string::String; use alloc::string::String;
use alloc::collections::VecDeque; use alloc::collections::VecDeque;
use sync::Condvar;
use sync::SpinNoIrqLock as Mutex;
pub fn get_line() -> String { pub fn get_line() -> String {
let mut s = String::new(); 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 { pub fn get_char() -> char {
CONSOLE_INPUT.pop() ::fs::STDIN.pop()
} }

@ -1,8 +1,10 @@
use simple_filesystem::*; use simple_filesystem::*;
use alloc::{boxed::Box, sync::Arc}; use alloc::{boxed::Box, sync::Arc, string::String, collections::VecDeque};
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::driver::ide; use arch::driver::ide;
use spin::Mutex; use sync::Condvar;
use sync::SpinNoIrqLock as Mutex;
use core::any::Any;
// Hard link user program // Hard link user program
#[cfg(target_arch = "riscv32")] #[cfg(target_arch = "riscv32")]
@ -102,3 +104,71 @@ impl BlockedDevice for ide::IDE {
self.write(block_id as u64, 1, buf).is_ok() 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::Error => Color::Red,
Level::Warn => Color::Yellow, Level::Warn => Color::Yellow,
Level::Info => Color::Blue, Level::Info => Color::Blue,
Level::Debug => Color::LightRed, Level::Debug => Color::Green,
Level::Trace => Color::DarkGray, Level::Trace => Color::DarkGray,
} }
} }

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

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