diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 36ede46..b17ca55 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -345,12 +345,12 @@ dependencies = [ [[package]] name = "rcore-fs" version = "0.1.0" -source = "git+https://github.com/rcore-os/rcore-fs#c611248f800e946acf44d64b218aeb8fc6751640" +source = "git+https://github.com/rcore-os/rcore-fs#d7a2006cc316c98b7050aec63a2770dd690a4a80" [[package]] name = "rcore-fs-sfs" version = "0.1.0" -source = "git+https://github.com/rcore-os/rcore-fs#c611248f800e946acf44d64b218aeb8fc6751640" +source = "git+https://github.com/rcore-os/rcore-fs#d7a2006cc316c98b7050aec63a2770dd690a4a80" dependencies = [ "bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/fs/file.rs b/kernel/src/fs/file.rs index ecddfff..dfb291f 100644 --- a/kernel/src/fs/file.rs +++ b/kernel/src/fs/file.rs @@ -2,7 +2,7 @@ use alloc::{string::String, sync::Arc}; -use rcore_fs::vfs::{FsError, INode, Metadata, Result}; +use rcore_fs::vfs::{FsError, INode, Metadata, PollStatus, Result}; #[derive(Clone)] pub struct FileHandle { @@ -108,4 +108,12 @@ impl FileHandle { self.offset += 1; Ok(name) } + + pub fn poll(&self) -> Result { + self.inode.poll() + } + + pub fn io_control(&self, cmd: u32, arg: u32) -> Result<()> { + self.inode.io_control(cmd, arg) + } } diff --git a/kernel/src/fs/file_like.rs b/kernel/src/fs/file_like.rs index bd1f660..47a3cc6 100644 --- a/kernel/src/fs/file_like.rs +++ b/kernel/src/fs/file_like.rs @@ -2,8 +2,9 @@ use core::fmt; use super::FileHandle; use crate::net::Socket; -use crate::syscall::SysResult; +use crate::syscall::{SysError, SysResult}; use alloc::boxed::Box; +use rcore_fs::vfs::PollStatus; // TODO: merge FileLike to FileHandle ? // TODO: fix dup and remove Clone @@ -30,12 +31,22 @@ impl FileLike { } pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult { match self { - FileLike::File(file) => { - warn!("ioctl not implemented for file"); - Ok(0) + FileLike::File(file) => file.io_control(request as u32, arg1 as u32)?, + FileLike::Socket(socket) => { + socket.ioctl(request, arg1, arg2, arg3)?; } - FileLike::Socket(socket) => socket.ioctl(request, arg1, arg2, arg3), } + Ok(0) + } + pub fn poll(&self) -> Result { + let status = match self { + FileLike::File(file) => file.poll()?, + FileLike::Socket(socket) => { + let (read, write, error) = socket.poll(); + PollStatus { read, write, error } + } + }; + Ok(status) } } diff --git a/kernel/src/fs/pipe.rs b/kernel/src/fs/pipe.rs index 4f35fc3..c0c50ea 100644 --- a/kernel/src/fs/pipe.rs +++ b/kernel/src/fs/pipe.rs @@ -57,7 +57,9 @@ impl Pipe { // TODO: better way to provide default impl? macro_rules! impl_inode { () => { + fn poll(&self) -> Result { Err(FsError::NotSupported) } fn metadata(&self) -> Result { Err(FsError::NotSupported) } + fn set_metadata(&self, _metadata: &Metadata) -> Result<()> { Ok(()) } fn sync_all(&self) -> Result<()> { Ok(()) } fn sync_data(&self) -> Result<()> { Ok(()) } fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) } @@ -67,9 +69,9 @@ macro_rules! impl_inode { 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 io_control(&self, _cmd: u32, _data: u32) -> Result<()> { Err(FsError::NotSupported) } fn fs(&self) -> Arc { unimplemented!() } fn as_any_ref(&self) -> &Any { self } - fn chmod(&self, _mode: u16) -> Result<()> { Ok(()) } }; } diff --git a/kernel/src/fs/stdio.rs b/kernel/src/fs/stdio.rs index 37da693..d2ceda2 100644 --- a/kernel/src/fs/stdio.rs +++ b/kernel/src/fs/stdio.rs @@ -47,6 +47,7 @@ lazy_static! { macro_rules! impl_inode { () => { fn metadata(&self) -> Result { Err(FsError::NotSupported) } + fn set_metadata(&self, _metadata: &Metadata) -> Result<()> { Ok(()) } fn sync_all(&self) -> Result<()> { Ok(()) } fn sync_data(&self) -> Result<()> { Ok(()) } fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) } @@ -56,20 +57,27 @@ macro_rules! impl_inode { 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 io_control(&self, _cmd: u32, _data: u32) -> Result<()> { Err(FsError::NotSupported) } fn fs(&self) -> Arc { unimplemented!() } fn as_any_ref(&self) -> &Any { self } - fn chmod(&self, _mode: u16) -> Result<()> { Ok(()) } }; } impl INode for Stdin { - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { buf[0] = self.pop() as u8; Ok(1) } fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { unimplemented!() } + fn poll(&self) -> Result { + Ok(PollStatus { + read: self.can_read(), + write: false, + error: false, + }) + } impl_inode!(); } @@ -84,5 +92,12 @@ impl INode for Stdout { print!("{}", s); Ok(buf.len()) } + fn poll(&self) -> Result { + Ok(PollStatus { + read: false, + write: true, + error: false, + }) + } impl_inode!(); } diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 73e9d53..9628242 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -88,34 +88,24 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu let proc = process(); let mut events = 0; for poll in polls.iter_mut() { - poll.revents = PE::NONE; - match proc.files.get(&(poll.fd as usize)) { - Some(FileLike::File(_)) => { - // FIXME: assume it is stdin for now - if poll.events.contains(PE::IN) && STDIN.can_read() { - poll.revents = poll.revents | PE::IN; - events = events + 1; - } + poll.revents = PE::empty(); + if let Some(file_like) = proc.files.get(&(poll.fd as usize)) { + let status = file_like.poll()?; + if status.error { + poll.revents |= PE::HUP; + events += 1; } - Some(FileLike::Socket(socket)) => { - let (input, output, err) = socket.poll(); - if err { - poll.revents = poll.revents | PE::HUP; - events = events + 1; - } - if input && poll.events.contains(PE::IN) { - poll.revents = poll.revents | PE::IN; - events = events + 1; - } - if output && poll.events.contains(PE::OUT) { - poll.revents = poll.revents | PE::OUT; - events = events + 1; - } + if status.read && poll.events.contains(PE::IN) { + poll.revents |= PE::IN; + events += 1; } - None => { - poll.revents = poll.revents | PE::ERR; - events = events + 1; + if status.write && poll.events.contains(PE::OUT) { + poll.revents |= PE::OUT; + events += 1; } + } else { + poll.revents |= PE::ERR; + events += 1; } } drop(proc); @@ -163,33 +153,21 @@ pub fn sys_select( let proc = process(); let mut events = 0; for (&fd, file_like) in proc.files.iter() { - if fd < nfds { - match file_like { - FileLike::File(_) => { - // FIXME: assume it is stdin for now - if STDIN.can_read() { - if read_fds.contains(fd) { - read_fds.set(fd); - events = events + 1; - } - } - } - FileLike::Socket(socket) => { - let (input, output, err) = socket.poll(); - if err && err_fds.contains(fd) { - err_fds.set(fd); - events = events + 1; - } - if input && read_fds.contains(fd) { - read_fds.set(fd); - events = events + 1; - } - if output && write_fds.contains(fd) { - write_fds.set(fd); - events = events + 1; - } - } - } + if fd >= nfds { + continue; + } + let status = file_like.poll()?; + if status.error && err_fds.contains(fd) { + err_fds.set(fd); + events += 1; + } + if status.read && read_fds.contains(fd) { + read_fds.set(fd); + events += 1; + } + if status.write && write_fds.contains(fd) { + write_fds.set(fd); + events += 1; } } drop(proc); @@ -1165,8 +1143,6 @@ pub struct PollFd { bitflags! { pub struct PollEvents: u16 { - /// Nothing Happens - const NONE = 0x0000; /// There is data to read. const IN = 0x0001; /// Writing is now possible.