Implement sys_pipe, fix sys_chdir, add dummy sys_setuid, and set an ephermal port when binding port 0

master
Jiajie Chen 6 years ago
parent bf5e176176
commit cca53536d1

@ -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

@ -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<u8>,
new_data: Condvar,
}
#[derive(Clone)]
pub struct Pipe {
data: Arc<Mutex<PipeData>>,
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<Metadata> { 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<Arc<INode>> { Err(FsError::NotDir) }
fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) }
fn link(&self, _name: &str, _other: &Arc<INode>) -> 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<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
fn as_any_ref(&self) -> &Any { self }
};
}
impl INode for Pipe {
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
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<usize> {
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!();
}

@ -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| {

@ -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)

@ -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)

@ -134,7 +134,7 @@ pub fn sys_exit(exit_code: isize) -> ! {
let mut proc = process();
let fds: Vec<usize> = 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);

Loading…
Cancel
Save