diff --git a/Cargo.toml b/Cargo.toml index dac1ef1a1b..631718b47e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ name = "syscall" [features] rustc-dep-of-std = ["core", "bitflags/rustc-dep-of-std"] +std = [] [dependencies] bitflags = "2.4" diff --git a/src/error.rs b/src/error.rs index a082f5a695..83779a5723 100644 --- a/src/error.rs +++ b/src/error.rs @@ -44,6 +44,15 @@ impl fmt::Display for Error { f.write_str(self.text()) } } +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +#[cfg(feature = "std")] +impl From for std::io::Error { + fn from(value: Error) -> Self { + std::io::Error::from_raw_os_error(value.errno) + } +} pub const EPERM: i32 = 1; /* Operation not permitted */ pub const ENOENT: i32 = 2; /* No such file or directory */ diff --git a/src/flag.rs b/src/flag.rs index 7199439deb..16cf104829 100644 --- a/src/flag.rs +++ b/src/flag.rs @@ -72,6 +72,7 @@ pub const SKMSG_FOBTAINFD: usize = 2; // TODO: Split SendFdFlags into caller flags and flags that the scheme receives? bitflags::bitflags! { + #[derive(Clone, Copy, Debug)] pub struct SendFdFlags: usize { /// If set, the kernel will enforce that the file descriptor is exclusively owned. /// @@ -82,6 +83,7 @@ bitflags::bitflags! { } } bitflags::bitflags! { + #[derive(Clone, Copy, Debug)] pub struct FobtainFdFlags: usize { /// If set, `packet.c` specifies the destination file descriptor slot, otherwise the lowest /// available slot will be selected, and placed in the usize pointed to by `packet.c`. @@ -335,3 +337,11 @@ bitflags! { // TODO: MAYMOVE, DONTUNMAP } } +bitflags! { + pub struct RwFlags: u32 { + const NONBLOCK = 1; + const APPEND = 2; + // TODO: sync/dsync + // TODO: O_DIRECT? + } +} diff --git a/src/lib.rs b/src/lib.rs index 3f6d884797..f6c81e8bc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(test), no_std)] +#![cfg_attr(not(any(feature = "std", test)), no_std)] #[cfg(test)] extern crate core; @@ -10,7 +10,6 @@ pub use self::error::*; pub use self::flag::*; pub use self::io::*; pub use self::number::*; -pub use self::scheme::*; #[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "arm"))] #[path="arch/nonredox.rs"] @@ -54,8 +53,11 @@ pub mod io; /// Call numbers used by each system call pub mod number; -/// A trait useful for scheme handlers +/// V2 scheme format +pub mod schemev2; + pub mod scheme; +pub use scheme::*; #[cfg(test)] mod tests; diff --git a/src/number.rs b/src/number.rs index 9c6311101d..93f5bee508 100644 --- a/src/number.rs +++ b/src/number.rs @@ -19,7 +19,9 @@ pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6; pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41; pub const SYS_DUP2: usize = SYS_CLASS_FILE | SYS_RET_FILE | 63; pub const SYS_READ: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 3; +pub const SYS_READ2: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 35; pub const SYS_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4; +pub const SYS_WRITE2: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 45; pub const SYS_LSEEK: usize = SYS_CLASS_FILE | 19; pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94; pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207; diff --git a/src/schemev2.rs b/src/schemev2.rs new file mode 100644 index 0000000000..2ae9b46423 --- /dev/null +++ b/src/schemev2.rs @@ -0,0 +1,173 @@ +use core::ops::{Deref, DerefMut}; +use core::{mem, slice}; + +use bitflags::bitflags; + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct Sqe { + pub opcode: u8, + pub sqe_flags: SqeFlags, + pub _rsvd: u16, // TODO: priority + pub tag: u32, + pub args: [u64; 6], + pub caller: u64, +} +impl Deref for Sqe { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Sqe as *const u8, mem::size_of::()) + } + } +} + +impl DerefMut for Sqe { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Sqe as *mut u8, mem::size_of::()) + } + } +} + +bitflags! { + #[derive(Clone, Copy, Debug, Default)] + pub struct SqeFlags: u8 { + // If zero, the message is bidirectional, and the scheme is expected to pass the Ksmsg's + // tag field to the Skmsg. Some opcodes require this flag to be set. + const ONEWAY = 1; + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +pub struct Cqe { + pub flags: u8, // bits 3:0 are CqeOpcode + pub extra_raw: [u8; 3], + pub tag: u32, + pub result: u64, +} +impl Deref for Cqe { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Cqe as *const u8, mem::size_of::()) + } + } +} + +impl DerefMut for Cqe { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Cqe as *mut u8, mem::size_of::()) + } + } +} + +bitflags! { + #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] + pub struct NewFdFlags: u8 { + const POSITIONED = 1; + } +} + +impl Cqe { + pub fn extra(&self) -> u32 { + u32::from_ne_bytes([self.extra_raw[0], self.extra_raw[1], self.extra_raw[2], 0]) + } +} + +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum CqeOpcode { + RespondRegular, + RespondWithFd, + SendFevent, // no tag + ObtainFd, + // TODO: ProvideMmap +} +impl CqeOpcode { + pub fn try_from_raw(raw: u8) -> Option { + Some(match raw { + 0 => Self::RespondRegular, + 1 => Self::RespondWithFd, + 2 => Self::SendFevent, + 3 => Self::ObtainFd, + _ => return None, + }) + } +} + +#[repr(u8)] +#[non_exhaustive] +#[derive(Clone, Copy, Debug)] +pub enum Opcode { + Open = 0, // path_ptr, path_len (utf8), flags + Rmdir = 1, // path_ptr, path_len (utf8) + Unlink = 2, // path_ptr, path_len (utf8) + Close = 3, // fd + Dup = 4, // old fd, buf_ptr, buf_len + Read = 5, // fd, buf_ptr, buf_len, TODO offset, TODO flags, _ + Write = 6, // fd, buf_ptr, buf_len, TODO offset, TODO flags) + Fsize = 7, // fd + Fchmod = 8, // fd, new mode + Fchown = 9, // fd, new uid, new gid + Fcntl = 10, // fd, cmd, arg + Fevent = 11, // fd, requested mask + Sendfd = 12, + Fpath = 13, // fd, buf_ptr, buf_len + Frename = 14, + Fstat = 15, // fd, buf_ptr, buf_len + Fstatvfs = 16, // fd, buf_ptr, buf_len + Fsync = 17, // fd + Ftruncate = 18, // fd, new len + Futimens = 19, // fd, times_buf, times_len + + MmapPrep = 20, + RequestMmap = 21, + Mremap = 22, + Munmap = 23, + Msync = 24, // TODO + + Cancel = 25, // @tag +} + +impl Opcode { + pub fn try_from_raw(raw: u8) -> Option { + use Opcode::*; + + // TODO: Use a library where this match can be automated. + Some(match raw { + 0 => Open, + 1 => Rmdir, + 2 => Unlink, + 3 => Close, + 4 => Dup, + 5 => Read, + 6 => Write, + 7 => Fsize, + 8 => Fchmod, + 9 => Fchown, + 10 => Fcntl, + 11 => Fevent, + 12 => Sendfd, + 13 => Fpath, + 14 => Frename, + 15 => Fstat, + 16 => Fstatvfs, + 17 => Fsync, + 18 => Ftruncate, + 19 => Futimens, + + 20 => MmapPrep, + 21 => RequestMmap, + 22 => Mremap, + 23 => Munmap, + 24 => Msync, + + 25 => Cancel, + + _ => return None, + }) + } +}