Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

201
vendor/redox_syscall/src/arch/aarch64.rs vendored Normal file
View File

@@ -0,0 +1,201 @@
use core::{
mem,
ops::{Deref, DerefMut},
slice,
};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
#[cfg(feature = "userspace")]
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
let ret: usize;
core::arch::asm!(
"svc 0",
in("x8") $a,
$(
in("x0") $b,
$(
in("x1") $c,
$(
in("x2") $d,
$(
in("x3") $e,
$(
in("x4") $f,
)?
)?
)?
)?
)?
lateout("x0") ret,
options(nostack),
);
Error::demux(ret)
}
)+
};
}
#[cfg(feature = "userspace")]
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
pub x30: usize,
pub x29: usize,
pub x28: usize,
pub x27: usize,
pub x26: usize,
pub x25: usize,
pub x24: usize,
pub x23: usize,
pub x22: usize,
pub x21: usize,
pub x20: usize,
pub x19: usize,
pub x18: usize,
pub x17: usize,
pub x16: usize,
pub x15: usize,
pub x14: usize,
pub x13: usize,
pub x12: usize,
pub x11: usize,
pub x10: usize,
pub x9: usize,
pub x8: usize,
pub x7: usize,
pub x6: usize,
pub x5: usize,
pub x4: usize,
pub x3: usize,
pub x2: usize,
pub x1: usize,
pub x0: usize,
}
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const IntRegisters as *const u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut IntRegisters as *mut u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct FloatRegisters {
pub fp_simd_regs: [u128; 32],
pub fpsr: u32,
pub fpcr: u32,
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const FloatRegisters as *const u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut FloatRegisters as *mut u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct EnvRegisters {
pub tpidr_el0: usize,
pub tpidrro_el0: usize,
}
impl Deref for EnvRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const EnvRegisters as *const u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
impl DerefMut for EnvRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut EnvRegisters as *mut u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct Exception {
pub kind: usize,
// TODO
}
impl Deref for Exception {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const Exception as *const u8,
mem::size_of::<Exception>(),
)
}
}
}
impl DerefMut for Exception {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut Exception as *mut u8,
mem::size_of::<Exception>(),
)
}
}
}

200
vendor/redox_syscall/src/arch/riscv64.rs vendored Normal file
View File

@@ -0,0 +1,200 @@
use super::error::{Error, Result};
use core::arch::asm;
use core::{
mem,
ops::{Deref, DerefMut},
slice,
};
pub const PAGE_SIZE: usize = 4096;
#[cfg(feature = "userspace")]
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
let ret: usize;
asm!(
"ecall",
in("a7") $a,
$(
in("a0") $b,
$(
in("a1") $c,
$(
in("a2") $d,
$(
in("a3") $e,
$(
in("a4") $f,
)?
)?
)?
)?
)?
lateout("a0") ret,
options(nostack),
);
Error::demux(ret)
}
)+
};
}
#[cfg(feature = "userspace")]
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
pub pc: usize,
pub x31: usize,
pub x30: usize,
pub x29: usize,
pub x28: usize,
pub x27: usize,
pub x26: usize,
pub x25: usize,
pub x24: usize,
pub x23: usize,
pub x22: usize,
pub x21: usize,
pub x20: usize,
pub x19: usize,
pub x18: usize,
pub x17: usize,
pub x16: usize,
pub x15: usize,
pub x14: usize,
pub x13: usize,
pub x12: usize,
pub x11: usize,
pub x10: usize,
pub x9: usize,
pub x8: usize,
pub x7: usize,
pub x6: usize,
pub x5: usize,
// x4(tp) is in env
// x3(gp) is a platform scratch register
pub x2: usize,
pub x1: usize,
}
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const IntRegisters as *const u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut IntRegisters as *mut u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct FloatRegisters {
pub fregs: [u64; 32],
pub fcsr: u32,
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const FloatRegisters as *const u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut FloatRegisters as *mut u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct EnvRegisters {
pub tp: usize,
}
impl Deref for EnvRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const EnvRegisters as *const u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
impl DerefMut for EnvRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut EnvRegisters as *mut u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct Exception {
pub kind: usize,
// TODO
}
impl Deref for Exception {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const Exception as *const u8,
mem::size_of::<Exception>(),
)
}
}
}
impl DerefMut for Exception {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut Exception as *mut u8,
mem::size_of::<Exception>(),
)
}
}
}

243
vendor/redox_syscall/src/arch/x86.rs vendored Normal file
View File

@@ -0,0 +1,243 @@
use core::{
arch::asm,
mem,
ops::{Deref, DerefMut},
slice,
};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
#[cfg(feature = "userspace")]
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
asm!(
"int 0x80",
inout("eax") $a,
$(
in("ebx") $b,
$(
in("ecx") $c,
$(
in("edx") $d,
$(
in("esi") $e,
$(
in("edi") $f,
)?
)?
)?
)?
)?
options(nostack),
);
Error::demux($a)
}
)+
};
}
#[cfg(feature = "userspace")]
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
// Must be done custom because LLVM reserves ESI
//syscall4(a, b, c, d, e,);
//syscall5(a, b, c, d, e, f,);
}
#[cfg(feature = "userspace")]
pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
asm!(
"xchg esi, {e}
int 0x80
xchg esi, {e}",
e = in(reg) e,
inout("eax") a,
in("ebx") b,
in("ecx") c,
in("edx") d,
options(nostack),
);
Error::demux(a)
}
#[cfg(feature = "userspace")]
pub unsafe fn syscall5(
mut a: usize,
b: usize,
c: usize,
d: usize,
e: usize,
f: usize,
) -> Result<usize> {
asm!(
"xchg esi, {e}
int 0x80
xchg esi, {e}",
e = in(reg) e,
inout("eax") a,
in("ebx") b,
in("ecx") c,
in("edx") d,
in("edi") f,
options(nostack),
);
Error::demux(a)
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
// TODO: Some of these don't get set by Redox yet. Should they?
pub ebp: usize,
pub esi: usize,
pub edi: usize,
pub ebx: usize,
pub eax: usize,
pub ecx: usize,
pub edx: usize,
// pub orig_rax: usize,
pub eip: usize,
pub cs: usize,
pub eflags: usize,
pub esp: usize,
pub ss: usize,
// pub fs_base: usize,
// pub gs_base: usize,
// pub ds: usize,
// pub es: usize,
pub fs: usize,
// pub gs: usize
}
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const IntRegisters as *const u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut IntRegisters as *mut u8,
mem::size_of::<IntRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct FloatRegisters {
pub fcw: u16,
pub fsw: u16,
pub ftw: u8,
pub _reserved: u8,
pub fop: u16,
pub fip: u64,
pub fdp: u64,
pub mxcsr: u32,
pub mxcsr_mask: u32,
pub st_space: [u128; 8],
pub xmm_space: [u128; 16],
// TODO: YMM/ZMM
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const FloatRegisters as *const u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut FloatRegisters as *mut u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct EnvRegisters {
pub fsbase: u32,
pub gsbase: u32,
}
impl Deref for EnvRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const EnvRegisters as *const u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
impl DerefMut for EnvRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut EnvRegisters as *mut u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct Exception {
pub kind: usize,
pub code: usize,
pub address: usize,
}
impl Deref for Exception {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const Exception as *const u8,
mem::size_of::<Exception>(),
)
}
}
}
impl DerefMut for Exception {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut Exception as *mut u8,
mem::size_of::<Exception>(),
)
}
}
}

188
vendor/redox_syscall/src/arch/x86_64.rs vendored Normal file
View File

@@ -0,0 +1,188 @@
use core::{
mem,
ops::{Deref, DerefMut},
slice,
};
pub const PAGE_SIZE: usize = 4096;
#[cfg(feature = "userspace")]
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> crate::error::Result<usize> {
core::arch::asm!(
"syscall",
inout("rax") $a,
$(
in("rdi") $b,
$(
in("rsi") $c,
$(
in("rdx") $d,
$(
in("r10") $e,
$(
in("r8") $f,
)?
)?
)?
)?
)?
out("rcx") _,
out("r11") _,
options(nostack),
);
crate::error::Error::demux($a)
}
)+
};
}
#[cfg(feature = "userspace")]
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub rbp: usize,
pub rbx: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rax: usize,
pub rcx: usize,
pub rdx: usize,
pub rsi: usize,
pub rdi: usize,
pub rip: usize,
pub cs: usize,
pub rflags: usize,
pub rsp: usize,
pub ss: usize,
}
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
}
}
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut u8, mem::size_of::<Self>()) }
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct FloatRegisters {
pub fcw: u16,
pub fsw: u16,
pub ftw: u8,
pub _reserved: u8,
pub fop: u16,
pub fip: u64,
pub fdp: u64,
pub mxcsr: u32,
pub mxcsr_mask: u32,
pub st_space: [u128; 8],
pub xmm_space: [u128; 16],
// TODO: YMM/ZMM
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const FloatRegisters as *const u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut FloatRegisters as *mut u8,
mem::size_of::<FloatRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct EnvRegisters {
pub fsbase: u64,
pub gsbase: u64,
// TODO: PKRU?
}
impl Deref for EnvRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const EnvRegisters as *const u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
impl DerefMut for EnvRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut EnvRegisters as *mut u8,
mem::size_of::<EnvRegisters>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct Exception {
pub kind: usize,
pub code: usize,
pub address: usize,
}
impl Deref for Exception {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const Exception as *const u8,
mem::size_of::<Exception>(),
)
}
}
}
impl DerefMut for Exception {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut Exception as *mut u8,
mem::size_of::<Exception>(),
)
}
}
}

252
vendor/redox_syscall/src/call.rs vendored Normal file
View File

@@ -0,0 +1,252 @@
use super::{
arch::*,
data::{Map, Stat, StatVfs, TimeSpec},
error::Result,
flag::*,
number::*,
};
use core::mem;
/// Close a file
pub fn close(fd: usize) -> Result<usize> {
unsafe { syscall1(SYS_CLOSE, fd) }
}
/// Get the current system time
pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
}
/// Copy and transform a file descriptor
pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
}
/// Copy and transform a file descriptor
pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
}
/// Change file permissions
pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }
}
/// Change file ownership
pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }
}
/// Change file descriptor flags
pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
}
/// Map a file into memory, but with the ability to set the address to map into, either as a hint
/// or as a requirement of the map.
///
/// # Errors
/// `EACCES` - the file descriptor was not open for reading
/// `EBADF` - if the file descriptor was invalid
/// `ENODEV` - mmapping was not supported
/// `EINVAL` - invalid combination of flags
/// `EEXIST` - if [`MapFlags::MAP_FIXED`] was set, and the address specified was already in use.
///
pub unsafe fn fmap(fd: usize, map: &Map) -> Result<usize> {
syscall3(
SYS_FMAP,
fd,
map as *const Map as usize,
mem::size_of::<Map>(),
)
}
/// Unmap whole (or partial) continous memory-mapped files
pub unsafe fn funmap(addr: usize, len: usize) -> Result<usize> {
syscall2(SYS_FUNMAP, addr, len)
}
/// Retrieve the canonical path of a file
pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
}
/// Create a link to a file
pub fn flink<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall3(SYS_FLINK, fd, path.as_ptr() as usize, path.len()) }
}
/// Rename a file
pub fn frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall3(SYS_FRENAME, fd, path.as_ptr() as usize, path.len()) }
}
/// Get metadata about a file
pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
unsafe {
syscall3(
SYS_FSTAT,
fd,
stat as *mut Stat as usize,
mem::size_of::<Stat>(),
)
}
}
/// Get metadata about a filesystem
pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
unsafe {
syscall3(
SYS_FSTATVFS,
fd,
stat as *mut StatVfs as usize,
mem::size_of::<StatVfs>(),
)
}
}
/// Sync a file descriptor to its underlying medium
pub fn fsync(fd: usize) -> Result<usize> {
unsafe { syscall1(SYS_FSYNC, fd) }
}
/// Truncate or extend a file to a specified length
pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
}
// Change modify and/or access times
pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
unsafe {
syscall3(
SYS_FUTIMENS,
fd,
times.as_ptr() as usize,
times.len() * mem::size_of::<TimeSpec>(),
)
}
}
/// Fast userspace mutex
pub unsafe fn futex(
addr: *mut i32,
op: usize,
val: i32,
val2: usize,
addr2: *mut i32,
) -> Result<usize> {
syscall5(
SYS_FUTEX,
addr as usize,
op,
(val as isize) as usize,
val2,
addr2 as usize,
)
}
/// Seek to `offset` bytes in a file descriptor
pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
}
/// Make a new scheme namespace
pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
}
/// Change mapping flags
pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize> {
syscall3(SYS_MPROTECT, addr, size, flags.bits())
}
/// Sleep for the time specified in `req`
pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
unsafe {
syscall2(
SYS_NANOSLEEP,
req as *const TimeSpec as usize,
rem as *mut TimeSpec as usize,
)
}
}
/// Open a file
pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) }
}
/// Open a file at a specific path
pub fn openat<T: AsRef<str>>(fd: usize, path: T, flags: usize, fcntl_flags: usize) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall5(SYS_OPENAT, fd, path.as_ptr() as usize, path.len(), flags, fcntl_flags) }
}
/// Read from a file descriptor into a buffer
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
}
/// Remove a directory
pub fn rmdir<T: AsRef<str>>(path: T) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) }
}
/// Remove a file
pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
let path = path.as_ref();
unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) }
}
/// Write a buffer to a file descriptor
///
/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
/// were written.
///
/// # Errors
///
/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
/// * `EBADF` - the file descriptor is not valid or is not open for writing
/// * `EFAULT` - `buf` does not point to the process's addressible memory
/// * `EIO` - an I/O error occurred
/// * `ENOSPC` - the device containing the file descriptor has no room for data
/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
}
/// Yield the process's time slice to the kernel
///
/// This function will return Ok(0) on success
pub fn sched_yield() -> Result<usize> {
unsafe { syscall0(SYS_YIELD) }
}
/// Send a file descriptor `fd`, handled by the scheme providing `receiver_socket`. `flags` is
/// currently unused (must be zero), and `arg` is included in the scheme call.
///
/// The scheme can return an arbitrary value.
pub fn sendfd(receiver_socket: usize, fd: usize, flags: usize, arg: u64) -> Result<usize> {
#[cfg(target_pointer_width = "32")]
unsafe {
syscall5(
SYS_SENDFD,
receiver_socket,
fd,
flags,
arg as u32 as usize,
(arg >> 32) as u32 as usize,
)
}
#[cfg(target_pointer_width = "64")]
unsafe {
syscall4(SYS_SENDFD, receiver_socket, fd, flags, arg as usize)
}
}

409
vendor/redox_syscall/src/data.rs vendored Normal file
View File

@@ -0,0 +1,409 @@
use core::{
mem,
ops::{Deref, DerefMut},
slice,
};
use crate::flag::{EventFlags, MapFlags, PtraceFlags};
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Event {
pub id: usize,
pub flags: EventFlags,
pub data: usize,
}
impl Deref for Event {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>()) }
}
}
impl DerefMut for Event {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>()) }
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct ITimerSpec {
pub it_interval: TimeSpec,
pub it_value: TimeSpec,
}
impl Deref for ITimerSpec {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const ITimerSpec as *const u8,
mem::size_of::<ITimerSpec>(),
)
}
}
}
impl DerefMut for ITimerSpec {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut ITimerSpec as *mut u8,
mem::size_of::<ITimerSpec>(),
)
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct OldMap {
pub offset: usize,
pub size: usize,
pub flags: MapFlags,
}
impl Deref for OldMap {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const OldMap as *const u8, mem::size_of::<OldMap>())
}
}
}
impl DerefMut for OldMap {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut OldMap as *mut u8, mem::size_of::<OldMap>())
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Map {
/// The offset inside the file that is being mapped.
pub offset: usize,
/// The size of the memory map.
pub size: usize,
/// Contains both prot and map flags.
pub flags: MapFlags,
/// Functions as a hint to where in the virtual address space of the running process, to place
/// the memory map. If [`MapFlags::MAP_FIXED`] is set, then this address must be the address to
/// map to.
pub address: usize,
}
impl Deref for Map {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Map as *const u8, mem::size_of::<Map>()) }
}
}
impl DerefMut for Map {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Map as *mut u8, mem::size_of::<Map>()) }
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Packet {
pub id: u64,
pub pid: usize,
pub uid: u32,
pub gid: u32,
pub a: usize,
pub b: usize,
pub c: usize,
pub d: usize,
}
impl Deref for Packet {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::<Packet>())
}
}
}
impl DerefMut for Packet {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::<Packet>())
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Stat {
pub st_dev: u64,
pub st_ino: u64,
pub st_mode: u16,
pub st_nlink: u32,
pub st_uid: u32,
pub st_gid: u32,
pub st_size: u64,
pub st_blksize: u32,
pub st_blocks: u64,
pub st_mtime: u64,
pub st_mtime_nsec: u32,
pub st_atime: u64,
pub st_atime_nsec: u32,
pub st_ctime: u64,
pub st_ctime_nsec: u32,
}
impl Deref for Stat {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Stat as *const u8, mem::size_of::<Stat>()) }
}
}
impl DerefMut for Stat {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Stat as *mut u8, mem::size_of::<Stat>()) }
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct StatVfs {
pub f_bsize: u32,
pub f_blocks: u64,
pub f_bfree: u64,
pub f_bavail: u64,
}
impl Deref for StatVfs {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const StatVfs as *const u8,
mem::size_of::<StatVfs>(),
)
}
}
}
impl DerefMut for StatVfs {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, mem::size_of::<StatVfs>())
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct TimeSpec {
pub tv_sec: i64,
pub tv_nsec: i32,
}
impl Deref for TimeSpec {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const TimeSpec as *const u8,
mem::size_of::<TimeSpec>(),
)
}
}
}
impl DerefMut for TimeSpec {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut TimeSpec as *mut u8, mem::size_of::<TimeSpec>())
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct PtraceEvent {
pub cause: PtraceFlags,
pub a: usize,
pub b: usize,
pub c: usize,
pub d: usize,
pub e: usize,
pub f: usize,
}
impl Deref for PtraceEvent {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const PtraceEvent as *const u8,
mem::size_of::<PtraceEvent>(),
)
}
}
}
impl DerefMut for PtraceEvent {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut PtraceEvent as *mut u8,
mem::size_of::<PtraceEvent>(),
)
}
}
}
#[macro_export]
macro_rules! ptrace_event {
($cause:expr $(, $a:expr $(, $b:expr $(, $c:expr)?)?)?) => {
$crate::data::PtraceEvent {
cause: $cause,
$(a: $a,
$(b: $b,
$(c: $c,)?
)?
)?
..Default::default()
}
}
}
bitflags::bitflags! {
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy, Default)]
pub struct GrantFlags: usize {
const GRANT_READ = 0x0000_0001;
const GRANT_WRITE = 0x0000_0002;
const GRANT_EXEC = 0x0000_0004;
const GRANT_SHARED = 0x0000_0008;
const GRANT_LAZY = 0x0000_0010;
const GRANT_SCHEME = 0x0000_0020;
const GRANT_PHYS = 0x0000_0040;
const GRANT_PINNED = 0x0000_0080;
const GRANT_PHYS_CONTIGUOUS = 0x0000_0100;
}
}
impl GrantFlags {
#[deprecated = "use the safe `from_bits_retain` method instead"]
pub unsafe fn from_bits_unchecked(bits: usize) -> Self {
Self::from_bits_retain(bits)
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct GrantDesc {
pub base: usize,
pub size: usize,
pub flags: GrantFlags,
pub offset: u64,
}
impl Deref for GrantDesc {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const GrantDesc as *const u8,
mem::size_of::<GrantDesc>(),
)
}
}
}
impl DerefMut for GrantDesc {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut GrantDesc as *mut u8,
mem::size_of::<GrantDesc>(),
)
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct SetSighandlerData {
pub user_handler: usize,
pub excp_handler: usize,
pub thread_control_addr: usize,
pub proc_control_addr: usize,
}
impl Deref for SetSighandlerData {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
}
}
impl DerefMut for SetSighandlerData {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut u8, mem::size_of::<Self>()) }
}
}
pub use crate::sigabi::*;
/// UNSTABLE
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct ProcSchemeAttrs {
pub pid: u32,
pub euid: u32,
pub egid: u32,
pub ens: u32,
pub debug_name: [u8; 32],
}
impl Deref for ProcSchemeAttrs {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
}
}
impl DerefMut for ProcSchemeAttrs {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut ProcSchemeAttrs as *mut u8,
mem::size_of::<ProcSchemeAttrs>(),
)
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct CtxtStsBuf {
pub status: usize,
pub excp: crate::Exception,
}
impl Deref for CtxtStsBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
}
}
impl DerefMut for CtxtStsBuf {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self as *mut CtxtStsBuf as *mut u8,
mem::size_of::<CtxtStsBuf>(),
)
}
}
}

229
vendor/redox_syscall/src/dirent.rs vendored Normal file
View File

@@ -0,0 +1,229 @@
use core::{
mem::size_of,
ops::{Deref, DerefMut},
slice,
};
use crate::{
error::{Error, Result, EINVAL},
ENAMETOOLONG,
};
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct DirentHeader {
pub inode: u64,
/// A filesystem-specific opaque value used to uniquely identify directory entries. This value,
/// in the last returned entry from a SYS_GETDENTS invocation, shall be passed to the next
/// call.
pub next_opaque_id: u64,
// This struct intentionally does not include a "next" offset field, unlike Linux, to easily
// guarantee the iterator will be reasonably deterministic, even if the scheme is adversarial.
pub record_len: u16,
/// A `DirentKind`.
///
/// May not be directly available (Unspecified), and if so needs to be looked using fstat.
pub kind: u8,
}
impl Deref for DirentHeader {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
}
}
impl DerefMut for DirentHeader {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
}
}
// Note: Must match relibc/include/bits/dirent.h
#[derive(Clone, Copy, Debug, Default)]
#[repr(u8)]
pub enum DirentKind {
#[default]
Unspecified = 0,
CharDev = 2,
Directory = 4,
BlockDev = 6,
Regular = 8,
Symlink = 10,
Socket = 12,
}
impl DirentKind {
// TODO: derive(FromPrimitive)
pub fn try_from_raw(raw: u8) -> Option<Self> {
Some(match raw {
0 => Self::Unspecified,
2 => Self::CharDev,
4 => Self::Directory,
6 => Self::BlockDev,
8 => Self::Regular,
10 => Self::Symlink,
12 => Self::Socket,
_ => return None,
})
}
}
pub struct DirentIter<'a>(&'a [u8]);
impl<'a> DirentIter<'a> {
pub const fn new(buffer: &'a [u8]) -> Self {
Self(buffer)
}
}
#[derive(Debug)]
pub struct Invalid;
impl<'a> Iterator for DirentIter<'a> {
type Item = Result<(&'a DirentHeader, &'a [u8]), Invalid>;
fn next(&mut self) -> Option<Self::Item> {
if self.0.len() < size_of::<DirentHeader>() {
return None;
}
let header = unsafe { &*(self.0.as_ptr().cast::<DirentHeader>()) };
if self.0.len() < usize::from(header.record_len) {
return Some(Err(Invalid));
}
let (this, remaining) = self.0.split_at(usize::from(header.record_len));
self.0 = remaining;
let name_and_nul = &this[size_of::<DirentHeader>()..];
let name = &name_and_nul[..name_and_nul.len() - 1];
Some(Ok((header, name)))
}
}
#[derive(Debug)]
pub struct DirentBuf<B> {
buffer: B,
// Exists in order to allow future extensions to the DirentHeader struct.
// TODO: Might add an upper bound to protect against cache miss DoS. The kernel currently
// forbids any other value than size_of::<DirentHeader>().
header_size: u16,
written: usize,
}
/// Abstraction between &mut [u8] and the kernel's UserSliceWo.
pub trait Buffer<'a>: Sized + 'a {
fn empty() -> Self;
fn length(&self) -> usize;
/// Split all of `self` into two disjoint contiguous subbuffers of lengths `index` and `length
/// - index` respectively.
///
/// Returns None if and only if `index > length`.
fn split_at(self, index: usize) -> Option<[Self; 2]>;
/// Copy from `src`, lengths must match exactly.
///
/// Allowed to overwrite subsequent buffer space, for performance reasons. Can be changed in
/// the future if too restrictive.
fn copy_from_slice_exact(self, src: &[u8]) -> Result<()>;
/// Write zeroes to this part of the buffer.
///
/// Allowed to overwrite subsequent buffer space, for performance reasons. Can be changed in
/// the future if too restrictive.
fn zero_out(self) -> Result<()>;
}
impl<'a> Buffer<'a> for &'a mut [u8] {
fn empty() -> Self {
&mut []
}
fn length(&self) -> usize {
self.len()
}
fn split_at(self, index: usize) -> Option<[Self; 2]> {
self.split_at_mut_checked(index).map(|(a, b)| [a, b])
}
fn copy_from_slice_exact(self, src: &[u8]) -> Result<()> {
self.copy_from_slice(src);
Ok(())
}
fn zero_out(self) -> Result<()> {
self.fill(0);
Ok(())
}
}
pub struct DirEntry<'name> {
pub inode: u64,
pub next_opaque_id: u64,
pub name: &'name str,
pub kind: DirentKind,
}
impl<'a, B: Buffer<'a>> DirentBuf<B> {
pub fn new(buffer: B, header_size: u16) -> Option<Self> {
if usize::from(header_size) < size_of::<DirentHeader>() {
return None;
}
Some(Self {
buffer,
header_size,
written: 0,
})
}
pub fn entry(&mut self, entry: DirEntry<'_>) -> Result<()> {
let name16 = u16::try_from(entry.name.len()).map_err(|_| Error::new(EINVAL))?;
let record_len = self
.header_size
.checked_add(name16)
// XXX: NUL byte. Unfortunately this is probably the only performant way to be
// compatible with C.
.and_then(|l| l.checked_add(1))
.ok_or(Error::new(ENAMETOOLONG))?;
let [this, remaining] = core::mem::replace(&mut self.buffer, B::empty())
.split_at(usize::from(record_len))
.ok_or(Error::new(EINVAL))?;
let [this_header_variable, this_name_and_nul] = this
.split_at(usize::from(self.header_size))
.expect("already know header_size + ... >= header_size");
let [this_name, this_name_nul] = this_name_and_nul
.split_at(usize::from(name16))
.expect("already know name.len() <= name.len() + 1");
// Every write here is currently sequential, allowing the buffer trait to do optimizations
// where subbuffer writes are out-of-bounds (but inside the total buffer).
let [this_header, this_header_extra] = this_header_variable
.split_at(size_of::<DirentHeader>())
.expect("already checked header_size <= size_of Header");
this_header.copy_from_slice_exact(&DirentHeader {
record_len,
next_opaque_id: entry.next_opaque_id,
inode: entry.inode,
kind: entry.kind as u8,
})?;
this_header_extra.zero_out()?;
this_name.copy_from_slice_exact(entry.name.as_bytes())?;
this_name_nul.copy_from_slice_exact(&[0])?;
self.written += usize::from(record_len);
self.buffer = remaining;
Ok(())
}
pub fn finalize(self) -> usize {
self.written
}
}

327
vendor/redox_syscall/src/error.rs vendored Normal file
View File

@@ -0,0 +1,327 @@
use core::{fmt, result};
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Error {
pub errno: i32,
}
pub type Result<T, E = Error> = result::Result<T, E>;
impl Error {
pub fn new(errno: i32) -> Error {
Error { errno }
}
pub fn mux(result: Result<usize>) -> usize {
match result {
Ok(value) => value,
Err(error) => -error.errno as usize,
}
}
pub fn demux(value: usize) -> Result<usize> {
let errno = -(value as i32);
if errno >= 1 && errno < STR_ERROR.len() as i32 {
Err(Error::new(errno))
} else {
Ok(value)
}
}
pub fn text(&self) -> &'static str {
STR_ERROR
.get(self.errno as usize)
.map(|&x| x)
.unwrap_or("Unknown Error")
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
f.write_str(self.text())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
f.write_str(self.text())
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
#[cfg(feature = "std")]
impl From<Error> 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 */
pub const ESRCH: i32 = 3; /* No such process */
pub const EINTR: i32 = 4; /* Interrupted system call */
pub const EIO: i32 = 5; /* I/O error */
pub const ENXIO: i32 = 6; /* No such device or address */
pub const E2BIG: i32 = 7; /* Argument list too long */
pub const ENOEXEC: i32 = 8; /* Exec format error */
pub const EBADF: i32 = 9; /* Bad file number */
pub const ECHILD: i32 = 10; /* No child processes */
pub const EAGAIN: i32 = 11; /* Try again */
pub const ENOMEM: i32 = 12; /* Out of memory */
pub const EACCES: i32 = 13; /* Permission denied */
pub const EFAULT: i32 = 14; /* Bad address */
pub const ENOTBLK: i32 = 15; /* Block device required */
pub const EBUSY: i32 = 16; /* Device or resource busy */
pub const EEXIST: i32 = 17; /* File exists */
pub const EXDEV: i32 = 18; /* Cross-device link */
pub const ENODEV: i32 = 19; /* No such device */
pub const ENOTDIR: i32 = 20; /* Not a directory */
pub const EISDIR: i32 = 21; /* Is a directory */
pub const EINVAL: i32 = 22; /* Invalid argument */
pub const ENFILE: i32 = 23; /* File table overflow */
pub const EMFILE: i32 = 24; /* Too many open files */
pub const ENOTTY: i32 = 25; /* Not a typewriter */
pub const ETXTBSY: i32 = 26; /* Text file busy */
pub const EFBIG: i32 = 27; /* File too large */
pub const ENOSPC: i32 = 28; /* No space left on device */
pub const ESPIPE: i32 = 29; /* Illegal seek */
pub const EROFS: i32 = 30; /* Read-only file system */
pub const EMLINK: i32 = 31; /* Too many links */
pub const EPIPE: i32 = 32; /* Broken pipe */
pub const EDOM: i32 = 33; /* Math argument out of domain of func */
pub const ERANGE: i32 = 34; /* Math result not representable */
pub const EDEADLK: i32 = 35; /* Resource deadlock would occur */
pub const ENAMETOOLONG: i32 = 36; /* File name too long */
pub const ENOLCK: i32 = 37; /* No record locks available */
pub const ENOSYS: i32 = 38; /* Function not implemented */
pub const ENOTEMPTY: i32 = 39; /* Directory not empty */
pub const ELOOP: i32 = 40; /* Too many symbolic links encountered */
pub const EWOULDBLOCK: i32 = 41; /* Operation would block */
pub const ENOMSG: i32 = 42; /* No message of desired type */
pub const EIDRM: i32 = 43; /* Identifier removed */
pub const ECHRNG: i32 = 44; /* Channel number out of range */
pub const EL2NSYNC: i32 = 45; /* Level 2 not synchronized */
pub const EL3HLT: i32 = 46; /* Level 3 halted */
pub const EL3RST: i32 = 47; /* Level 3 reset */
pub const ELNRNG: i32 = 48; /* Link number out of range */
pub const EUNATCH: i32 = 49; /* Protocol driver not attached */
pub const ENOCSI: i32 = 50; /* No CSI structure available */
pub const EL2HLT: i32 = 51; /* Level 2 halted */
pub const EBADE: i32 = 52; /* Invalid exchange */
pub const EBADR: i32 = 53; /* Invalid request descriptor */
pub const EXFULL: i32 = 54; /* Exchange full */
pub const ENOANO: i32 = 55; /* No anode */
pub const EBADRQC: i32 = 56; /* Invalid request code */
pub const EBADSLT: i32 = 57; /* Invalid slot */
pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
pub const EBFONT: i32 = 59; /* Bad font file format */
pub const ENOSTR: i32 = 60; /* Device not a stream */
pub const ENODATA: i32 = 61; /* No data available */
pub const ETIME: i32 = 62; /* Timer expired */
pub const ENOSR: i32 = 63; /* Out of streams resources */
pub const ENONET: i32 = 64; /* Machine is not on the network */
pub const ENOPKG: i32 = 65; /* Package not installed */
pub const EREMOTE: i32 = 66; /* Object is remote */
pub const ENOLINK: i32 = 67; /* Link has been severed */
pub const EADV: i32 = 68; /* Advertise error */
pub const ESRMNT: i32 = 69; /* Srmount error */
pub const ECOMM: i32 = 70; /* Communication error on send */
pub const EPROTO: i32 = 71; /* Protocol error */
pub const EMULTIHOP: i32 = 72; /* Multihop attempted */
pub const EDOTDOT: i32 = 73; /* RFS specific error */
pub const EBADMSG: i32 = 74; /* Not a data message */
pub const EOVERFLOW: i32 = 75; /* Value too large for defined data type */
pub const ENOTUNIQ: i32 = 76; /* Name not unique on network */
pub const EBADFD: i32 = 77; /* File descriptor in bad state */
pub const EREMCHG: i32 = 78; /* Remote address changed */
pub const ELIBACC: i32 = 79; /* Can not access a needed shared library */
pub const ELIBBAD: i32 = 80; /* Accessing a corrupted shared library */
pub const ELIBSCN: i32 = 81; /* .lib section in a.out corrupted */
pub const ELIBMAX: i32 = 82; /* Attempting to link in too many shared libraries */
pub const ELIBEXEC: i32 = 83; /* Cannot exec a shared library directly */
pub const EILSEQ: i32 = 84; /* Illegal byte sequence */
pub const ERESTART: i32 = 85; /* Interrupted system call should be restarted */
pub const ESTRPIPE: i32 = 86; /* Streams pipe error */
pub const EUSERS: i32 = 87; /* Too many users */
pub const ENOTSOCK: i32 = 88; /* Socket operation on non-socket */
pub const EDESTADDRREQ: i32 = 89; /* Destination address required */
pub const EMSGSIZE: i32 = 90; /* Message too long */
pub const EPROTOTYPE: i32 = 91; /* Protocol wrong type for socket */
pub const ENOPROTOOPT: i32 = 92; /* Protocol not available */
pub const EPROTONOSUPPORT: i32 = 93; /* Protocol not supported */
pub const ESOCKTNOSUPPORT: i32 = 94; /* Socket type not supported */
pub const EOPNOTSUPP: i32 = 95; /* Operation not supported on transport endpoint */
pub const EPFNOSUPPORT: i32 = 96; /* Protocol family not supported */
pub const EAFNOSUPPORT: i32 = 97; /* Address family not supported by protocol */
pub const EADDRINUSE: i32 = 98; /* Address already in use */
pub const EADDRNOTAVAIL: i32 = 99; /* Cannot assign requested address */
pub const ENETDOWN: i32 = 100; /* Network is down */
pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
pub const ENOBUFS: i32 = 105; /* No buffer space available */
pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
pub const ECONNREFUSED: i32 = 111; /* Connection refused */
pub const EHOSTDOWN: i32 = 112; /* Host is down */
pub const EHOSTUNREACH: i32 = 113; /* No route to host */
pub const EALREADY: i32 = 114; /* Operation already in progress */
pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
pub const ESTALE: i32 = 116; /* Stale NFS file handle */
pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
pub const EISNAM: i32 = 120; /* Is a named type file */
pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
pub const EDQUOT: i32 = 122; /* Quota exceeded */
pub const ENOMEDIUM: i32 = 123; /* No medium found */
pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
pub const ECANCELED: i32 = 125; /* Operation Canceled */
pub const ENOKEY: i32 = 126; /* Required key not available */
pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
pub const EOWNERDEAD: i32 = 130; /* Owner died */
pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
pub const ESKMSG: i32 = 132; /* Scheme-kernel message code */
pub static STR_ERROR: [&'static str; 133] = [
"Success",
"Operation not permitted",
"No such file or directory",
"No such process",
"Interrupted system call",
"I/O error",
"No such device or address",
"Argument list too long",
"Exec format error",
"Bad file number",
"No child processes",
"Try again",
"Out of memory",
"Permission denied",
"Bad address",
"Block device required",
"Device or resource busy",
"File exists",
"Cross-device link",
"No such device",
"Not a directory",
"Is a directory",
"Invalid argument",
"File table overflow",
"Too many open files",
"Not a typewriter",
"Text file busy",
"File too large",
"No space left on device",
"Illegal seek",
"Read-only file system",
"Too many links",
"Broken pipe",
"Math argument out of domain of func",
"Math result not representable",
"Resource deadlock would occur",
"File name too long",
"No record locks available",
"Function not implemented",
"Directory not empty",
"Too many symbolic links encountered",
"Operation would block",
"No message of desired type",
"Identifier removed",
"Channel number out of range",
"Level 2 not synchronized",
"Level 3 halted",
"Level 3 reset",
"Link number out of range",
"Protocol driver not attached",
"No CSI structure available",
"Level 2 halted",
"Invalid exchange",
"Invalid request descriptor",
"Exchange full",
"No anode",
"Invalid request code",
"Invalid slot",
"Resource deadlock would occur",
"Bad font file format",
"Device not a stream",
"No data available",
"Timer expired",
"Out of streams resources",
"Machine is not on the network",
"Package not installed",
"Object is remote",
"Link has been severed",
"Advertise error",
"Srmount error",
"Communication error on send",
"Protocol error",
"Multihop attempted",
"RFS specific error",
"Not a data message",
"Value too large for defined data type",
"Name not unique on network",
"File descriptor in bad state",
"Remote address changed",
"Can not access a needed shared library",
"Accessing a corrupted shared library",
".lib section in a.out corrupted",
"Attempting to link in too many shared libraries",
"Cannot exec a shared library directly",
"Illegal byte sequence",
"Interrupted system call should be restarted",
"Streams pipe error",
"Too many users",
"Socket operation on non-socket",
"Destination address required",
"Message too long",
"Protocol wrong type for socket",
"Protocol not available",
"Protocol not supported",
"Socket type not supported",
"Operation not supported on transport endpoint",
"Protocol family not supported",
"Address family not supported by protocol",
"Address already in use",
"Cannot assign requested address",
"Network is down",
"Network is unreachable",
"Network dropped connection because of reset",
"Software caused connection abort",
"Connection reset by peer",
"No buffer space available",
"Transport endpoint is already connected",
"Transport endpoint is not connected",
"Cannot send after transport endpoint shutdown",
"Too many references: cannot splice",
"Connection timed out",
"Connection refused",
"Host is down",
"No route to host",
"Operation already in progress",
"Operation now in progress",
"Stale NFS file handle",
"Structure needs cleaning",
"Not a XENIX named type file",
"No XENIX semaphores available",
"Is a named type file",
"Remote I/O error",
"Quota exceeded",
"No medium found",
"Wrong medium type",
"Operation Canceled",
"Required key not available",
"Key has expired",
"Key has been revoked",
"Key was rejected by service",
"Owner died",
"State not recoverable",
"Scheme-kernel message code",
];

406
vendor/redox_syscall/src/flag.rs vendored Normal file
View File

@@ -0,0 +1,406 @@
use bitflags::bitflags as inner_bitflags;
use core::{mem, ops::Deref, slice};
macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => {
// First, use the inner bitflags
inner_bitflags! {
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy, Default)]
$(#[$outer])*
pub struct $BitFlags: $T {
$(
$(#[$inner $($args)*])*
const $Flag = $value;
)+
}
}
impl $BitFlags {
#[deprecated = "use the safe `from_bits_retain` method instead"]
pub unsafe fn from_bits_unchecked(bits: $T) -> Self {
Self::from_bits_retain(bits)
}
}
// Secondly, re-export all inner constants
// (`pub use self::Struct::*` doesn't work)
$(
$(#[$inner $($args)*])*
pub const $Flag: $BitFlags = $BitFlags::$Flag;
)+
}
}
pub const CLOCK_REALTIME: usize = 1;
pub const CLOCK_MONOTONIC: usize = 4;
bitflags! {
pub struct EventFlags: usize {
const EVENT_NONE = 0;
const EVENT_READ = 1;
const EVENT_WRITE = 2;
}
}
pub const F_DUPFD: usize = 0;
pub const F_GETFD: usize = 1;
pub const F_SETFD: usize = 2;
pub const F_GETFL: usize = 3;
pub const F_SETFL: usize = 4;
pub const FUTEX_WAIT: usize = 0;
pub const FUTEX_WAKE: usize = 1;
pub const FUTEX_REQUEUE: usize = 2;
pub const FUTEX_WAIT64: usize = 3;
// packet.c = fd
pub const SKMSG_FRETURNFD: usize = 0;
// packet.uid:packet.gid = offset, packet.c = base address, packet.d = page count
pub const SKMSG_PROVIDE_MMAP: usize = 1;
// packet.id provides state, packet.c = dest fd or pointer to dest fd, packet.d = flags
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 descriptors are exclusively owned.
///
/// That is, there will no longer exist any other reference to those FDs when removed from
/// the file table (sendfd always removes the FDs from the file table, but without this
/// flag, it can be retained by SYS_DUPing them first).
const EXCLUSIVE = 1;
/// If set, the file descriptors will be cloned and *not* removed from the sender's file table.
/// By default, `SYS_SENDFD` moves the file descriptors, removing them from the sender.
const CLONE = 2;
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct FobtainFdFlags: usize {
/// If set, the SYS_CALL payload specifies the destination file descriptor slots, otherwise the lowest
/// available slots will be selected, and placed in the usize pointed to by SYS_CALL
/// payload.
const MANUAL_FD = 1;
/// If set, the file descriptors received are guaranteed to be exclusively owned (by the file
/// table the obtainer is running in).
const EXCLUSIVE = 2;
/// If set, the file descriptors received will be placed into the *upper* file table.
const UPPER_TBL = 4;
// No, cloexec won't be stored in the kernel in the future, when the stable ABI is moved to
// relibc, so no flag for that!
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct RecvFdFlags: usize {
/// If set, the SYS_CALL payload specifies the destination file descriptor slots, otherwise the lowest
/// available slots will be selected, and placed in the usize pointed to by SYS_CALL
/// payload.
const MANUAL_FD = 1;
/// If set, the file descriptors received will be placed into the *upper* file table.
const UPPER_TBL = 2;
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct FmoveFdFlags: usize {
/// If set, the kernel will enforce that the file descriptors are exclusively owned.
///
/// That is, there will no longer exist any other reference to those FDs when removed from
/// the file table (SYS_CALL always removes the FDs from the file table, but without this
/// flag, it can be retained by SYS_DUPing them first).
const EXCLUSIVE = 1;
/// If set, the file descriptors will be cloned and *not* removed from the sender's file table.
/// By default, sendfd moves the file descriptors, removing them from the sender.
const CLONE = 2;
}
}
bitflags! {
pub struct MapFlags: usize {
// TODO: Downgrade PROT_NONE to global constant? (bitflags specifically states zero flags
// can cause buggy behavior).
const PROT_NONE = 0x0000_0000;
const PROT_EXEC = 0x0001_0000;
const PROT_WRITE = 0x0002_0000;
const PROT_READ = 0x0004_0000;
const MAP_SHARED = 0x0001;
const MAP_PRIVATE = 0x0002;
const MAP_FIXED = 0x0004;
const MAP_FIXED_NOREPLACE = 0x000C;
/// For *userspace-backed mmaps*, return from the mmap call before all pages have been
/// provided by the scheme. This requires the scheme to be trusted, as the current context
/// can block indefinitely, if the scheme does not respond to the page fault handler's
/// request, as it tries to map the page by requesting it from the scheme.
///
/// In some cases however, such as the program loader, the data needs to be trusted as much
/// with or without MAP_LAZY, and if so, mapping lazily will not cause insecureness by
/// itself.
///
/// For kernel-backed mmaps, this flag has no effect at all. It is unspecified whether
/// kernel mmaps are lazy or not.
const MAP_LAZY = 0x0010;
}
}
bitflags! {
pub struct MunmapFlags: usize {
/// Indicates whether the funmap call must implicitly do an msync, for the changes to
/// become visible later.
///
/// This flag will currently be set if and only if MAP_SHARED | PROT_WRITE are set.
const NEEDS_SYNC = 1;
}
}
pub const MODE_TYPE: u16 = 0xF000;
pub const MODE_DIR: u16 = 0x4000;
pub const MODE_FILE: u16 = 0x8000;
pub const MODE_SYMLINK: u16 = 0xA000;
pub const MODE_FIFO: u16 = 0x1000;
pub const MODE_CHR: u16 = 0x2000;
pub const MODE_SOCK: u16 = 0xC000;
pub const MODE_PERM: u16 = 0x0FFF;
pub const MODE_SETUID: u16 = 0o4000;
pub const MODE_SETGID: u16 = 0o2000;
pub const O_RDONLY: usize = 0x0001_0000;
pub const O_WRONLY: usize = 0x0002_0000;
pub const O_RDWR: usize = 0x0003_0000;
pub const O_NONBLOCK: usize = 0x0004_0000;
pub const O_APPEND: usize = 0x0008_0000;
pub const O_SHLOCK: usize = 0x0010_0000;
pub const O_EXLOCK: usize = 0x0020_0000;
pub const O_ASYNC: usize = 0x0040_0000;
pub const O_FSYNC: usize = 0x0080_0000;
pub const O_CLOEXEC: usize = 0x0100_0000;
pub const O_CREAT: usize = 0x0200_0000;
pub const O_TRUNC: usize = 0x0400_0000;
pub const O_EXCL: usize = 0x0800_0000;
pub const O_DIRECTORY: usize = 0x1000_0000;
pub const O_STAT: usize = 0x2000_0000;
pub const O_SYMLINK: usize = 0x4000_0000;
pub const O_NOFOLLOW: usize = 0x8000_0000;
pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR;
// The top 48 bits of PTRACE_* are reserved, for now
// NOT ABI STABLE!
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(usize)]
pub enum ContextStatus {
Runnable,
Blocked,
NotYetStarted,
Dead,
ForceKilled,
Stopped,
UnhandledExcp,
#[default]
Other, // reserved
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
pub enum ContextVerb {
Stop = 1,
Unstop = 2,
Interrupt = 3,
ForceKill = usize::MAX,
}
impl ContextVerb {
pub fn try_from_raw(raw: usize) -> Option<Self> {
Some(match raw {
1 => Self::Stop,
2 => Self::Unstop,
3 => Self::Interrupt,
usize::MAX => Self::ForceKill,
_ => return None,
})
}
}
// NOT ABI STABLE!
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum ProcSchemeVerb {
Iopl = 255,
}
impl ProcSchemeVerb {
pub fn try_from_raw(verb: u8) -> Option<Self> {
Some(match verb {
255 => Self::Iopl,
_ => return None,
})
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
pub enum SchemeSocketCall {
ObtainFd = 0,
MoveFd = 1,
}
impl SchemeSocketCall {
pub fn try_from_raw(raw: usize) -> Option<Self> {
Some(match raw {
0 => Self::ObtainFd,
1 => Self::MoveFd,
_ => return None,
})
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
#[non_exhaustive]
pub enum FsCall {
Connect = 0,
}
impl FsCall {
pub fn try_from_raw(raw: usize) -> Option<Self> {
Some(match raw {
0 => Self::Connect,
_ => return None,
})
}
}
bitflags! {
pub struct PtraceFlags: u64 {
/// Stop before a syscall is handled. Send PTRACE_FLAG_IGNORE to not
/// handle the syscall.
const PTRACE_STOP_PRE_SYSCALL = 0x0000_0000_0000_0001;
/// Stop after a syscall is handled.
const PTRACE_STOP_POST_SYSCALL = 0x0000_0000_0000_0002;
/// Stop after exactly one instruction. TODO: This may not handle
/// fexec/signal boundaries. Should it?
const PTRACE_STOP_SINGLESTEP = 0x0000_0000_0000_0004;
/// Stop before a signal is handled. Send PTRACE_FLAG_IGNORE to not
/// handle signal.
const PTRACE_STOP_SIGNAL = 0x0000_0000_0000_0008;
/// Stop on a software breakpoint, such as the int3 instruction for
/// x86_64.
const PTRACE_STOP_BREAKPOINT = 0x0000_0000_0000_0010;
/// Stop just before exiting for good.
const PTRACE_STOP_EXIT = 0x0000_0000_0000_0020;
const PTRACE_STOP_MASK = 0x0000_0000_0000_00FF;
/// Sent when a child is cloned, giving you the opportunity to trace it.
/// If you don't catch this, the child is started as normal.
const PTRACE_EVENT_CLONE = 0x0000_0000_0000_0100;
/// Sent when current-addrspace is changed, allowing the tracer to reopen the memory file.
const PTRACE_EVENT_ADDRSPACE_SWITCH = 0x0000_0000_0000_0200;
const PTRACE_EVENT_MASK = 0x0000_0000_0000_0F00;
/// Special meaning, depending on the event. Usually, when fired before
/// an action, it will skip performing that action.
const PTRACE_FLAG_IGNORE = 0x0000_0000_0000_1000;
const PTRACE_FLAG_MASK = 0x0000_0000_0000_F000;
}
}
impl Deref for PtraceFlags {
type Target = [u8];
fn deref(&self) -> &Self::Target {
// Same as to_ne_bytes but in-place
unsafe {
slice::from_raw_parts(&self.bits() as *const _ as *const u8, mem::size_of::<u64>())
}
}
}
pub const SEEK_SET: usize = 0;
pub const SEEK_CUR: usize = 1;
pub const SEEK_END: usize = 2;
pub const SIGCHLD: usize = 17;
pub const SIGTSTP: usize = 20;
pub const SIGTTIN: usize = 21;
pub const SIGTTOU: usize = 22;
pub const ADDRSPACE_OP_MMAP: usize = 0;
pub const ADDRSPACE_OP_MUNMAP: usize = 1;
pub const ADDRSPACE_OP_MPROTECT: usize = 2;
pub const ADDRSPACE_OP_TRANSFER: usize = 3;
bitflags! {
pub struct MremapFlags: usize {
const FIXED = 1;
const FIXED_REPLACE = 3;
/// Alias's memory region at `old_address` to `new_address` such that both regions share
/// the same frames.
const KEEP_OLD = 1 << 2;
// TODO: MAYMOVE, DONTUNMAP
}
}
bitflags! {
pub struct RwFlags: u32 {
const NONBLOCK = 1;
const APPEND = 2;
// TODO: sync/dsync
// TODO: O_DIRECT?
}
}
bitflags! {
pub struct SigcontrolFlags: usize {
/// Prevents the kernel from jumping the context to the signal trampoline, but otherwise
/// has absolutely no effect on which signals are blocked etc. Meant to be used for
/// short-lived critical sections inside libc.
const INHIBIT_DELIVERY = 1;
}
}
bitflags! {
pub struct CallFlags: usize {
// reserved
const RSVD0 = 1 << 0;
const RSVD1 = 1 << 1;
const RSVD2 = 1 << 2;
const RSVD3 = 1 << 3;
const RSVD4 = 1 << 4;
const RSVD5 = 1 << 5;
const RSVD6 = 1 << 6;
const RSVD7 = 1 << 7;
/// Remove the fd from the caller's file table before sending the message.
const CONSUME = 1 << 8;
const WRITE = 1 << 9;
const READ = 1 << 10;
/// Indicates the request is a bulk fd passing request.
const FD = 1 << 11;
/// Flags for the fd passing request.
const FD_EXCLUSIVE = 1 << 12;
const FD_CLONE = 1 << 13;
const FD_UPPER = 1 << 14;
}
}
/// The tag for the fd number in the upper file descriptor table.
pub const UPPER_FDTBL_TAG: usize = 1 << (usize::BITS - 2);

73
vendor/redox_syscall/src/io/io.rs vendored Normal file
View File

@@ -0,0 +1,73 @@
use core::{
cmp::PartialEq,
ops::{BitAnd, BitOr, Not},
};
pub trait Io {
type Value: Copy
+ PartialEq
+ BitAnd<Output = Self::Value>
+ BitOr<Output = Self::Value>
+ Not<Output = Self::Value>;
fn read(&self) -> Self::Value;
fn write(&mut self, value: Self::Value);
#[inline(always)]
fn readf(&self, flags: Self::Value) -> bool {
(self.read() & flags) as Self::Value == flags
}
#[inline(always)]
fn writef(&mut self, flags: Self::Value, value: bool) {
let tmp: Self::Value = match value {
true => self.read() | flags,
false => self.read() & !flags,
};
self.write(tmp);
}
}
pub struct ReadOnly<I> {
inner: I,
}
impl<I> ReadOnly<I> {
pub const fn new(inner: I) -> ReadOnly<I> {
ReadOnly { inner: inner }
}
}
impl<I: Io> ReadOnly<I> {
#[inline(always)]
pub fn read(&self) -> I::Value {
self.inner.read()
}
#[inline(always)]
pub fn readf(&self, flags: I::Value) -> bool {
self.inner.readf(flags)
}
}
pub struct WriteOnly<I> {
inner: I,
}
impl<I> WriteOnly<I> {
pub const fn new(inner: I) -> WriteOnly<I> {
WriteOnly { inner: inner }
}
}
impl<I: Io> WriteOnly<I> {
#[inline(always)]
pub fn write(&mut self, value: I::Value) {
self.inner.write(value)
}
#[inline(always)]
pub fn writef(&mut self, flags: I::Value, value: bool) {
self.inner.writef(flags, value)
}
}

165
vendor/redox_syscall/src/io/mmio.rs vendored Normal file
View File

@@ -0,0 +1,165 @@
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
use core::ops::{BitAnd, BitOr, Not};
use core::{mem::MaybeUninit, ptr};
use super::io::Io;
#[repr(transparent)]
pub struct Mmio<T> {
value: MaybeUninit<T>,
}
impl<T> Mmio<T> {
pub unsafe fn zeroed() -> Self {
Self {
value: MaybeUninit::zeroed(),
}
}
pub unsafe fn uninit() -> Self {
Self {
value: MaybeUninit::uninit(),
}
}
pub const fn from(value: T) -> Self {
Self {
value: MaybeUninit::new(value),
}
}
}
// Generic implementation (WARNING: requires aligned pointers!)
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl<T> Io for Mmio<T>
where
T: Copy + PartialEq + BitAnd<Output = T> + BitOr<Output = T> + Not<Output = T>,
{
type Value = T;
fn read(&self) -> T {
unsafe { ptr::read_volatile(ptr::addr_of!(self.value).cast::<T>()) }
}
fn write(&mut self, value: T) {
unsafe { ptr::write_volatile(ptr::addr_of_mut!(self.value).cast::<T>(), value) };
}
}
// x86 u8 implementation
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl Io for Mmio<u8> {
type Value = u8;
fn read(&self) -> Self::Value {
unsafe {
let value: Self::Value;
let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov {}, [{}]",
out(reg_byte) value,
in(reg) ptr
);
value
}
}
fn write(&mut self, value: Self::Value) {
unsafe {
let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov [{}], {}",
in(reg) ptr,
in(reg_byte) value,
);
}
}
}
// x86 u16 implementation
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl Io for Mmio<u16> {
type Value = u16;
fn read(&self) -> Self::Value {
unsafe {
let value: Self::Value;
let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov {:x}, [{}]",
out(reg) value,
in(reg) ptr
);
value
}
}
fn write(&mut self, value: Self::Value) {
unsafe {
let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov [{}], {:x}",
in(reg) ptr,
in(reg) value,
);
}
}
}
// x86 u32 implementation
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl Io for Mmio<u32> {
type Value = u32;
fn read(&self) -> Self::Value {
unsafe {
let value: Self::Value;
let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov {:e}, [{}]",
out(reg) value,
in(reg) ptr
);
value
}
}
fn write(&mut self, value: Self::Value) {
unsafe {
let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov [{}], {:e}",
in(reg) ptr,
in(reg) value,
);
}
}
}
// x86 u64 implementation (x86_64 only)
#[cfg(target_arch = "x86_64")]
impl Io for Mmio<u64> {
type Value = u64;
fn read(&self) -> Self::Value {
unsafe {
let value: Self::Value;
let ptr: *const Self::Value = ptr::addr_of!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov {:r}, [{}]",
out(reg) value,
in(reg) ptr
);
value
}
}
fn write(&mut self, value: Self::Value) {
unsafe {
let ptr: *mut Self::Value = ptr::addr_of_mut!(self.value).cast::<Self::Value>();
core::arch::asm!(
"mov [{}], {:r}",
in(reg) ptr,
in(reg) value,
);
}
}
}

12
vendor/redox_syscall/src/io/mod.rs vendored Normal file
View File

@@ -0,0 +1,12 @@
//! I/O functions
pub use self::{io::*, mmio::*};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::pio::*;
mod io;
mod mmio;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod pio;

89
vendor/redox_syscall/src/io/pio.rs vendored Normal file
View File

@@ -0,0 +1,89 @@
use core::{arch::asm, marker::PhantomData};
use super::io::Io;
/// Generic PIO
#[derive(Copy, Clone)]
pub struct Pio<T> {
port: u16,
value: PhantomData<T>,
}
impl<T> Pio<T> {
/// Create a PIO from a given port
pub const fn new(port: u16) -> Self {
Pio::<T> {
port,
value: PhantomData,
}
}
}
/// Read/Write for byte PIO
impl Io for Pio<u8> {
type Value = u8;
/// Read
#[inline(always)]
fn read(&self) -> u8 {
let value: u8;
unsafe {
asm!("in al, dx", in("dx") self.port, out("al") value, options(nostack, nomem, preserves_flags));
}
value
}
/// Write
#[inline(always)]
fn write(&mut self, value: u8) {
unsafe {
asm!("out dx, al", in("dx") self.port, in("al") value, options(nostack, nomem, preserves_flags));
}
}
}
/// Read/Write for word PIO
impl Io for Pio<u16> {
type Value = u16;
/// Read
#[inline(always)]
fn read(&self) -> u16 {
let value: u16;
unsafe {
asm!("in ax, dx", in("dx") self.port, out("ax") value, options(nostack, nomem, preserves_flags));
}
value
}
/// Write
#[inline(always)]
fn write(&mut self, value: u16) {
unsafe {
asm!("out dx, ax", in("dx") self.port, in("ax") value, options(nostack, nomem, preserves_flags));
}
}
}
/// Read/Write for doubleword PIO
impl Io for Pio<u32> {
type Value = u32;
/// Read
#[inline(always)]
fn read(&self) -> u32 {
let value: u32;
unsafe {
asm!("in eax, dx", in("dx") self.port, out("eax") value, options(nostack, nomem, preserves_flags));
}
value
}
/// Write
#[inline(always)]
fn write(&mut self, value: u32) {
unsafe {
asm!("out dx, eax", in("dx") self.port, in("eax") value, options(nostack, nomem, preserves_flags));
}
}
}

56
vendor/redox_syscall/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,56 @@
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![allow(unexpected_cfgs)] // why does this even exist?
#[cfg(test)]
extern crate core;
pub use self::{arch::*, data::*, error::*, flag::*, io::*, number::*};
#[cfg(target_arch = "aarch64")]
#[path = "arch/aarch64.rs"]
mod arch;
#[cfg(target_arch = "riscv64")]
#[path = "arch/riscv64.rs"]
mod arch;
#[cfg(target_arch = "x86")]
#[path = "arch/x86.rs"]
mod arch;
#[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64.rs"]
mod arch;
/// Function definitions
#[cfg(feature = "userspace")]
pub mod call;
#[cfg(feature = "userspace")]
pub use call::*;
/// Complex structures that are used for some system calls
pub mod data;
pub mod dirent;
/// All errors that can be generated by a system call
pub mod error;
/// Flags used as an argument to many system calls
pub mod flag;
/// Functions for low level hardware control
pub mod io;
/// Call numbers used by each system call
pub mod number;
/// ABI for shared memory based signals
pub mod sigabi;
/// V2 scheme format
pub mod schemev2;
pub mod scheme;
pub use scheme::*;

75
vendor/redox_syscall/src/number.rs vendored Normal file
View File

@@ -0,0 +1,75 @@
pub const SYS_CLASS: usize = 0xF000_0000;
pub const SYS_CLASS_PATH: usize = 0x1000_0000;
pub const SYS_CLASS_FILE: usize = 0x2000_0000;
pub const SYS_ARG: usize = 0x0F00_0000;
pub const SYS_ARG_SLICE: usize = 0x0100_0000;
pub const SYS_ARG_MSLICE: usize = 0x0200_0000;
pub const SYS_ARG_PATH: usize = 0x0300_0000;
pub const SYS_RET: usize = 0x00F0_0000;
pub const SYS_RET_FILE: usize = 0x0010_0000;
pub const SYS_OPEN: usize = SYS_CLASS_PATH | SYS_RET_FILE | 5;
pub const SYS_OPENAT: usize = SYS_CLASS_PATH | SYS_RET_FILE | 7;
pub const SYS_RMDIR: usize = SYS_CLASS_PATH | 84;
pub const SYS_UNLINK: usize = SYS_CLASS_PATH | 10;
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;
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
// SYS_CALL, fd, inout buf ptr, inout buf len, flags, metadata buf ptr, metadata buf len
pub const SYS_CALL: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | SYS_ARG_MSLICE | 0xCA11;
pub const SYS_SENDFD: usize = SYS_CLASS_FILE | 34;
pub const SYS_GETDENTS: usize = SYS_CLASS_FILE | 43;
// TODO: Rename FMAP/FUNMAP to MMAP/MUNMAP
pub const SYS_FMAP_OLD: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 90;
pub const SYS_FMAP: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 900;
// TODO: SYS_FUNMAP should be SYS_CLASS_FILE
// TODO: Remove FMAP/FMAP_OLD
pub const SYS_FUNMAP_OLD: usize = SYS_CLASS_FILE | 91;
pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 92;
pub const SYS_MREMAP: usize = 155;
pub const SYS_FLINK: usize = SYS_CLASS_FILE | SYS_ARG_PATH | 9;
pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
pub const SYS_FRENAME: usize = SYS_CLASS_FILE | SYS_ARG_PATH | 38;
pub const SYS_FSTAT: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
pub const SYS_FSYNC: usize = SYS_CLASS_FILE | 118;
pub const SYS_FTRUNCATE: usize = SYS_CLASS_FILE | 93;
pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320;
// b = file, c = flags, d = required_page_count, uid:gid = offset
pub const KSMSG_MMAP: usize = SYS_CLASS_FILE | 72;
// b = file, c = flags, d = page_count, uid:gid = offset
pub const KSMSG_MSYNC: usize = SYS_CLASS_FILE | 73;
// b = file, c = page_count, uid:gid = offset
pub const KSMSG_MUNMAP: usize = SYS_CLASS_FILE | 74;
// b = file, c = flags, d = page_count, uid:gid = offset
pub const KSMSG_MMAP_PREP: usize = SYS_CLASS_FILE | 75;
// b = target_packetid_lo32, c = target_packetid_hi32
pub const KSMSG_CANCEL: usize = SYS_CLASS_FILE | 76;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const SYS_FUTEX: usize = 240;
pub const SYS_MPROTECT: usize = 125;
pub const SYS_MKNS: usize = 984;
pub const SYS_NANOSLEEP: usize = 162;
pub const SYS_YIELD: usize = 158;

25
vendor/redox_syscall/src/scheme/generate.sh vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -e
echo "Generating SchemeMut from Scheme"
sed 's/trait Scheme/trait SchemeMut/' scheme.rs \
| sed 's/\&self/\&mut self/g' \
> scheme_mut.rs
echo "Generating SchemeBlock from Scheme"
sed 's/trait Scheme/trait SchemeBlock/' scheme.rs \
| sed 's/fn handle(\&self, packet: \&mut Packet)/fn handle(\&self, packet: \&Packet) -> Option<usize>/' \
| sed 's/packet.a = Error::mux(res);/res.transpose().map(Error::mux)/' \
| sed 's/\.map(|f| f\.bits())/\.map(|f| f.map(|f| f.bits()))/' \
| sed 's/\.map(|o| o as usize)/.map(|o| o.map(|o| o as usize))/' \
| sed 's/Ok(0)/Ok(Some(0))/g' \
| sed 's/Result<\([^>]\+\)>/Result<Option<\1>>/g' \
| sed 's/convert_to_this_scheme/convert_to_this_scheme_block/g' \
| sed 's/convert_in_scheme_handle/convert_in_scheme_handle_block/g' \
> scheme_block.rs
echo "Generating SchemeBlockMut from SchemeBlock"
sed 's/trait SchemeBlock/trait SchemeBlockMut/' scheme_block.rs \
| sed 's/\&self/\&mut self/g' \
> scheme_block_mut.rs

73
vendor/redox_syscall/src/scheme/mod.rs vendored Normal file
View File

@@ -0,0 +1,73 @@
use core::{slice, str};
use crate::{Error, Packet, Result, EOPNOTSUPP, ESKMSG, SKMSG_FRETURNFD};
pub use self::{
scheme::Scheme, scheme_block::SchemeBlock, scheme_block_mut::SchemeBlockMut,
scheme_mut::SchemeMut, seek::*,
};
unsafe fn str_from_raw_parts(ptr: *const u8, len: usize) -> Option<&'static str> {
let slice = slice::from_raw_parts(ptr, len);
str::from_utf8(slice).ok()
}
mod scheme;
mod scheme_block;
mod scheme_block_mut;
mod scheme_mut;
mod seek;
pub struct CallerCtx {
pub pid: usize,
pub uid: u32,
pub gid: u32,
}
pub enum OpenResult {
ThisScheme { number: usize },
OtherScheme { fd: usize },
}
// TODO: Find a better solution than generate.sh
pub(crate) fn convert_to_this_scheme(r: Result<usize>) -> Result<OpenResult> {
r.map(|number| OpenResult::ThisScheme { number })
}
pub(crate) fn convert_to_this_scheme_block(r: Result<Option<usize>>) -> Result<Option<OpenResult>> {
r.map(|o| o.map(|number| OpenResult::ThisScheme { number }))
}
pub(crate) fn convert_in_scheme_handle_block(
_: &Packet,
result: Result<Option<OpenResult>>,
) -> Result<Option<usize>> {
match result {
Ok(Some(OpenResult::ThisScheme { number })) => Ok(Some(number)),
Ok(Some(OpenResult::OtherScheme { .. })) => Err(Error::new(EOPNOTSUPP)),
Ok(None) => Ok(None),
Err(err) => Err(err),
}
}
pub(crate) fn convert_in_scheme_handle(
packet: &mut Packet,
result: Result<OpenResult>,
) -> Result<usize> {
match result {
Ok(OpenResult::ThisScheme { number }) => Ok(number),
Ok(OpenResult::OtherScheme { fd }) => {
packet.b = SKMSG_FRETURNFD;
packet.c = fd;
Err(Error::new(ESKMSG))
}
Err(err) => Err(err),
}
}
impl CallerCtx {
pub fn from_packet(packet: &Packet) -> Self {
Self {
pid: packet.pid,
uid: packet.uid,
gid: packet.gid,
}
}
}

View File

@@ -0,0 +1,248 @@
use core::{mem, slice};
use crate::{data::*, error::*, flag::*, number::*, scheme::*, CallerCtx, OpenResult};
pub trait Scheme {
fn handle(&self, packet: &mut Packet) {
let res = match packet.a {
SYS_OPEN => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
convert_in_scheme_handle(
packet,
self.xopen(path, packet.d, &CallerCtx::from_packet(&packet)),
)
} else {
Err(Error::new(EINVAL))
}
}
SYS_RMDIR => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_UNLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_DUP => convert_in_scheme_handle(
packet,
self.xdup(
packet.b,
unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) },
&CallerCtx::from_packet(&packet),
),
),
SYS_READ => self.read(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_WRITE => self.write(packet.b, unsafe {
slice::from_raw_parts(packet.c as *const u8, packet.d)
}),
SYS_LSEEK => self
.seek(packet.b, packet.c as isize, packet.d)
.map(|o| o as usize),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self
.fevent(packet.b, EventFlags::from_bits_truncate(packet.c))
.map(|f| f.bits()),
SYS_FLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.flink(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FPATH => self.fpath(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_FRENAME => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FSTAT => {
if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSTATVFS => {
if packet.d >= mem::size_of::<StatVfs>() {
self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSYNC => self.fsync(packet.b),
SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c),
SYS_FUTIMENS => {
if packet.d >= mem::size_of::<TimeSpec>() {
self.futimens(packet.b, unsafe {
slice::from_raw_parts(
packet.c as *const TimeSpec,
packet.d / mem::size_of::<TimeSpec>(),
)
})
} else {
Err(Error::new(EFAULT))
}
}
SYS_CLOSE => self.close(packet.b),
KSMSG_MMAP_PREP => self.mmap_prep(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MapFlags::from_bits_truncate(packet.d),
),
KSMSG_MUNMAP => self.munmap(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MunmapFlags::from_bits_truncate(packet.d),
),
_ => Err(Error::new(ENOSYS)),
};
packet.a = Error::mux(res);
}
/* Scheme operations */
#[allow(unused_variables)]
fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn xopen(&self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
convert_to_this_scheme(self.open(path, flags, ctx.uid, ctx.gid))
}
#[allow(unused_variables)]
fn chmod(&self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
/* Resource operations */
#[allow(unused_variables)]
fn dup(&self, old_id: usize, buf: &[u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn xdup(&self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
convert_to_this_scheme(self.dup(old_id, buf))
}
#[allow(unused_variables)]
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchmod(&self, id: usize, mode: u16) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn flink(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn frename(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fsync(&self, id: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn ftruncate(&self, id: usize, len: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn futimens(&self, id: usize, times: &[TimeSpec]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn close(&self, id: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn mmap_prep(&self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
#[allow(unused_variables)]
fn munmap(&self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
}

View File

@@ -0,0 +1,248 @@
use core::{mem, slice};
use crate::{data::*, error::*, flag::*, number::*, scheme::*, CallerCtx, OpenResult};
pub trait SchemeBlock {
fn handle(&self, packet: &Packet) -> Option<usize> {
let res = match packet.a {
SYS_OPEN => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
convert_in_scheme_handle_block(
packet,
self.xopen(path, packet.d, &CallerCtx::from_packet(&packet)),
)
} else {
Err(Error::new(EINVAL))
}
}
SYS_RMDIR => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_UNLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_DUP => convert_in_scheme_handle_block(
packet,
self.xdup(
packet.b,
unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) },
&CallerCtx::from_packet(&packet),
),
),
SYS_READ => self.read(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_WRITE => self.write(packet.b, unsafe {
slice::from_raw_parts(packet.c as *const u8, packet.d)
}),
SYS_LSEEK => self
.seek(packet.b, packet.c as isize, packet.d)
.map(|o| o.map(|o| o as usize)),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self
.fevent(packet.b, EventFlags::from_bits_truncate(packet.c))
.map(|f| f.map(|f| f.bits())),
SYS_FLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.flink(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FPATH => self.fpath(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_FRENAME => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FSTAT => {
if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSTATVFS => {
if packet.d >= mem::size_of::<StatVfs>() {
self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSYNC => self.fsync(packet.b),
SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c),
SYS_FUTIMENS => {
if packet.d >= mem::size_of::<TimeSpec>() {
self.futimens(packet.b, unsafe {
slice::from_raw_parts(
packet.c as *const TimeSpec,
packet.d / mem::size_of::<TimeSpec>(),
)
})
} else {
Err(Error::new(EFAULT))
}
}
SYS_CLOSE => self.close(packet.b),
KSMSG_MMAP_PREP => self.mmap_prep(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MapFlags::from_bits_truncate(packet.d),
),
KSMSG_MUNMAP => self.munmap(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MunmapFlags::from_bits_truncate(packet.d),
),
_ => Err(Error::new(ENOSYS)),
};
res.transpose().map(Error::mux)
}
/* Scheme operations */
#[allow(unused_variables)]
fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn xopen(&self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<Option<OpenResult>> {
convert_to_this_scheme_block(self.open(path, flags, ctx.uid, ctx.gid))
}
#[allow(unused_variables)]
fn chmod(&self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
/* Resource operations */
#[allow(unused_variables)]
fn dup(&self, old_id: usize, buf: &[u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn xdup(&self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<Option<OpenResult>> {
convert_to_this_scheme_block(self.dup(old_id, buf))
}
#[allow(unused_variables)]
fn read(&self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn write(&self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchmod(&self, id: usize, mode: u16) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fevent(&self, id: usize, flags: EventFlags) -> Result<Option<EventFlags>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn flink(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn frename(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstat(&self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fsync(&self, id: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn ftruncate(&self, id: usize, len: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn futimens(&self, id: usize, times: &[TimeSpec]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn close(&self, id: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn mmap_prep(&self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<Option<usize>> {
Err(Error::new(EOPNOTSUPP))
}
#[allow(unused_variables)]
fn munmap(&self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result<Option<usize>> {
Err(Error::new(EOPNOTSUPP))
}
}

View File

@@ -0,0 +1,248 @@
use core::{mem, slice};
use crate::{data::*, error::*, flag::*, number::*, scheme::*, CallerCtx, OpenResult};
pub trait SchemeBlockMut {
fn handle(&mut self, packet: &Packet) -> Option<usize> {
let res = match packet.a {
SYS_OPEN => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
convert_in_scheme_handle_block(
packet,
self.xopen(path, packet.d, &CallerCtx::from_packet(&packet)),
)
} else {
Err(Error::new(EINVAL))
}
}
SYS_RMDIR => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_UNLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_DUP => convert_in_scheme_handle_block(
packet,
self.xdup(
packet.b,
unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) },
&CallerCtx::from_packet(&packet),
),
),
SYS_READ => self.read(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_WRITE => self.write(packet.b, unsafe {
slice::from_raw_parts(packet.c as *const u8, packet.d)
}),
SYS_LSEEK => self
.seek(packet.b, packet.c as isize, packet.d)
.map(|o| o.map(|o| o as usize)),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self
.fevent(packet.b, EventFlags::from_bits_truncate(packet.c))
.map(|f| f.map(|f| f.bits())),
SYS_FLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.flink(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FPATH => self.fpath(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_FRENAME => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FSTAT => {
if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSTATVFS => {
if packet.d >= mem::size_of::<StatVfs>() {
self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSYNC => self.fsync(packet.b),
SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c),
SYS_FUTIMENS => {
if packet.d >= mem::size_of::<TimeSpec>() {
self.futimens(packet.b, unsafe {
slice::from_raw_parts(
packet.c as *const TimeSpec,
packet.d / mem::size_of::<TimeSpec>(),
)
})
} else {
Err(Error::new(EFAULT))
}
}
SYS_CLOSE => self.close(packet.b),
KSMSG_MMAP_PREP => self.mmap_prep(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MapFlags::from_bits_truncate(packet.d),
),
KSMSG_MUNMAP => self.munmap(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MunmapFlags::from_bits_truncate(packet.d),
),
_ => Err(Error::new(ENOSYS)),
};
res.transpose().map(Error::mux)
}
/* Scheme operations */
#[allow(unused_variables)]
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<Option<OpenResult>> {
convert_to_this_scheme_block(self.open(path, flags, ctx.uid, ctx.gid))
}
#[allow(unused_variables)]
fn chmod(&mut self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&mut self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&mut self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
/* Resource operations */
#[allow(unused_variables)]
fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn xdup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<Option<OpenResult>> {
convert_to_this_scheme_block(self.dup(old_id, buf))
}
#[allow(unused_variables)]
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchmod(&mut self, id: usize, mode: u16) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchown(&mut self, id: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fevent(&mut self, id: usize, flags: EventFlags) -> Result<Option<EventFlags>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn flink(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn frename(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fsync(&mut self, id: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn ftruncate(&mut self, id: usize, len: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn futimens(&mut self, id: usize, times: &[TimeSpec]) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn close(&mut self, id: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<Option<usize>> {
Err(Error::new(EOPNOTSUPP))
}
#[allow(unused_variables)]
fn munmap(&mut self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result<Option<usize>> {
Err(Error::new(EOPNOTSUPP))
}
}

View File

@@ -0,0 +1,248 @@
use core::{mem, slice};
use crate::{data::*, error::*, flag::*, number::*, scheme::*, CallerCtx, OpenResult};
pub trait SchemeMut {
fn handle(&mut self, packet: &mut Packet) {
let res = match packet.a {
SYS_OPEN => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
convert_in_scheme_handle(
packet,
self.xopen(path, packet.d, &CallerCtx::from_packet(&packet)),
)
} else {
Err(Error::new(EINVAL))
}
}
SYS_RMDIR => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_UNLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_DUP => convert_in_scheme_handle(
packet,
self.xdup(
packet.b,
unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) },
&CallerCtx::from_packet(&packet),
),
),
SYS_READ => self.read(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_WRITE => self.write(packet.b, unsafe {
slice::from_raw_parts(packet.c as *const u8, packet.d)
}),
SYS_LSEEK => self
.seek(packet.b, packet.c as isize, packet.d)
.map(|o| o as usize),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self
.fevent(packet.b, EventFlags::from_bits_truncate(packet.c))
.map(|f| f.bits()),
SYS_FLINK => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.flink(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FPATH => self.fpath(packet.b, unsafe {
slice::from_raw_parts_mut(packet.c as *mut u8, packet.d)
}),
SYS_FRENAME => {
if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
}
}
SYS_FSTAT => {
if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSTATVFS => {
if packet.d >= mem::size_of::<StatVfs>() {
self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) })
} else {
Err(Error::new(EFAULT))
}
}
SYS_FSYNC => self.fsync(packet.b),
SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c),
SYS_FUTIMENS => {
if packet.d >= mem::size_of::<TimeSpec>() {
self.futimens(packet.b, unsafe {
slice::from_raw_parts(
packet.c as *const TimeSpec,
packet.d / mem::size_of::<TimeSpec>(),
)
})
} else {
Err(Error::new(EFAULT))
}
}
SYS_CLOSE => self.close(packet.b),
KSMSG_MMAP_PREP => self.mmap_prep(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MapFlags::from_bits_truncate(packet.d),
),
KSMSG_MUNMAP => self.munmap(
packet.b,
u64::from(packet.uid) | (u64::from(packet.gid) << 32),
packet.c,
MunmapFlags::from_bits_truncate(packet.d),
),
_ => Err(Error::new(ENOSYS)),
};
packet.a = Error::mux(res);
}
/* Scheme operations */
#[allow(unused_variables)]
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
convert_to_this_scheme(self.open(path, flags, ctx.uid, ctx.gid))
}
#[allow(unused_variables)]
fn chmod(&mut self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&mut self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&mut self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
/* Resource operations */
#[allow(unused_variables)]
fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn xdup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
convert_to_this_scheme(self.dup(old_id, buf))
}
#[allow(unused_variables)]
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<isize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchmod(&mut self, id: usize, mode: u16) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fchown(&mut self, id: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fevent(&mut self, id: usize, flags: EventFlags) -> Result<EventFlags> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn flink(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn frename(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fsync(&mut self, id: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn futimens(&mut self, id: usize, times: &[TimeSpec]) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn close(&mut self, id: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
#[allow(unused_variables)]
fn munmap(&mut self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
}

41
vendor/redox_syscall/src/scheme/seek.rs vendored Normal file
View File

@@ -0,0 +1,41 @@
use crate::{error::*, flag::*};
use core::{cmp, convert::TryFrom};
/// Helper for seek calls
/// In most cases it's easier to use a usize to track the offset and buffer size internally,
/// but the seek interface uses isize. This wrapper ensures EOVERFLOW errors are returned
/// as appropriate if the value in the usize can't fit in the isize.
pub fn calc_seek_offset_usize(
cur_offset: usize,
pos: isize,
whence: usize,
buf_len: usize,
) -> Result<isize> {
let cur_offset = isize::try_from(cur_offset).or_else(|_| Err(Error::new(EOVERFLOW)))?;
let buf_len = isize::try_from(buf_len).or_else(|_| Err(Error::new(EOVERFLOW)))?;
calc_seek_offset_isize(cur_offset, pos, whence, buf_len)
}
/// Helper for seek calls
/// Result is guaranteed to be positive.
/// EOVERFLOW returned if the arguments would cause an overflow.
/// EINVAL returned if the new offset is out of bounds.
pub fn calc_seek_offset_isize(
cur_offset: isize,
pos: isize,
whence: usize,
buf_len: isize,
) -> Result<isize> {
let new_offset = match whence {
SEEK_CUR => pos.checked_add(cur_offset),
SEEK_END => pos.checked_add(buf_len),
SEEK_SET => Some(pos),
_ => None,
};
match new_offset {
Some(new_offset) if new_offset < 0 => Err(Error::new(EINVAL)),
Some(new_offset) => Ok(cmp::min(new_offset, buf_len)),
None => Err(Error::new(EOVERFLOW)),
}
}

187
vendor/redox_syscall/src/schemev2.rs vendored Normal file
View File

@@ -0,0 +1,187 @@
use core::{
mem,
ops::{Deref, DerefMut},
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::<Sqe>()) }
}
}
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::<Sqe>()) }
}
}
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 2: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::<Cqe>()) }
}
}
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::<Cqe>()) }
}
}
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,
RespondWithMultipleFds,
// TODO: ProvideMmap
}
impl CqeOpcode {
pub fn try_from_raw(raw: u8) -> Option<Self> {
Some(match raw {
0 => Self::RespondRegular,
1 => Self::RespondWithFd,
2 => Self::SendFevent,
3 => Self::ObtainFd,
4 => Self::RespondWithMultipleFds,
_ => 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
Getdents = 26,
CloseMsg = 27,
Call = 28,
OpenAt = 29, // fd, buf_ptr, buf_len, flags
Flink = 30,
Recvfd = 31,
}
impl Opcode {
pub fn try_from_raw(raw: u8) -> Option<Self> {
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,
26 => Getdents,
27 => CloseMsg,
28 => Call,
29 => OpenAt,
30 => Flink,
31 => Recvfd,
_ => return None,
})
}
}

331
vendor/redox_syscall/src/sigabi.rs vendored Normal file
View File

@@ -0,0 +1,331 @@
use core::sync::atomic::{AtomicUsize, Ordering};
/// Signal runtime struct for the entire process
#[derive(Debug)]
#[repr(C, align(4096))]
pub struct SigProcControl {
pub pending: AtomicU64,
pub actions: [RawAction; 64],
pub sender_infos: [AtomicU64; 32],
//pub queue: [RealtimeSig; 32], TODO
// qhead, qtail TODO
}
/*#[derive(Debug)]
#[repr(transparent)]
pub struct RealtimeSig {
pub arg: NonatomicUsize,
}*/
#[derive(Debug, Default)]
#[repr(C, align(16))]
pub struct RawAction {
/// Only two MSBs are interesting for the kernel. If bit 63 is set, signal is ignored. If bit
/// 62 is set and the signal is SIGTSTP/SIGTTIN/SIGTTOU, it's equivalent to the action of
/// Stop.
pub first: AtomicU64,
/// Completely ignored by the kernel, but exists so userspace can (when 16-byte atomics exist)
/// atomically set both the handler, sigaction flags, and sigaction mask.
pub user_data: AtomicU64,
}
/// Signal runtime struct for a thread
#[derive(Debug, Default)]
#[repr(C)]
pub struct Sigcontrol {
// composed of [lo "pending" | lo "unmasked", hi "pending" | hi "unmasked"]
pub word: [AtomicU64; 2],
// lo = sender pid, hi = sender ruid
pub sender_infos: [AtomicU64; 32],
pub control_flags: SigatomicUsize,
pub saved_ip: NonatomicUsize, // rip/eip/pc
pub saved_archdep_reg: NonatomicUsize, // rflags(x64)/eflags(x86)/x0(aarch64)/t0(riscv64)
}
#[derive(Clone, Copy, Debug)]
pub struct SenderInfo {
pub pid: u32,
pub ruid: u32,
}
impl SenderInfo {
#[inline]
pub fn raw(self) -> u64 {
u64::from(self.pid) | (u64::from(self.ruid) << 32)
}
#[inline]
pub const fn from_raw(raw: u64) -> Self {
Self {
pid: raw as u32,
ruid: (raw >> 32) as u32,
}
}
}
impl Sigcontrol {
pub fn currently_pending_unblocked(&self, proc: &SigProcControl) -> u64 {
let proc_pending = proc.pending.load(Ordering::Relaxed);
let [w0, w1] = core::array::from_fn(|i| {
let w = self.word[i].load(Ordering::Relaxed);
((w | (proc_pending >> (i * 32))) & 0xffff_ffff) & (w >> 32)
});
//core::sync::atomic::fence(Ordering::Acquire);
w0 | (w1 << 32)
}
pub fn set_allowset(&self, new_allowset: u64) -> u64 {
//core::sync::atomic::fence(Ordering::Release);
let [w0, w1] = self.word.each_ref().map(|w| w.load(Ordering::Relaxed));
let old_a0 = w0 & 0xffff_ffff_0000_0000;
let old_a1 = w1 & 0xffff_ffff_0000_0000;
let new_a0 = (new_allowset & 0xffff_ffff) << 32;
let new_a1 = new_allowset & 0xffff_ffff_0000_0000;
let prev_w0 = self.word[0].fetch_add(new_a0.wrapping_sub(old_a0), Ordering::Relaxed);
let prev_w1 = self.word[0].fetch_add(new_a1.wrapping_sub(old_a1), Ordering::Relaxed);
//core::sync::atomic::fence(Ordering::Acquire);
let up0 = prev_w0 & (prev_w0 >> 32);
let up1 = prev_w1 & (prev_w1 >> 32);
up0 | (up1 << 32)
}
}
#[derive(Debug, Default)]
#[repr(transparent)]
pub struct SigatomicUsize(AtomicUsize);
impl SigatomicUsize {
#[inline]
pub fn load(&self, ordering: Ordering) -> usize {
let value = self.0.load(Ordering::Relaxed);
if ordering != Ordering::Relaxed {
core::sync::atomic::compiler_fence(ordering);
}
value
}
#[inline]
pub fn store(&self, value: usize, ordering: Ordering) {
if ordering != Ordering::Relaxed {
core::sync::atomic::compiler_fence(ordering);
}
self.0.store(value, Ordering::Relaxed);
}
}
#[derive(Debug, Default)]
#[repr(transparent)]
pub struct NonatomicUsize(AtomicUsize);
impl NonatomicUsize {
#[inline]
pub const fn new(a: usize) -> Self {
Self(AtomicUsize::new(a))
}
#[inline]
pub fn get(&self) -> usize {
self.0.load(Ordering::Relaxed)
}
#[inline]
pub fn set(&self, value: usize) {
self.0.store(value, Ordering::Relaxed);
}
}
pub fn sig_bit(sig: usize) -> u64 {
1 << (sig - 1)
}
impl SigProcControl {
// TODO: Move to redox_rt?
pub fn signal_will_ign(&self, sig: usize, is_parent_sigchld: bool) -> bool {
let flags = self.actions[sig - 1].first.load(Ordering::Relaxed);
let will_ign = flags & (1 << 63) != 0;
let sig_specific = flags & (1 << 62) != 0; // SA_NOCLDSTOP if sig == SIGCHLD
will_ign || (sig == SIGCHLD && is_parent_sigchld && sig_specific)
}
// TODO: Move to redox_rt?
pub fn signal_will_stop(&self, sig: usize) -> bool {
use crate::flag::*;
matches!(sig, SIGTSTP | SIGTTIN | SIGTTOU)
&& self.actions[sig - 1].first.load(Ordering::Relaxed) & (1 << 62) != 0
}
}
#[cfg(not(target_arch = "x86"))]
pub use core::sync::atomic::AtomicU64;
use crate::SIGCHLD;
#[cfg(target_arch = "x86")]
pub use self::atomic::AtomicU64;
#[cfg(target_arch = "x86")]
mod atomic {
use core::{cell::UnsafeCell, sync::atomic::Ordering};
#[derive(Debug, Default)]
pub struct AtomicU64(UnsafeCell<u64>);
unsafe impl Send for AtomicU64 {}
unsafe impl Sync for AtomicU64 {}
impl AtomicU64 {
pub const fn new(inner: u64) -> Self {
Self(UnsafeCell::new(inner))
}
pub fn compare_exchange(
&self,
old: u64,
new: u64,
_success: Ordering,
_failure: Ordering,
) -> Result<u64, u64> {
let old_hi = (old >> 32) as u32;
let old_lo = old as u32;
let new_hi = (new >> 32) as u32;
let new_lo = new as u32;
let mut out_hi;
let mut out_lo;
unsafe {
core::arch::asm!("lock cmpxchg8b [{}]", in(reg) self.0.get(), inout("edx") old_hi => out_hi, inout("eax") old_lo => out_lo, in("ecx") new_hi, in("ebx") new_lo);
}
if old_hi == out_hi && old_lo == out_lo {
Ok(old)
} else {
Err(u64::from(out_lo) | (u64::from(out_hi) << 32))
}
}
pub fn load(&self, ordering: Ordering) -> u64 {
match self.compare_exchange(0, 0, ordering, ordering) {
Ok(new) => new,
Err(new) => new,
}
}
pub fn store(&self, new: u64, ordering: Ordering) {
let mut old = 0;
loop {
match self.compare_exchange(old, new, ordering, Ordering::Relaxed) {
Ok(_) => break,
Err(new) => {
old = new;
core::hint::spin_loop();
}
}
}
}
pub fn fetch_update(
&self,
set_order: Ordering,
fetch_order: Ordering,
mut f: impl FnMut(u64) -> Option<u64>,
) -> Result<u64, u64> {
let mut old = self.load(fetch_order);
loop {
let new = f(old).ok_or(old)?;
match self.compare_exchange(old, new, set_order, Ordering::Relaxed) {
Ok(_) => return Ok(new),
Err(changed) => {
old = changed;
core::hint::spin_loop();
}
}
}
}
pub fn fetch_or(&self, bits: u64, order: Ordering) -> u64 {
self.fetch_update(order, Ordering::Relaxed, |b| Some(b | bits))
.unwrap()
}
pub fn fetch_and(&self, bits: u64, order: Ordering) -> u64 {
self.fetch_update(order, Ordering::Relaxed, |b| Some(b & bits))
.unwrap()
}
pub fn fetch_add(&self, term: u64, order: Ordering) -> u64 {
self.fetch_update(order, Ordering::Relaxed, |b| Some(b.wrapping_add(term)))
.unwrap()
}
}
}
#[cfg(test)]
mod tests {
use std::sync::{
atomic::{AtomicU64, Ordering},
Arc,
};
#[cfg(not(loom))]
use std::{sync::Mutex, thread};
#[cfg(not(loom))]
fn model(f: impl FnOnce()) {
f()
}
#[cfg(loom)]
use loom::{model, sync::Mutex, thread};
use crate::{RawAction, SigProcControl, Sigcontrol};
struct FakeThread {
ctl: Sigcontrol,
pctl: SigProcControl,
ctxt: Mutex<()>,
}
impl Default for FakeThread {
fn default() -> Self {
Self {
ctl: Sigcontrol::default(),
pctl: SigProcControl {
pending: AtomicU64::new(0),
actions: core::array::from_fn(|_| RawAction::default()),
sender_infos: Default::default(),
},
ctxt: Default::default(),
}
}
}
#[test]
fn singlethread_mask() {
model(|| {
let fake_thread = Arc::new(FakeThread::default());
let thread = {
let fake_thread = Arc::clone(&fake_thread);
thread::spawn(move || {
fake_thread.ctl.set_allowset(!0);
{
let _g = fake_thread.ctxt.lock();
if fake_thread
.ctl
.currently_pending_unblocked(&fake_thread.pctl)
== 0
{
drop(_g);
thread::park();
}
}
})
};
for sig in 1..=64 {
let _g = fake_thread.ctxt.lock();
let idx = sig - 1;
let bit = 1 << (idx % 32);
fake_thread.ctl.word[idx / 32].fetch_or(bit, Ordering::Relaxed);
let w = fake_thread.ctl.word[idx / 32].load(Ordering::Relaxed);
if w & (w >> 32) != 0 {
thread.thread().unpark();
}
}
thread.join().unwrap();
});
}
}