feature: add FileDescriptor type

This commit is contained in:
2021-11-13 12:58:51 +02:00
parent 0f48379e1a
commit a695232926
11 changed files with 144 additions and 93 deletions
+4 -4
View File
@@ -4,8 +4,8 @@ use crate::config::{ConfigKey, CONFIG};
use crate::fs::{devfs, MemfsBlockAlloc};
use crate::mem;
use crate::proc::{elf, Process};
use libsys::stat::{FileDescriptor, OpenFlags};
use memfs::Ramfs;
use libsys::stat::OpenFlags;
use vfs::{Filesystem, Ioctx};
/// Kernel init process function
@@ -51,9 +51,9 @@ pub extern "C" fn init_fn(_arg: usize) -> ! {
let stdout = tty_node.open(OpenFlags::O_WRONLY).unwrap();
let stderr = stdout.clone();
io.set_file(0, stdin).unwrap();
io.set_file(1, stdout).unwrap();
io.set_file(2, stderr).unwrap();
io.set_file(FileDescriptor::STDIN, stdin).unwrap();
io.set_file(FileDescriptor::STDOUT, stdout).unwrap();
io.set_file(FileDescriptor::STDERR, stderr).unwrap();
}
drop(cfg);
+10 -9
View File
@@ -1,12 +1,12 @@
//! Process file descriptors and I/O context
use alloc::collections::BTreeMap;
use libsys::error::Errno;
use libsys::{error::Errno, stat::FileDescriptor};
use vfs::{FileRef, Ioctx};
/// Process I/O context. Contains file tables, root/cwd info etc.
pub struct ProcessIo {
ioctx: Option<Ioctx>,
files: BTreeMap<usize, FileRef>,
files: BTreeMap<u32, FileRef>,
}
impl ProcessIo {
@@ -22,8 +22,8 @@ impl ProcessIo {
}
/// Returns [File] struct referred to by file descriptor `idx`
pub fn file(&mut self, idx: usize) -> Result<FileRef, Errno> {
self.files.get(&idx).cloned().ok_or(Errno::InvalidFile)
pub fn file(&mut self, fd: FileDescriptor) -> Result<FileRef, Errno> {
self.files.get(&u32::from(fd)).cloned().ok_or(Errno::InvalidFile)
}
/// Returns [Ioctx] structure reference of this I/O context
@@ -32,19 +32,19 @@ impl ProcessIo {
}
/// Allocates a file descriptor and associates a [File] struct with it
pub fn place_file(&mut self, file: FileRef) -> Result<usize, Errno> {
pub fn place_file(&mut self, file: FileRef) -> Result<FileDescriptor, Errno> {
for idx in 0..64 {
if self.files.get(&idx).is_none() {
self.files.insert(idx, file);
return Ok(idx);
return Ok(FileDescriptor::from(idx));
}
}
Err(Errno::TooManyDescriptors)
}
/// Performs [File] close and releases its associated file descriptor `idx`
pub fn close_file(&mut self, idx: usize) -> Result<(), Errno> {
let res = self.files.remove(&idx);
pub fn close_file(&mut self, idx: FileDescriptor) -> Result<(), Errno> {
let res = self.files.remove(&u32::from(idx));
assert!(res.is_some());
Ok(())
}
@@ -59,7 +59,8 @@ impl ProcessIo {
/// Assigns a descriptor number to an open file. If the number is not available,
/// returns [Errno::AlreadyExists].
pub fn set_file(&mut self, idx: usize, file: FileRef) -> Result<(), Errno> {
pub fn set_file(&mut self, idx: FileDescriptor, file: FileRef) -> Result<(), Errno> {
let idx = u32::from(idx);
if self.files.get(&idx).is_none() {
self.files.insert(idx, file);
Ok(())
-1
View File
@@ -9,7 +9,6 @@ use crate::proc::{wait::Wait, ProcessIo, PROCESSES, SCHED};
use crate::sync::IrqSafeSpinLock;
use alloc::rc::Rc;
use core::cell::UnsafeCell;
use core::fmt;
use core::sync::atomic::{AtomicU32, Ordering};
use libsys::{error::Errno, signal::Signal, proc::{ExitCode, Pid}};
+3 -4
View File
@@ -57,11 +57,10 @@ pub fn sleep(timeout: Duration, remaining: &mut Duration) -> Result<(), Errno> {
pub fn select(
proc: ProcessRef,
n: u32,
mut rfds: Option<&mut FdSet>,
mut wfds: Option<&mut FdSet>,
timeout: Option<Duration>,
) -> Result<u32, Errno> {
) -> Result<usize, Errno> {
// TODO support wfds
if wfds.is_some() || rfds.is_none() {
todo!();
@@ -77,7 +76,7 @@ pub fn select(
loop {
if let Some(read) = &read {
for fd in read.iter() {
let file = io.file(fd as usize)?;
let file = io.file(fd)?;
if file.borrow().is_ready(false)? {
rfds.as_mut().unwrap().set(fd);
return Ok(1);
@@ -86,7 +85,7 @@ pub fn select(
}
if let Some(write) = &write {
for fd in write.iter() {
let file = io.file(fd as usize)?;
let file = io.file(fd)?;
if file.borrow().is_ready(true)? {
wfds.as_mut().unwrap().set(fd);
return Ok(1);
+20 -21
View File
@@ -3,7 +3,6 @@
use crate::arch::platform::exception::ExceptionFrame;
use crate::debug::Level;
use crate::proc::{elf, wait, Process, ProcessIo};
use core::cmp::Ordering;
use core::mem::size_of;
use core::ops::DerefMut;
use core::time::Duration;
@@ -13,7 +12,7 @@ use libsys::{
ioctl::IoctlCmd,
proc::Pid,
signal::{Signal, SignalDestination},
stat::{FdSet, FileMode, OpenFlags, Stat, AT_EMPTY_PATH, AT_FDCWD},
stat::{FdSet, FileDescriptor, FileMode, OpenFlags, Stat, AT_EMPTY_PATH},
traits::{Read, Write},
};
use vfs::VnodeRef;
@@ -34,11 +33,11 @@ pub unsafe fn sys_fork(regs: &mut ExceptionFrame) -> Result<Pid, Errno> {
fn find_at_node<T: DerefMut<Target = ProcessIo>>(
io: &mut T,
at_fd: usize,
at_fd: Option<FileDescriptor>,
filename: &str,
empty_path: bool,
) -> Result<VnodeRef, Errno> {
let at = if at_fd as i32 != AT_FDCWD {
let at = if let Some(at_fd) = at_fd {
io.file(at_fd)?.borrow().node()
} else {
None
@@ -62,7 +61,7 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
// I/O system calls
abi::SYS_OPENAT => {
let at_fd = args[0];
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
let path = validate_user_str(args[1], args[2])?;
let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
let opts = OpenFlags::from_bits(args[4] as u32).ok_or(Errno::InvalidArgument)?;
@@ -70,31 +69,33 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
let proc = Process::current();
let mut io = proc.io.lock();
let at = if at_fd as i32 == AT_FDCWD {
None
let at = if let Some(fd) = at_fd {
io.file(fd)?.borrow().node()
} else {
io.file(at_fd)?.borrow().node()
None
};
let file = io.ioctx().open(at, path, mode, opts)?;
io.place_file(file)
Ok(u32::from(io.place_file(file)?) as usize)
}
abi::SYS_READ => {
let proc = Process::current();
let fd = FileDescriptor::from(args[0] as u32);
let mut io = proc.io.lock();
let buf = validate_user_ptr(args[1], args[2])?;
io.file(args[0])?.borrow_mut().read(buf)
io.file(fd)?.borrow_mut().read(buf)
}
abi::SYS_WRITE => {
let proc = Process::current();
let fd = FileDescriptor::from(args[0] as u32);
let mut io = proc.io.lock();
let buf = validate_user_ptr(args[1], args[2])?;
io.file(args[0])?.borrow_mut().write(buf)
io.file(fd)?.borrow_mut().write(buf)
}
abi::SYS_FSTATAT => {
let at_fd = args[0];
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
let filename = validate_user_str(args[1], args[2])?;
let buf = validate_user_ptr_struct::<Stat>(args[3])?;
let flags = args[4] as u32;
@@ -107,7 +108,7 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
abi::SYS_CLOSE => {
let proc = Process::current();
let mut io = proc.io.lock();
let fd = args[0];
let fd = FileDescriptor::from(args[0] as u32);
io.close_file(fd)?;
Ok(0)
@@ -140,7 +141,7 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
}
}
abi::SYS_IOCTL => {
let fd = args[0];
let fd = FileDescriptor::from(args[0] as u32);
let cmd = IoctlCmd::try_from(args[1] as u32)?;
let proc = Process::current();
@@ -197,18 +198,16 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
}
abi::SYS_SELECT => {
let n = args[0] as u32;
let rfds = validate_user_ptr_struct_option::<FdSet>(args[1])?;
let wfds = validate_user_ptr_struct_option::<FdSet>(args[2])?;
let timeout = if args[3] == 0 {
let rfds = validate_user_ptr_struct_option::<FdSet>(args[0])?;
let wfds = validate_user_ptr_struct_option::<FdSet>(args[1])?;
let timeout = if args[2] == 0 {
None
} else {
Some(Duration::from_nanos(args[3] as u64))
Some(Duration::from_nanos(args[2] as u64))
};
let proc = Process::current();
let fd = wait::select(proc, n, rfds, wfds, timeout)?;
Ok(fd as usize)
wait::select(proc, rfds, wfds, timeout)
}
_ => {