From cca53536d1253f2b9da89e9a439e0080b9ca2737 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 7 Mar 2019 19:31:46 +0800 Subject: [PATCH] Implement sys_pipe, fix sys_chdir, add dummy sys_setuid, and set an ephermal port when binding port 0 --- kernel/src/fs/mod.rs | 2 + kernel/src/fs/pipe.rs | 105 +++++++++++++++++++++++++++++++++++++ kernel/src/syscall/fs.rs | 27 +++++++++- kernel/src/syscall/mod.rs | 5 ++ kernel/src/syscall/net.rs | 9 +++- kernel/src/syscall/proc.rs | 2 +- 6 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 kernel/src/fs/pipe.rs diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 468329b..44b5b91 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -11,10 +11,12 @@ use crate::drivers::block::virtio_blk::VirtIOBlkDriver; pub use self::file::*; pub use self::stdio::{STDIN, STDOUT}; +pub use self::pipe::Pipe; mod file; mod stdio; mod device; +mod pipe; lazy_static! { /// The root of file system diff --git a/kernel/src/fs/pipe.rs b/kernel/src/fs/pipe.rs new file mode 100644 index 0000000..c905d03 --- /dev/null +++ b/kernel/src/fs/pipe.rs @@ -0,0 +1,105 @@ +//! Implement INode for Pipe + +use alloc::{collections::vec_deque::VecDeque, string::String, sync::Arc}; +use core::any::Any; + +use rcore_fs::vfs::*; + +use crate::sync::Condvar; +use crate::sync::SpinNoIrqLock as Mutex; + +#[derive(Clone)] +pub enum PipeEnd { + Read, + Write, +} + +pub struct PipeData { + buf: VecDeque, + new_data: Condvar, +} + +#[derive(Clone)] +pub struct Pipe { + data: Arc>, + direction: PipeEnd, +} + +impl Pipe { + /// Create a pair of INode: (read, write) + pub fn create_pair() -> (Pipe, Pipe) { + let inner = PipeData { + buf: VecDeque::new(), + new_data: Condvar::new(), + }; + let data = Arc::new(Mutex::new(inner)); + ( + Pipe { + data: data.clone(), + direction: PipeEnd::Read, + }, + Pipe { + data: data.clone(), + direction: PipeEnd::Write, + }, + ) + } + + pub fn can_read(&self) -> bool { + if let PipeEnd::Read = self.direction { + self.data.lock().buf.len() > 0 + } else { + false + } + } +} + +// TODO: better way to provide default impl? +macro_rules! impl_inode { + () => { + fn metadata(&self) -> Result { Err(FsError::NotSupported) } + fn sync(&self) -> Result<()> { Ok(()) } + fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) } + fn create(&self, _name: &str, _type_: FileType, _mode: u32) -> Result> { Err(FsError::NotDir) } + fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) } + fn link(&self, _name: &str, _other: &Arc) -> Result<()> { Err(FsError::NotDir) } + fn rename(&self, _old_name: &str, _new_name: &str) -> Result<()> { Err(FsError::NotDir) } + fn move_(&self, _old_name: &str, _target: &Arc, _new_name: &str) -> Result<()> { Err(FsError::NotDir) } + fn find(&self, _name: &str) -> Result> { Err(FsError::NotDir) } + fn get_entry(&self, _id: usize) -> Result { Err(FsError::NotDir) } + fn fs(&self) -> Arc { unimplemented!() } + fn as_any_ref(&self) -> &Any { self } + }; +} + +impl INode for Pipe { + fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + if let PipeEnd::Read = self.direction { + let mut data = self.data.lock(); + if let Some(ch) = data.buf.pop_front() { + buf[0] = ch; + Ok(1) + } else { + Ok(0) + } + } else { + Ok(0) + } + } + + fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { + if let PipeEnd::Write = self.direction { + if buf.len() > 0 { + let mut data = self.data.lock(); + data.buf.push_back(buf[0]); + data.new_data.notify_all(); + Ok(1) + } else { + Ok(0) + } + } else { + Ok(0) + } + } + impl_inode!(); +} diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 39eedda..40eca94 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -454,8 +454,14 @@ pub fn sys_chdir(path: *const u8) -> SysResult { if info.type_ != FileType::Dir { return Err(SysError::ENOTDIR); } - // FIXME: calculate absolute path of new cwd - proc.cwd += &path; + + if path.len() > 0 && path.as_bytes()[0] == b'/' { + // absolute + proc.cwd = path; + } else { + // relative + proc.cwd += &path; + } Ok(0) } @@ -517,6 +523,23 @@ pub fn sys_unlink(path: *const u8) -> SysResult { Ok(0) } +pub fn sys_pipe(fds: *mut u32) -> SysResult { + info!("pipe: fds: {:?}", fds); + + let mut proc = process(); + proc.memory_set.check_mut_array(fds, 2); + let (read, write) = Pipe::create_pair(); + let read_fd = proc.get_free_inode(); + + let read_fd = proc.get_free_inode(); + proc.files.insert(read_fd, FileLike::File(FileHandle::new(Arc::new(read), OpenOptions { read: true, write: false, append: false }))); + + let write_fd = proc.get_free_inode(); + proc.files.insert(write_fd, FileLike::File(FileHandle::new(Arc::new(write), OpenOptions { read: false, write: true, append: false }))); + + Ok(0) +} + impl Process { fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> { self.files.get_mut(&fd).ok_or(SysError::EBADF).and_then(|f| { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 3424215..b2fa883 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -50,6 +50,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 019 => sys_readv(args[0], args[1] as *const IoVec, args[2]), 020 => sys_writev(args[0], args[1] as *const IoVec, args[2]), 021 => sys_access(args[0] as *const u8, args[1]), + 022 => sys_pipe(args[0] as *mut u32), 023 => sys_select(args[0], args[1] as *mut u32, args[2] as *mut u32, args[3] as *mut u32, args[4] as *const TimeVal), 024 => sys_yield(), 033 => sys_dup2(args[0], args[1]), @@ -148,6 +149,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { warn!("sys_getegid is unimplemented"); Ok(0) } + 112 => { + warn!("sys_setsid is unimplemented"); + Ok(0) + } 131 => { warn!("sys_sigaltstack is unimplemented"); Ok(0) diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 89836c6..2c55eb9 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -482,7 +482,10 @@ pub fn sys_bind(fd: usize, addr: *const SockaddrIn, len: usize) -> SysResult { } let sockaddr_in = unsafe { &*(addr) }; - let endpoint = sockaddr_in.to_endpoint()?; + let mut endpoint = sockaddr_in.to_endpoint()?; + if endpoint.port == 0 { + endpoint.port = get_ephemeral_port(); + } let iface = &*(NET_DRIVERS.read()[0]); let wrapper = &mut proc.get_socket_mut(fd)?; @@ -508,7 +511,9 @@ pub fn sys_listen(fd: usize, backlog: usize) -> SysResult { match socket.listen(endpoint) { Ok(()) => Ok(0), - Err(_) => Err(SysError::EINVAL), + Err(err) => { + Err(SysError::EINVAL) + }, } } else { Err(SysError::EINVAL) diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 4fbd9ab..e8bd400 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -134,7 +134,7 @@ pub fn sys_exit(exit_code: isize) -> ! { let mut proc = process(); let fds: Vec = proc.files.keys().cloned().collect(); for fd in fds.into_iter() { - sys_close_internal(&mut proc, fd); + sys_close_internal(&mut proc, fd).unwrap(); } drop(proc);