Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

View File

@ -0,0 +1 @@
{"files":{"Cargo.toml":"91d2cdde6f3eaad21dc8f0d8879b0572d92b0eca34fd2dcac26ccc00c50b6839","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"9b4cf7da1f001ce54bfd01b7a001dbc8043c1ef89823781a2a1070e2c096a9ce","src/arch/nonredox.rs":"1055cd441f4b95c9ec428222a7796c7fac953a8a500ca08173743ea95220aab3","src/arch/riscv64.rs":"20bf9a8db779059773b113643d0cb3737fbb5d57f45ee39b8ae9d3396b6ef636","src/arch/x86.rs":"cf01f4d798e8861ad5b9429714c947e2d7c53a3cb9a13d53dc7a38e4bdad4101","src/arch/x86_64.rs":"fd80c9a412d07c85f2b942f36de364edfff7cd49f6c00c043e69becb7c76119f","src/call.rs":"1630ef687b0de538e19e7408d79c55177e61a7a7c8a2693da9bd01e5358a9a8e","src/data.rs":"cff635f60875977935e1b243aff638ef2193aa05a73fc1399964e55225eb3934","src/error.rs":"c8cacebca86e388e2ef12ac504818d7c1bc16df5d89fcabc1dfc9839e7c3aecf","src/flag.rs":"0505c4ed82970109d83ef01100c40d0fee344919d10f5a78957fc20706f8e228","src/io/dma.rs":"85577342547afaac0dc46740dfeb9d2e4239d8809b86748c3fcaa12f922b1c9d","src/io/io.rs":"e1d454ff47efac70fdaa709251a5a9c1c5637f931994ba3bf6a38c6db9145822","src/io/mmio.rs":"ab64f0bee9d13ebcfc21d0125f6c973f460f582cbc3d566d00491fe1ac714127","src/io/mod.rs":"79c2fce4fd6d75f3b9169df64b7a605feff31fab2e5ed81984ae085a1d07c0c4","src/io/pio.rs":"9ee6f2229b700d1c45b4c8c6242bd99fe69634e16dcd5843d9e8d1c958047406","src/lib.rs":"25c9f35cf709e7e50336ae12f0390f968cc11515f93b6d757825a7b7725eeadb","src/number.rs":"c0463c7f8eb3f3d16062efb0e65472b22f81821329af2ed8271fdddfa70f3e8b","src/scheme/generate.sh":"2eed5d6a382cd3daa31ccaa7c80b1995258f9126462228191b41f32e7af958a2","src/scheme/mod.rs":"acdd7526d6477288c47efc2a4c310d9a9fef8795cad4358c54aba0763ae2fcd2","src/scheme/scheme.rs":"860526f02cb8cab0d1a996079c9ef5d9440b45796429c4376e00d253b4d3ba51","src/scheme/scheme_block.rs":"6afebd8f3d6dd2716236e63bfd3943f5d6725e29aac392ce0e21101fd4578a82","src/scheme/scheme_block_mut.rs":"ed2d27e7519f437a42d32cbd80e33c4b9446cd90d3e6dbd82e3509a41e92acb7","src/scheme/scheme_mut.rs":"1d2e2ad31da6622ef80493c3670909fe8179306081bbc7f450b24528e6ef23d8","src/scheme/seek.rs":"94e044de47b0f00eb0c2aea3fb21001ac2b9aa1e4b20d73fd54163fe92fa63f7","src/tests.rs":"0fb2355fe625188a348fbae8c23fa622d4a08c6378a56ff40d3ef54ed78884b9"},"package":"4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"}

38
vendor/redox_syscall/Cargo.toml vendored Normal file
View File

@ -0,0 +1,38 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "redox_syscall"
version = "0.4.1"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
description = "A Rust library to access raw Redox system calls"
documentation = "https://docs.rs/redox_syscall"
readme = "README.md"
license = "MIT"
repository = "https://gitlab.redox-os.org/redox-os/syscall"
[lib]
name = "syscall"
[dependencies.bitflags]
version = "1.1.0"
[dependencies.core]
version = "1.0.0"
optional = true
package = "rustc-std-workspace-core"
[features]
rustc-dep-of-std = [
"core",
"bitflags/rustc-dep-of-std",
]

22
vendor/redox_syscall/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2017 Redox OS Developers
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

6
vendor/redox_syscall/README.md vendored Normal file
View File

@ -0,0 +1,6 @@
# syscall
[Redox OS](https://gitlab.redox-os.org/redox-os/redox)'s syscall API
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![crates.io](http://meritbadge.herokuapp.com/redox_syscall)](https://crates.io/crates/redox_syscall)
[![docs.rs](https://docs.rs/redox_syscall/badge.svg)](https://docs.rs/redox_syscall)

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

@ -0,0 +1,150 @@
use core::{mem, slice};
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
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)
}
)+
};
}
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(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(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>())
}
}
}

View File

@ -0,0 +1,29 @@
use super::error::{Error, Result, ENOSYS};
// Doesn't really matter, but since we will most likely run on an x86_64 host, why not 4096?
pub const PAGE_SIZE: usize = 4096;
pub unsafe fn syscall0(_a: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall1(_a: usize, _b: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall2(_a: usize, _b: usize, _c: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall3(_a: usize, _b: usize, _c: usize, _d: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall4(_a: usize, _b: usize, _c: usize, _d: usize, _e: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall5(_a: usize, _b: usize, _c: usize, _d: usize, _e: usize, _f: usize)
-> Result<usize> {
Err(Error::new(ENOSYS))
}

View File

@ -0,0 +1,93 @@
use core::{mem, slice};
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
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)
}
)+
};
}
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 {
//TODO
}
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(packed)]
pub struct FloatRegisters {
//TODO
}
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>())
}
}
}

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

@ -0,0 +1,184 @@
use core::{mem, slice};
use core::arch::asm;
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
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)
}
)+
};
}
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,);
}
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)
}
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(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(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>())
}
}
}

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

@ -0,0 +1,157 @@
use core::{mem, slice};
use core::arch::asm;
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
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!(
"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),
);
Error::demux($a)
}
)+
};
}
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 {
// TODO: Some of these don't get set by Redox yet. Should they?
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 orig_rax: usize,
pub rip: usize,
pub cs: usize,
pub rflags: usize,
pub rsp: 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(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(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>())
}
}
}

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

@ -0,0 +1,364 @@
use super::arch::*;
use super::data::{Map, SigAction, Stat, StatVfs, TimeSpec};
use super::error::Result;
use super::flag::*;
use super::number::*;
use core::{mem, ptr};
// Signal restorer
extern "C" fn restorer() -> ! {
sigreturn().unwrap();
unreachable!();
}
/// 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()) }
}
/// Exit the current process
pub fn exit(status: usize) -> Result<usize> {
unsafe { syscall1(SYS_EXIT, status) }
}
/// 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()) }
}
/// Rename a file
pub fn frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().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)
}
/// Get the effective group ID
pub fn getegid() -> Result<usize> {
unsafe { syscall0(SYS_GETEGID) }
}
/// Get the effective namespace
pub fn getens() -> Result<usize> {
unsafe { syscall0(SYS_GETENS) }
}
/// Get the effective user ID
pub fn geteuid() -> Result<usize> {
unsafe { syscall0(SYS_GETEUID) }
}
/// Get the current group ID
pub fn getgid() -> Result<usize> {
unsafe { syscall0(SYS_GETGID) }
}
/// Get the current namespace
pub fn getns() -> Result<usize> {
unsafe { syscall0(SYS_GETNS) }
}
/// Get the current process ID
pub fn getpid() -> Result<usize> {
unsafe { syscall0(SYS_GETPID) }
}
/// Get the process group ID
pub fn getpgid(pid: usize) -> Result<usize> {
unsafe { syscall1(SYS_GETPGID, pid) }
}
/// Get the parent process ID
pub fn getppid() -> Result<usize> {
unsafe { syscall0(SYS_GETPPID) }
}
/// Get the current user ID
pub fn getuid() -> Result<usize> {
unsafe { syscall0(SYS_GETUID) }
}
/// Set the I/O privilege level
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `EINVAL` - `level > 3`
pub unsafe fn iopl(level: usize) -> Result<usize> {
syscall1(SYS_IOPL, level)
}
/// Send a signal `sig` to the process identified by `pid`
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
unsafe { syscall2(SYS_KILL, pid, sig) }
}
/// Create a link to a file
pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
syscall2(SYS_LINK, old as usize, new 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> {
unsafe { syscall3(SYS_OPEN, path.as_ref().as_ptr() as usize, path.as_ref().len(), flags) }
}
/// Allocate frames, linearly in physical memory.
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
pub unsafe fn physalloc(size: usize) -> Result<usize> {
syscall1(SYS_PHYSALLOC, size)
}
/// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
/// [`PARTIAL_ALLOC`], this will result in `physalloc3` with `min = 1`.
///
/// Refer to the simpler [`physalloc`] and the more complex [`physalloc3`], that this convenience
/// function is based on.
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
pub unsafe fn physalloc2(size: usize, flags: usize) -> Result<usize> {
let mut ret = 1usize;
physalloc3(size, flags, &mut ret)
}
/// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
/// [`PARTIAL_ALLOC`], the `min` parameter specifies the number of frames that have to be allocated
/// for this operation to succeed. The return value is the offset of the first frame, and `min` is
/// overwritten with the number of frames actually allocated.
///
/// Refer to the simpler [`physalloc`] and the simpler library function [`physalloc2`].
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
/// * `EINVAL` - `min = 0`
pub unsafe fn physalloc3(size: usize, flags: usize, min: &mut usize) -> Result<usize> {
syscall3(SYS_PHYSALLOC3, size, flags, min as *mut usize as usize)
}
/// Free physically allocated pages
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
syscall2(SYS_PHYSFREE, physical_address, size)
}
/// Map physical memory to virtual memory
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
pub unsafe fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
syscall3(SYS_PHYSMAP, physical_address, size, flags.bits())
}
/// 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> {
unsafe { syscall2(SYS_RMDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
/// Set the process group ID
pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
unsafe { syscall2(SYS_SETPGID, pid, pgid) }
}
/// Set the current process group IDs
pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
unsafe { syscall2(SYS_SETREGID, rgid, egid) }
}
/// Make a new scheme namespace
pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
unsafe { syscall2(SYS_SETRENS, rns, ens) }
}
/// Set the current process user IDs
pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
unsafe { syscall2(SYS_SETREUID, ruid, euid) }
}
/// Set up a signal handler
pub fn sigaction(sig: usize, act: Option<&SigAction>, oldact: Option<&mut SigAction>) -> Result<usize> {
unsafe { syscall4(SYS_SIGACTION, sig,
act.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
oldact.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize,
restorer as usize) }
}
/// Get and/or set signal masks
pub fn sigprocmask(how: usize, set: Option<&[u64; 2]>, oldset: Option<&mut [u64; 2]>) -> Result<usize> {
unsafe { syscall3(SYS_SIGPROCMASK, how,
set.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
oldset.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize) }
}
// Return from signal handler
pub fn sigreturn() -> Result<usize> {
unsafe { syscall0(SYS_SIGRETURN) }
}
/// Set the file mode creation mask
pub fn umask(mask: usize) -> Result<usize> {
unsafe { syscall1(SYS_UMASK, mask) }
}
/// Remove a file
pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
unsafe { syscall2(SYS_UNLINK, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
/// Convert a virtual address to a physical one
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
syscall1(SYS_VIRTTOPHYS, virtual_address)
}
/// Check if a child process has exited or received a signal
pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize> {
unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options.bits()) }
}
/// 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) }
}

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

@ -0,0 +1,356 @@
use core::ops::{Deref, DerefMut};
use core::{mem, slice};
use crate::flag::{EventFlags, MapFlags, PtraceFlags, SigActionFlags};
#[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 SigAction {
pub sa_handler: Option<extern "C" fn(usize)>,
pub sa_mask: [u64; 2],
pub sa_flags: SigActionFlags,
}
impl Deref for SigAction {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const SigAction as *const u8,
mem::size_of::<SigAction>())
}
}
}
impl DerefMut for SigAction {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut SigAction as *mut u8,
mem::size_of::<SigAction>())
}
}
}
#[allow(dead_code)]
unsafe fn _assert_size_of_function_is_sane() {
// Transmuting will complain *at compile time* if sizes differ.
// Rust forbids a fn-pointer from being 0 so to allow SIG_DFL to
// exist, we use Option<extern "C" fn(usize)> which will mean 0
// becomes None
let _ = mem::transmute::<Option<extern "C" fn(usize)>, usize>(None);
}
#[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(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;
}
}
#[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>())
}
}
}

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

@ -0,0 +1,313 @@
use core::{fmt, result};
#[derive(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: 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())
}
}
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"];

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

@ -0,0 +1,374 @@
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(Default)]
$(#[$outer])*
pub struct $BitFlags: $T {
$(
$(#[$inner $($args)*])*
const $Flag = $value;
)+
}
}
// 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;
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_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;
bitflags! {
pub struct PhysmapFlags: usize {
const PHYSMAP_WRITE = 0x0000_0001;
const PHYSMAP_WRITE_COMBINE = 0x0000_0002;
const PHYSMAP_NO_CACHE = 0x0000_0004;
}
}
bitflags! {
/// Extra flags for [`physalloc2`] or [`physalloc3`].
///
/// [`physalloc2`]: ../call/fn.physalloc2.html
/// [`physalloc3`]: ../call/fn.physalloc3.html
pub struct PhysallocFlags: usize {
/// Only allocate memory within the 32-bit physical memory space. This is necessary for
/// some devices may not support 64-bit memory.
const SPACE_32 = 0x0000_0001;
/// The frame that will be allocated, is going to reside anywhere in 64-bit space. This
/// flag is redundant for the most part, except when overriding some other default.
const SPACE_64 = 0x0000_0002;
/// Do a "partial allocation", which means that not all of the frames specified in the
/// frame count `size` actually have to be allocated. This means that if the allocator was
/// unable to find a physical memory range large enough, it can instead return whatever
/// range it decides is optimal. Thus, instead of letting one driver get an expensive
/// 128MiB physical memory range when the physical memory has become fragmented, and
/// failing, it can instead be given a more optimal range. If the device supports
/// scatter-gather lists, then the driver only has to allocate more ranges, and the device
/// will do vectored I/O.
///
/// PARTIAL_ALLOC supports different allocation strategies, refer to
/// [`Optimal`], [`GreatestRange`].
///
/// [`Optimal`]: ./enum.PartialAllocStrategy.html
/// [`GreatestRange`]: ./enum.PartialAllocStrategy.html
const PARTIAL_ALLOC = 0x0000_0004;
}
}
/// The bitmask of the partial allocation strategy. Currently four different strategies are
/// supported. If [`PARTIAL_ALLOC`] is not set, this bitmask is no longer reserved.
pub const PARTIAL_ALLOC_STRATEGY_MASK: usize = 0x0003_0000;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(usize)]
pub enum PartialAllocStrategy {
/// The allocator decides itself the size of the memory range, based on e.g. free memory ranges
/// and other processes which require large physical memory chunks.
Optimal = 0x0001_0000,
/// The allocator returns the absolute greatest range it can find.
GreatestRange = 0x0002_0000,
/// The allocator returns the first range that fits the minimum count, without searching extra.
Greedy = 0x0003_0000,
}
impl Default for PartialAllocStrategy {
fn default() -> Self {
Self::Optimal
}
}
impl PartialAllocStrategy {
pub fn from_raw(raw: usize) -> Option<Self> {
match raw {
0x0001_0000 => Some(Self::Optimal),
0x0002_0000 => Some(Self::GreatestRange),
0x0003_0000 => Some(Self::Greedy),
_ => None,
}
}
}
// The top 48 bits of PTRACE_* are reserved, for now
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 SIGHUP: usize = 1;
pub const SIGINT: usize = 2;
pub const SIGQUIT: usize = 3;
pub const SIGILL: usize = 4;
pub const SIGTRAP: usize = 5;
pub const SIGABRT: usize = 6;
pub const SIGBUS: usize = 7;
pub const SIGFPE: usize = 8;
pub const SIGKILL: usize = 9;
pub const SIGUSR1: usize = 10;
pub const SIGSEGV: usize = 11;
pub const SIGUSR2: usize = 12;
pub const SIGPIPE: usize = 13;
pub const SIGALRM: usize = 14;
pub const SIGTERM: usize = 15;
pub const SIGSTKFLT: usize= 16;
pub const SIGCHLD: usize = 17;
pub const SIGCONT: usize = 18;
pub const SIGSTOP: usize = 19;
pub const SIGTSTP: usize = 20;
pub const SIGTTIN: usize = 21;
pub const SIGTTOU: usize = 22;
pub const SIGURG: usize = 23;
pub const SIGXCPU: usize = 24;
pub const SIGXFSZ: usize = 25;
pub const SIGVTALRM: usize= 26;
pub const SIGPROF: usize = 27;
pub const SIGWINCH: usize = 28;
pub const SIGIO: usize = 29;
pub const SIGPWR: usize = 30;
pub const SIGSYS: usize = 31;
pub const SIG_DFL: usize = 0;
pub const SIG_IGN: usize = 1;
pub const SIG_BLOCK: usize = 0;
pub const SIG_UNBLOCK: usize = 1;
pub const SIG_SETMASK: usize = 2;
bitflags! {
pub struct SigActionFlags: usize {
const SA_NOCLDSTOP = 0x00000001;
const SA_NOCLDWAIT = 0x00000002;
const SA_SIGINFO = 0x00000004;
const SA_RESTORER = 0x04000000;
const SA_ONSTACK = 0x08000000;
const SA_RESTART = 0x10000000;
const SA_NODEFER = 0x40000000;
const SA_RESETHAND = 0x80000000;
}
}
bitflags! {
pub struct WaitFlags: usize {
const WNOHANG = 0x01;
const WUNTRACED = 0x02;
const WCONTINUED = 0x08;
}
}
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;
/// True if status indicates the child is stopped.
pub fn wifstopped(status: usize) -> bool {
(status & 0xff) == 0x7f
}
/// If wifstopped(status), the signal that stopped the child.
pub fn wstopsig(status: usize) -> usize {
(status >> 8) & 0xff
}
/// True if status indicates the child continued after a stop.
pub fn wifcontinued(status: usize) -> bool {
status == 0xffff
}
/// True if STATUS indicates termination by a signal.
pub fn wifsignaled(status: usize) -> bool {
((status & 0x7f) + 1) as i8 >= 2
}
/// If wifsignaled(status), the terminating signal.
pub fn wtermsig(status: usize) -> usize {
status & 0x7f
}
/// True if status indicates normal termination.
pub fn wifexited(status: usize) -> bool {
wtermsig(status) == 0
}
/// If wifexited(status), the exit status.
pub fn wexitstatus(status: usize) -> usize {
(status >> 8) & 0xff
}
/// True if status indicates a core dump was created.
pub fn wcoredump(status: usize) -> bool {
(status & 0x80) != 0
}
bitflags! {
pub struct MremapFlags: usize {
const FIXED = 1;
const FIXED_REPLACE = 3;
// TODO: MAYMOVE, DONTUNMAP
}
}

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

@ -0,0 +1,219 @@
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::{ptr, slice};
use crate::Result;
use crate::{PartialAllocStrategy, PhysallocFlags, PhysmapFlags};
use crate::arch::PAGE_SIZE;
/// An RAII guard of a physical memory allocation. Currently all physically allocated memory are
/// page-aligned and take up at least 4k of space (on x86_64).
#[derive(Debug)]
pub struct PhysBox {
address: usize,
size: usize
}
const fn round_up(x: usize) -> usize {
(x + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE
}
fn assert_aligned(x: usize) {
assert_eq!(x % PAGE_SIZE, 0);
}
#[cfg(target_arch = "aarch64")]
fn physmap_flags() -> PhysmapFlags {
// aarch64 currently must map DMA memory without caching to ensure coherence
crate::PHYSMAP_NO_CACHE | crate::PHYSMAP_WRITE
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn physmap_flags() -> PhysmapFlags {
// x86 ensures cache coherence with DMA memory
crate::PHYSMAP_WRITE
}
impl PhysBox {
/// Construct a PhysBox from an address and a size. The address must be page-aligned, and the
/// size must similarly be a multiple of the page size.
///
/// # Safety
/// This function is unsafe because when dropping, Self has to a valid allocation.
pub unsafe fn from_raw_parts(address: usize, size: usize) -> Self {
assert_aligned(address);
assert_aligned(size);
Self {
address,
size,
}
}
/// Retrieve the byte address in physical memory, of this allocation.
pub fn address(&self) -> usize {
self.address
}
/// Retrieve the size in bytes of the alloc.
pub fn size(&self) -> usize {
self.size
}
/// Allocate physical memory that must reside in 32-bit space.
pub fn new_in_32bit_space(size: usize) -> Result<Self> {
Self::new_with_flags(size, PhysallocFlags::SPACE_32)
}
pub fn new_with_flags(size: usize, flags: PhysallocFlags) -> Result<Self> {
assert!(!flags.contains(PhysallocFlags::PARTIAL_ALLOC));
assert_aligned(size);
let address = unsafe { crate::physalloc2(size, flags.bits())? };
Ok(unsafe { Self::from_raw_parts(address, size) })
}
/// "Partially" allocate physical memory, in the sense that the allocation may be smaller than
/// expected, but still with a minimum limit. This is particularly useful when the physical
/// memory space is fragmented, and a device supports scatter-gather I/O. In that case, the
/// driver can optimistically request e.g. 1 alloc of 1 MiB, with the minimum of 512 KiB. If
/// that first allocation only returns half the size, the driver can do another allocation
/// and then let the device use both buffers.
pub fn new_partial_allocation(size: usize, flags: PhysallocFlags, strategy: Option<PartialAllocStrategy>, mut min: usize) -> Result<Self> {
assert_aligned(size);
debug_assert!(!(flags.contains(PhysallocFlags::PARTIAL_ALLOC) && strategy.is_none()));
let address = unsafe { crate::physalloc3(size, flags.bits() | strategy.map_or(0, |s| s as usize), &mut min)? };
Ok(unsafe { Self::from_raw_parts(address, size) })
}
pub fn new(size: usize) -> Result<Self> {
assert_aligned(size);
let address = unsafe { crate::physalloc(size)? };
Ok(unsafe { Self::from_raw_parts(address, size) })
}
}
impl Drop for PhysBox {
fn drop(&mut self) {
let _ = unsafe { crate::physfree(self.address, self.size) };
}
}
pub struct Dma<T: ?Sized> {
phys: PhysBox,
virt: *mut T,
}
impl<T> Dma<T> {
pub fn from_physbox_uninit(phys: PhysBox) -> Result<Dma<MaybeUninit<T>>> {
let virt = unsafe { crate::physmap(phys.address, phys.size, physmap_flags())? } as *mut MaybeUninit<T>;
Ok(Dma {
phys,
virt,
})
}
pub fn from_physbox_zeroed(phys: PhysBox) -> Result<Dma<MaybeUninit<T>>> {
let this = Self::from_physbox_uninit(phys)?;
unsafe { ptr::write_bytes(this.virt as *mut MaybeUninit<u8>, 0, this.phys.size) }
Ok(this)
}
pub fn from_physbox(phys: PhysBox, value: T) -> Result<Self> {
let this = Self::from_physbox_uninit(phys)?;
Ok(unsafe {
ptr::write(this.virt, MaybeUninit::new(value));
this.assume_init()
})
}
pub fn new(value: T) -> Result<Self> {
let phys = PhysBox::new(round_up(mem::size_of::<T>()))?;
Self::from_physbox(phys, value)
}
pub fn zeroed() -> Result<Dma<MaybeUninit<T>>> {
let phys = PhysBox::new(round_up(mem::size_of::<T>()))?;
Self::from_physbox_zeroed(phys)
}
}
impl<T> Dma<MaybeUninit<T>> {
pub unsafe fn assume_init(self) -> Dma<T> {
let &Dma { phys: PhysBox { address, size }, virt } = &self;
mem::forget(self);
Dma {
phys: PhysBox { address, size },
virt: virt as *mut T,
}
}
}
impl<T: ?Sized> Dma<T> {
pub fn physical(&self) -> usize {
self.phys.address()
}
pub fn size(&self) -> usize {
self.phys.size()
}
pub fn phys(&self) -> &PhysBox {
&self.phys
}
}
impl<T> Dma<[T]> {
pub fn from_physbox_uninit_unsized(phys: PhysBox, len: usize) -> Result<Dma<[MaybeUninit<T>]>> {
let max_len = phys.size() / mem::size_of::<T>();
assert!(len <= max_len);
Ok(Dma {
virt: unsafe { slice::from_raw_parts_mut(crate::physmap(phys.address, phys.size, physmap_flags())? as *mut MaybeUninit<T>, len) } as *mut [MaybeUninit<T>],
phys,
})
}
pub fn from_physbox_zeroed_unsized(phys: PhysBox, len: usize) -> Result<Dma<[MaybeUninit<T>]>> {
let this = Self::from_physbox_uninit_unsized(phys, len)?;
unsafe { ptr::write_bytes(this.virt as *mut MaybeUninit<u8>, 0, this.phys.size()) }
Ok(this)
}
/// Creates a new DMA buffer with a size only known at runtime.
/// ## Safety
/// * `T` must be properly aligned.
/// * `T` must be valid as zeroed (i.e. no NonNull pointers).
pub unsafe fn zeroed_unsized(count: usize) -> Result<Self> {
let phys = PhysBox::new(round_up(mem::size_of::<T>() * count))?;
Ok(Self::from_physbox_zeroed_unsized(phys, count)?.assume_init())
}
}
impl<T> Dma<[MaybeUninit<T>]> {
pub unsafe fn assume_init(self) -> Dma<[T]> {
let &Dma { phys: PhysBox { address, size }, virt } = &self;
mem::forget(self);
Dma {
phys: PhysBox { address, size },
virt: virt as *mut [T],
}
}
}
impl<T: ?Sized> Deref for Dma<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.virt }
}
}
impl<T: ?Sized> DerefMut for Dma<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.virt }
}
}
impl<T: ?Sized> Drop for Dma<T> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.virt) }
let _ = unsafe { crate::funmap(self.virt as *mut u8 as usize, self.phys.size) };
}
}

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

@ -0,0 +1,71 @@
use core::cmp::PartialEq;
use core::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)
}
}

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

@ -0,0 +1,168 @@
use core::mem::MaybeUninit;
use core::ptr;
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
use core::ops::{BitAnd, BitOr, Not};
use super::io::Io;
#[repr(packed)]
pub struct Mmio<T> {
value: MaybeUninit<T>,
}
impl<T> Mmio<T> {
/// Create a new Mmio without initializing
#[deprecated = "unsound because it's possible to read even though it's uninitialized"]
pub fn new() -> Self {
unsafe { Self::uninit() }
}
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,
);
}
}
}

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

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

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

@ -0,0 +1,90 @@
use core::arch::asm;
use core::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));
}
}
}

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

@ -0,0 +1,61 @@
#![cfg_attr(not(test), no_std)]
#[cfg(test)]
extern crate core;
pub use self::arch::*;
pub use self::call::*;
pub use self::data::*;
pub use self::error::*;
pub use self::flag::*;
pub use self::io::*;
pub use self::number::*;
pub use self::scheme::*;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "arm"))]
#[path="arch/nonredox.rs"]
mod arch;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "aarch64"))]
#[path="arch/aarch64.rs"]
mod arch;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "riscv64"))]
#[path="arch/riscv64.rs"]
mod arch;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "x86"))]
#[path="arch/x86.rs"]
mod arch;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "x86_64"))]
#[path="arch/x86_64.rs"]
mod arch;
#[cfg(not(any(target_os = "none", target_os = "redox")))]
#[path="arch/nonredox.rs"]
mod arch;
/// Function definitions
pub mod call;
/// Complex structures that are used for some system calls
pub mod data;
/// 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;
/// A trait useful for scheme handlers
pub mod scheme;
#[cfg(test)]
mod tests;

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

@ -0,0 +1,89 @@
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_LINK: usize = SYS_CLASS_PATH | SYS_ARG_PATH | 9;
pub const SYS_OPEN: usize = SYS_CLASS_PATH | SYS_RET_FILE | 5;
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_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
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;
// 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_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;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const SYS_EXIT: usize = 1;
pub const SYS_FUTEX: usize = 240;
pub const SYS_GETEGID: usize = 202;
pub const SYS_GETENS: usize = 951;
pub const SYS_GETEUID: usize = 201;
pub const SYS_GETGID: usize = 200;
pub const SYS_GETNS: usize = 950;
pub const SYS_GETPID: usize = 20;
pub const SYS_GETPGID: usize = 132;
pub const SYS_GETPPID: usize = 64;
pub const SYS_GETUID: usize = 199;
pub const SYS_IOPL: usize = 110;
pub const SYS_KILL: usize = 37;
pub const SYS_MPROTECT: usize = 125;
pub const SYS_MKNS: usize = 984;
pub const SYS_NANOSLEEP: usize =162;
pub const SYS_PHYSALLOC: usize =945;
pub const SYS_PHYSALLOC3: usize=9453;
pub const SYS_PHYSFREE: usize = 946;
pub const SYS_PHYSMAP: usize = 947;
pub const SYS_VIRTTOPHYS: usize=949;
pub const SYS_SETPGID: usize = 57;
pub const SYS_SETREGID: usize = 204;
pub const SYS_SETRENS: usize = 952;
pub const SYS_SETREUID: usize = 203;
pub const SYS_SIGACTION: usize =67;
pub const SYS_SIGPROCMASK:usize=126;
pub const SYS_SIGRETURN: usize =119;
pub const SYS_UMASK: usize = 60;
pub const SYS_WAITPID: usize = 7;
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

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

@ -0,0 +1,68 @@
use core::{slice, str};
use crate::{Error, Result, EOPNOTSUPP, ESKMSG, Packet, SKMSG_FRETURNFD};
pub use self::scheme::Scheme;
pub use self::scheme_mut::SchemeMut;
pub use self::scheme_block::SchemeBlock;
pub use self::scheme_block_mut::SchemeBlockMut;
pub use self::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_mut;
mod scheme_block;
mod scheme_block_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,194 @@
use core::{mem, slice};
use crate::CallerCtx;
use crate::OpenResult;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::*;
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_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 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,194 @@
use core::{mem, slice};
use crate::CallerCtx;
use crate::OpenResult;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::*;
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_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 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,194 @@
use core::{mem, slice};
use crate::CallerCtx;
use crate::OpenResult;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::*;
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_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 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,194 @@
use core::{mem, slice};
use crate::CallerCtx;
use crate::OpenResult;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::*;
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_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 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))
}
}

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

@ -0,0 +1,33 @@
use core::cmp;
use core::convert::TryFrom;
use crate::error::*;
use crate::flag::*;
/// 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))
}
}

416
vendor/redox_syscall/src/tests.rs vendored Normal file
View File

@ -0,0 +1,416 @@
#[test]
fn clone() {
let expected_status = 42;
let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) };
if pid_res == Ok(0) {
crate::exit(expected_status).unwrap();
panic!("failed to exit");
} else {
let pid = dbg!(pid_res).unwrap();
let mut status = 0;
assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid));
assert_eq!(dbg!(crate::wifexited(status)), true);
assert_eq!(dbg!(crate::wexitstatus(status)), expected_status);
}
}
//TODO: close
#[test]
fn clock_gettime() {
let mut tp = crate::TimeSpec::default();
assert_eq!(dbg!(
crate::clock_gettime(crate::CLOCK_MONOTONIC, &mut tp)
), Ok(0));
assert_ne!(dbg!(tp), crate::TimeSpec::default());
tp = crate::TimeSpec::default();
assert_eq!(dbg!(
crate::clock_gettime(crate::CLOCK_REALTIME, &mut tp)
), Ok(0));
assert_ne!(dbg!(tp), crate::TimeSpec::default());
}
//TODO: dup
//TODO: dup2
//TODO: exit (handled by clone?)
//TODO: fchmod
//TODO: fcntl
#[test]
fn fexec() {
let name = "file:/bin/ls";
let fd = dbg!(
crate::open(name, crate::O_RDONLY | crate::O_CLOEXEC)
).unwrap();
let args = &[
[name.as_ptr() as usize, name.len()]
];
let vars = &[];
let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) };
if pid_res == Ok(0) {
crate::fexec(fd, args, vars).unwrap();
panic!("failed to fexec");
} else {
assert_eq!(dbg!(crate::close(fd)), Ok(0));
let pid = dbg!(pid_res).unwrap();
let mut status = 0;
assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid));
assert_eq!(dbg!(crate::wifexited(status)), true);
assert_eq!(dbg!(crate::wexitstatus(status)), 0);
}
}
#[test]
fn fmap() {
use std::slice;
let fd = dbg!(
crate::open(
"file:/tmp/syscall-tests-fmap",
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let size = 128;
let map = unsafe {
slice::from_raw_parts_mut(
dbg!(
crate::fmap(fd, &crate::Map {
address: 0,
offset: 0,
size,
flags: crate::PROT_READ | crate::PROT_WRITE
})
).unwrap() as *mut u8,
128
)
};
// Maps should be available after closing
assert_eq!(dbg!(crate::close(fd)), Ok(0));
for i in 0..128 {
map[i as usize] = i;
assert_eq!(map[i as usize], i);
}
//TODO: add msync
unsafe {
assert_eq!(dbg!(
crate::funmap(map.as_mut_ptr() as usize, size)
), Ok(0));
}
}
// funmap tested by fmap
#[test]
fn fpath() {
use std::str;
let path = "file:/tmp/syscall-tests-fpath";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut buf = [0; 4096];
let count = dbg!(
crate::fpath(fd, &mut buf)
).unwrap();
assert_eq!(dbg!(str::from_utf8(&buf[..count])), Ok(path));
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: frename
#[test]
fn fstat() {
let path = "file:/tmp/syscall-tests-fstat";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut stat = crate::Stat::default();
assert_eq!(dbg!(crate::fstat(fd, &mut stat)), Ok(0));
assert_ne!(dbg!(stat), crate::Stat::default());
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
#[test]
fn fstatvfs() {
let path = "file:/tmp/syscall-tests-fstatvfs";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut statvfs = crate::StatVfs::default();
assert_eq!(dbg!(crate::fstatvfs(fd, &mut statvfs)), Ok(0));
assert_ne!(dbg!(statvfs), crate::StatVfs::default());
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: fsync
//TODO: ftruncate
//TODO: futimens
//TODO: futex
#[test]
fn getegid() {
assert_eq!(crate::getegid(), Ok(0));
}
#[test]
fn getens() {
assert_eq!(crate::getens(), Ok(1));
}
#[test]
fn geteuid() {
assert_eq!(crate::geteuid(), Ok(0));
}
#[test]
fn getgid() {
assert_eq!(crate::getgid(), Ok(0));
}
#[test]
fn getns() {
assert_eq!(crate::getns(), Ok(1));
}
//TODO: getpid
//TODO: getpgid
//TODO: getppid
#[test]
fn getuid() {
assert_eq!(crate::getuid(), Ok(0));
}
//TODO: iopl
//TODO: kill
//TODO: link (probably will not work)
#[test]
fn lseek() {
let path = "file:/tmp/syscall-tests-lseek";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
{
let mut buf = [0; 256];
for i in 0..buf.len() {
buf[i] = i as u8;
}
assert_eq!(dbg!(crate::write(fd, &buf)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_CUR)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_END)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
}
{
let mut buf = [0; 256];
assert_eq!(dbg!(crate::read(fd, &mut buf)), Ok(buf.len()));
for i in 0..buf.len() {
assert_eq!(buf[i], i as u8);
}
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_CUR)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_END)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
}
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: mkns
//TODO: mprotect
#[test]
fn nanosleep() {
let req = crate::TimeSpec {
tv_sec: 0,
tv_nsec: 0,
};
let mut rem = crate::TimeSpec::default();
assert_eq!(crate::nanosleep(&req, &mut rem), Ok(0));
assert_eq!(rem, crate::TimeSpec::default());
}
//TODO: open
//TODO: physalloc
//TODO: physfree
//TODO: physmap
//TODO: physunmap
//TODO: read
#[test]
fn rmdir() {
let path = "file:/tmp/syscall-tests-rmdir";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_DIRECTORY | crate::O_CLOEXEC
)
).unwrap();
assert_eq!(dbg!(crate::close(fd)), Ok(0));
assert_eq!(dbg!(crate::rmdir(path)), Ok(0));
}
//TODO: setpgid
//TODO: setregid
//TODO: setrens
//TODO: setreuid
//TODO: sigaction
//TODO: sigprocmask
//TODO: sigreturn
#[test]
fn umask() {
let old = dbg!(crate::umask(0o244)).unwrap();
assert_eq!(dbg!(crate::umask(old)), Ok(0o244));
}
#[test]
fn unlink() {
let path = "file:/tmp/syscall-tests-unlink";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
assert_eq!(dbg!(crate::close(fd)), Ok(0));
assert_eq!(dbg!(crate::unlink(path)), Ok(0));
}
//TODO: virttophys
// waitpid tested by clone
//TODO: write
#[test]
fn sched_yield() {
assert_eq!(dbg!(crate::sched_yield()), Ok(0));
}
#[test]
fn sigaction() {
use std::{
mem,
sync::atomic::{AtomicBool, Ordering}
};
static SA_HANDLER_WAS_RAN: AtomicBool = AtomicBool::new(false);
static SA_HANDLER_2_WAS_IGNORED: AtomicBool = AtomicBool::new(false);
let child = unsafe { crate::clone(crate::CLONE_VM).unwrap() };
if child == 0 {
let pid = crate::getpid().unwrap();
extern "C" fn hello_im_a_signal_handler(signal: usize) {
assert_eq!(signal, crate::SIGUSR1);
SA_HANDLER_WAS_RAN.store(true, Ordering::SeqCst);
}
let my_signal_handler = crate::SigAction {
sa_handler: Some(hello_im_a_signal_handler),
..Default::default()
};
crate::sigaction(crate::SIGUSR1, Some(&my_signal_handler), None).unwrap();
crate::kill(pid, crate::SIGUSR1).unwrap(); // calls handler
let mut old_signal_handler = crate::SigAction::default();
crate::sigaction(
crate::SIGUSR1,
Some(&crate::SigAction {
sa_handler: unsafe { mem::transmute::<usize, Option<extern "C" fn(usize)>>(crate::SIG_IGN) },
..Default::default()
}),
Some(&mut old_signal_handler)
).unwrap();
assert_eq!(my_signal_handler, old_signal_handler);
crate::kill(pid, crate::SIGUSR1).unwrap(); // does nothing
SA_HANDLER_2_WAS_IGNORED.store(true, Ordering::SeqCst);
crate::sigaction(
crate::SIGUSR1,
Some(&crate::SigAction {
sa_handler: unsafe { mem::transmute::<usize, Option<extern "C" fn(usize)>>(crate::SIG_DFL) },
..Default::default()
}),
Some(&mut old_signal_handler)
).unwrap();
crate::kill(pid, crate::SIGUSR1).unwrap(); // actually exits
} else {
let mut status = 0;
dbg!(crate::waitpid(child, &mut status, crate::WaitFlags::empty())).unwrap();
assert!(crate::wifsignaled(status));
assert_eq!(crate::wtermsig(status), crate::SIGUSR1);
assert!(SA_HANDLER_WAS_RAN.load(Ordering::SeqCst));
assert!(SA_HANDLER_2_WAS_IGNORED.load(Ordering::SeqCst));
}
}