feature: add FileDescriptor type
This commit is contained in:
+34
-18
@@ -2,7 +2,7 @@ use crate::abi;
|
||||
use crate::{
|
||||
ioctl::IoctlCmd,
|
||||
signal::{Signal, SignalDestination},
|
||||
stat::{FdSet, FileMode, OpenFlags, Stat},
|
||||
stat::{FdSet, FileDescriptor, FileMode, OpenFlags, Stat},
|
||||
};
|
||||
|
||||
// TODO document the syscall ABI
|
||||
@@ -80,8 +80,8 @@ pub unsafe fn sys_exit(status: i32) -> ! {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_close(fd: i32) -> i32 {
|
||||
syscall!(abi::SYS_CLOSE, argn!(fd)) as i32
|
||||
pub unsafe fn sys_close(fd: FileDescriptor) -> i32 {
|
||||
syscall!(abi::SYS_CLOSE, argn!(u32::from(fd))) as i32
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
@@ -108,10 +108,15 @@ pub unsafe fn sys_ex_debug_trace(msg: &[u8]) -> usize {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_openat(at: i32, pathname: &str, mode: FileMode, flags: OpenFlags) -> i32 {
|
||||
pub unsafe fn sys_openat(
|
||||
at: Option<FileDescriptor>,
|
||||
pathname: &str,
|
||||
mode: FileMode,
|
||||
flags: OpenFlags,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_OPENAT,
|
||||
argn!(at),
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argn!(mode.bits()),
|
||||
@@ -123,10 +128,10 @@ pub unsafe fn sys_openat(at: i32, pathname: &str, mode: FileMode, flags: OpenFla
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_read(fd: i32, data: &mut [u8]) -> isize {
|
||||
pub unsafe fn sys_read(fd: FileDescriptor, data: &mut [u8]) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_READ,
|
||||
argn!(fd),
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_mut_ptr()),
|
||||
argn!(data.len())
|
||||
) as isize
|
||||
@@ -136,10 +141,10 @@ pub unsafe fn sys_read(fd: i32, data: &mut [u8]) -> isize {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_write(fd: i32, data: &[u8]) -> isize {
|
||||
pub unsafe fn sys_write(fd: FileDescriptor, data: &[u8]) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_WRITE,
|
||||
argn!(fd),
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_ptr()),
|
||||
argn!(data.len())
|
||||
) as isize
|
||||
@@ -149,10 +154,15 @@ pub unsafe fn sys_write(fd: i32, data: &[u8]) -> isize {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_fstatat(at: i32, pathname: &str, statbuf: &mut Stat, flags: u32) -> i32 {
|
||||
pub unsafe fn sys_fstatat(
|
||||
at: Option<FileDescriptor>,
|
||||
pathname: &str,
|
||||
statbuf: &mut Stat,
|
||||
flags: u32,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_FSTATAT,
|
||||
argn!(at),
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argp!(statbuf as *mut Stat),
|
||||
@@ -192,10 +202,10 @@ pub unsafe fn sys_waitpid(pid: u32, status: &mut i32) -> i32 {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ioctl(fd: u32, cmd: IoctlCmd, ptr: usize, len: usize) -> isize {
|
||||
pub unsafe fn sys_ioctl(fd: FileDescriptor, cmd: IoctlCmd, ptr: usize, len: usize) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_IOCTL,
|
||||
argn!(fd),
|
||||
argn!(u32::from(fd)),
|
||||
argn!(cmd),
|
||||
argn!(ptr),
|
||||
argn!(len)
|
||||
@@ -215,21 +225,27 @@ pub unsafe fn sys_ex_sigreturn() -> ! {
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_kill(pid: SignalDestination, signum: Signal) -> i32 {
|
||||
syscall!(abi::SYS_EX_KILL, argn!(isize::from(pid)), argn!(signum as u32)) as i32
|
||||
syscall!(
|
||||
abi::SYS_EX_KILL,
|
||||
argn!(isize::from(pid)),
|
||||
argn!(signum as u32)
|
||||
) as i32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_select(
|
||||
n: u32,
|
||||
read_fds: Option<&mut FdSet>,
|
||||
write_fds: Option<&mut FdSet>,
|
||||
timeout: u64,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_SELECT,
|
||||
argn!(n),
|
||||
argp!(read_fds.map(|e| e as *mut _).unwrap_or(core::ptr::null_mut())),
|
||||
argp!(write_fds.map(|e| e as *mut _).unwrap_or(core::ptr::null_mut())),
|
||||
argp!(read_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argp!(write_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argn!(timeout)
|
||||
) as i32
|
||||
}
|
||||
|
||||
+56
-21
@@ -1,12 +1,9 @@
|
||||
use core::fmt;
|
||||
use crate::error::Errno;
|
||||
|
||||
pub const AT_FDCWD: i32 = -2;
|
||||
const AT_FDCWD: i32 = -2;
|
||||
pub const AT_EMPTY_PATH: u32 = 1 << 16;
|
||||
|
||||
pub const STDIN_FILENO: i32 = 0;
|
||||
pub const STDOUT_FILENO: i32 = 1;
|
||||
pub const STDERR_FILENO: i32 = 2;
|
||||
|
||||
bitflags! {
|
||||
pub struct OpenFlags: u32 {
|
||||
const O_RDONLY = 1;
|
||||
@@ -39,6 +36,10 @@ pub struct FdSet {
|
||||
bits: [u64; 2]
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct FileDescriptor(u32);
|
||||
|
||||
struct FdSetIter<'a> {
|
||||
idx: u32,
|
||||
set: &'a FdSet
|
||||
@@ -64,25 +65,25 @@ impl FdSet {
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.bits.iter().find(|&&x| x != 0).is_some()
|
||||
self.bits.iter().any(|&x| x != 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set(&mut self, fd: u32) {
|
||||
self.bits[(fd as usize) / 64] |= 1 << (fd % 64);
|
||||
pub fn set(&mut self, fd: FileDescriptor) {
|
||||
self.bits[(fd.0 as usize) / 64] |= 1 << (fd.0 % 64);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear(&mut self, fd: u32) {
|
||||
self.bits[(fd as usize) / 64] &= !(1 << (fd % 64));
|
||||
pub fn clear(&mut self, fd: FileDescriptor) {
|
||||
self.bits[(fd.0 as usize) / 64] &= !(1 << (fd.0 % 64));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_set(&self, fd: u32) -> bool {
|
||||
self.bits[(fd as usize) / 64] & (1 << (fd % 64)) != 0
|
||||
pub fn is_set(&self, fd: FileDescriptor) -> bool {
|
||||
self.bits[(fd.0 as usize) / 64] & (1 << (fd.0 % 64)) != 0
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = u32> + '_ {
|
||||
pub fn iter(&self) -> impl Iterator<Item = FileDescriptor> + '_ {
|
||||
FdSetIter {
|
||||
idx: 0,
|
||||
set: self
|
||||
@@ -91,14 +92,14 @@ impl FdSet {
|
||||
}
|
||||
|
||||
impl Iterator for FdSetIter<'_> {
|
||||
type Item = u32;
|
||||
type Item = FileDescriptor;
|
||||
|
||||
fn next(&mut self) -> Option<u32> {
|
||||
fn next(&mut self) -> Option<FileDescriptor> {
|
||||
while self.idx < 128 {
|
||||
if self.set.is_set(self.idx) {
|
||||
if self.set.is_set(FileDescriptor(self.idx)) {
|
||||
let res = self.idx;
|
||||
self.idx += 1;
|
||||
return Some(res);
|
||||
return Some(FileDescriptor::from(res));
|
||||
}
|
||||
self.idx += 1;
|
||||
}
|
||||
@@ -109,13 +110,11 @@ impl Iterator for FdSetIter<'_> {
|
||||
impl fmt::Debug for FdSet {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "FdSet {{ ")?;
|
||||
let mut count = 0;
|
||||
for fd in self.iter() {
|
||||
for (count, fd) in self.iter().enumerate() {
|
||||
if count != 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", fd)?;
|
||||
count += 1;
|
||||
write!(f, "{:?}", fd)?;
|
||||
}
|
||||
write!(f, " }}")
|
||||
}
|
||||
@@ -132,3 +131,39 @@ impl FileMode {
|
||||
unsafe { Self::from_bits_unchecked(0o644) }
|
||||
}
|
||||
}
|
||||
|
||||
impl FileDescriptor {
|
||||
pub const STDIN: Self = Self(0);
|
||||
pub const STDOUT: Self = Self(1);
|
||||
pub const STDERR: Self = Self(2);
|
||||
|
||||
pub fn from_i32(u: i32) -> Result<Option<Self>, Errno> {
|
||||
if u >= 0 {
|
||||
Ok(Some(Self(u as u32)))
|
||||
} else if u == AT_FDCWD {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(Errno::InvalidArgument)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_i32(u: Option<Self>) -> i32 {
|
||||
if let Some(u) = u {
|
||||
u.0 as i32
|
||||
} else {
|
||||
AT_FDCWD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for FileDescriptor {
|
||||
fn from(u: u32) -> Self {
|
||||
Self(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileDescriptor> for u32 {
|
||||
fn from(u: FileDescriptor) -> u32 {
|
||||
u.0
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user