Introduce the new error handling mechanism
* Fast error diagnosing (e.g., backtrace and code location) * First-class POSIX errno (e.g., every error has an errno) * Zero-overhead abstraction (e.g., no heap allocation for simple errors) * Ergonomic grammar (e.g., providing convenient macros)
This commit is contained in:
parent
d8d51fcfd4
commit
1a365de08f
2
src/libos/Cargo.lock
generated
2
src/libos/Cargo.lock
generated
@ -2,7 +2,7 @@
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "Occlum"
|
||||
version = "0.0.1"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "Occlum"
|
||||
version = "0.0.1"
|
||||
version = "0.5.0"
|
||||
|
||||
[lib]
|
||||
name = "occlum_rs"
|
||||
|
@ -1,6 +1,22 @@
|
||||
include ../sgxenv.mk
|
||||
|
||||
RELEASE ?= 0
|
||||
# Build LibOS in debug or release mode
|
||||
LIBOS_RELEASE ?= 0
|
||||
|
||||
# The log level for LibOS
|
||||
#
|
||||
# There are five levels:
|
||||
# 1 - error
|
||||
# 2 - warn
|
||||
# 3 - info
|
||||
# 4 - debug
|
||||
# 5 - trace
|
||||
#
|
||||
# By setting the log level to a specific value (say warn), all log messages
|
||||
# whose levels are no greater than the value (error and warn <= warn) will
|
||||
# be printed.
|
||||
LIBOS_LOG ?= error
|
||||
|
||||
ONLY_REBUILD_BUILTIN ?= 0
|
||||
|
||||
# The final and intermediate libraries
|
||||
|
@ -1,64 +1,47 @@
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ffi::CString;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sgxfs::SgxFile;
|
||||
|
||||
const LIBOS_CONFIG_PATH: &str = "./.occlum/build/Occlum.json.protected";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref LIBOS_CONFIG: Config = {
|
||||
fn load_config(config_path: &str) -> Result<Config> {
|
||||
let mut config_file = {
|
||||
let config_file = match SgxFile::open_integrity_only(LIBOS_CONFIG_PATH) {
|
||||
Err(_) => panic!(
|
||||
"Failed to find or open Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(file) => file,
|
||||
};
|
||||
let config_file =
|
||||
SgxFile::open_integrity_only(config_path).map_err(|e| errno!(e))?;
|
||||
|
||||
let actual_mac = match config_file.get_mac() {
|
||||
Err(_) => panic!(
|
||||
"Failed to get the MAC of Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(mac) => mac,
|
||||
};
|
||||
let actual_mac = config_file.get_mac().map_err(|e| errno!(e))?;
|
||||
let expected_mac = conf_get_hardcoded_file_mac();
|
||||
if actual_mac != expected_mac {
|
||||
panic!(
|
||||
"The MAC of Occlum's config file is not as expected: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
);
|
||||
return_errno!(EINVAL, "unexpected file MAC");
|
||||
}
|
||||
|
||||
config_file
|
||||
};
|
||||
let config_json = {
|
||||
let mut config_json = String::new();
|
||||
config_file.read_to_string(&mut config_json).map_err(|_| {
|
||||
panic!(
|
||||
"Failed to read from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
);
|
||||
});
|
||||
config_file
|
||||
.read_to_string(&mut config_json)
|
||||
.map_err(|e| errno!(e))?;
|
||||
config_json
|
||||
};
|
||||
let config_input: InputConfig = match serde_json::from_str(&config_json) {
|
||||
Err(_) => panic!(
|
||||
"Failed to parse JSON from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(config_input) => config_input,
|
||||
};
|
||||
let config = match Config::from_input(&config_input) {
|
||||
Err(_) => panic!(
|
||||
"Found invalid config in Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
let config_input: InputConfig =
|
||||
serde_json::from_str(&config_json).map_err(|e| errno!(e))?;
|
||||
let config = Config::from_input(&config_input)
|
||||
.cause_err(|e| errno!(EINVAL, "invalid config JSON"))?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
let config_path = "./.occlum/build/Occlum.json.protected";
|
||||
match load_config(config_path) {
|
||||
Err(e) => {
|
||||
error!("failed to load config: {}", e.backtrace());
|
||||
panic!();
|
||||
}
|
||||
Ok(config) => config,
|
||||
};
|
||||
config
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -77,18 +60,17 @@ fn conf_get_hardcoded_file_mac() -> sgx_aes_gcm_128bit_tag_t {
|
||||
mac
|
||||
}
|
||||
|
||||
fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
||||
fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t> {
|
||||
let bytes_str_vec = {
|
||||
let bytes_str_vec: Vec<&str> = mac_str.split("-").collect();
|
||||
if bytes_str_vec.len() != 16 {
|
||||
return errno!(EINVAL, "The length or format of MAC string is invalid");
|
||||
return_errno!(EINVAL, "The length or format of MAC string is invalid");
|
||||
}
|
||||
bytes_str_vec
|
||||
};
|
||||
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
for (byte_i, byte_str) in bytes_str_vec.iter().enumerate() {
|
||||
mac[byte_i] = u8::from_str_radix(byte_str, 16)
|
||||
.map_err(|_| Error::new(Errno::EINVAL, "The format of MAC string is invalid"))?;
|
||||
mac[byte_i] = u8::from_str_radix(byte_str, 16).map_err(|e| errno!(e))?;
|
||||
}
|
||||
Ok(mac)
|
||||
}
|
||||
@ -136,7 +118,7 @@ pub struct ConfigMountOptions {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
||||
fn from_input(input: &InputConfig) -> Result<Config> {
|
||||
let vm = ConfigVM::from_input(&input.vm)?;
|
||||
let process = ConfigProcess::from_input(&input.process)?;
|
||||
let env = {
|
||||
@ -163,14 +145,14 @@ impl Config {
|
||||
}
|
||||
|
||||
impl ConfigVM {
|
||||
fn from_input(input: &InputConfigVM) -> Result<ConfigVM, Error> {
|
||||
fn from_input(input: &InputConfigVM) -> Result<ConfigVM> {
|
||||
let user_space_size = parse_memory_size(&input.user_space_size)?;
|
||||
Ok(ConfigVM { user_space_size })
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigProcess {
|
||||
fn from_input(input: &InputConfigProcess) -> Result<ConfigProcess, Error> {
|
||||
fn from_input(input: &InputConfigProcess) -> Result<ConfigProcess> {
|
||||
let default_stack_size = parse_memory_size(&input.default_stack_size)?;
|
||||
let default_heap_size = parse_memory_size(&input.default_heap_size)?;
|
||||
let default_mmap_size = parse_memory_size(&input.default_mmap_size)?;
|
||||
@ -183,7 +165,7 @@ impl ConfigProcess {
|
||||
}
|
||||
|
||||
impl ConfigMount {
|
||||
fn from_input(input: &InputConfigMount) -> Result<ConfigMount, Error> {
|
||||
fn from_input(input: &InputConfigMount) -> Result<ConfigMount> {
|
||||
const ALL_FS_TYPES: [&str; 3] = ["sefs", "hostfs", "ramfs"];
|
||||
|
||||
let type_ = match input.type_.as_str() {
|
||||
@ -191,13 +173,13 @@ impl ConfigMount {
|
||||
"hostfs" => ConfigMountFsType::TYPE_HOSTFS,
|
||||
"ramfs" => ConfigMountFsType::TYPE_RAMFS,
|
||||
_ => {
|
||||
return errno!(EINVAL, "Unsupported file system type");
|
||||
return_errno!(EINVAL, "Unsupported file system type");
|
||||
}
|
||||
};
|
||||
let target = {
|
||||
let target = PathBuf::from(&input.target);
|
||||
if !target.starts_with("/") {
|
||||
return errno!(EINVAL, "Target must be an absolute path");
|
||||
return_errno!(EINVAL, "Target must be an absolute path");
|
||||
}
|
||||
target
|
||||
};
|
||||
@ -213,12 +195,12 @@ impl ConfigMount {
|
||||
}
|
||||
|
||||
impl ConfigMountOptions {
|
||||
fn from_input(input: &InputConfigMountOptions) -> Result<ConfigMountOptions, Error> {
|
||||
fn from_input(input: &InputConfigMountOptions) -> Result<ConfigMountOptions> {
|
||||
let (integrity_only, mac) = if !input.integrity_only {
|
||||
(false, None)
|
||||
} else {
|
||||
if input.mac.is_none() {
|
||||
return errno!(EINVAL, "MAC is expected");
|
||||
return_errno!(EINVAL, "MAC is expected");
|
||||
}
|
||||
(true, Some(parse_mac(&input.mac.as_ref().unwrap())?))
|
||||
};
|
||||
@ -229,7 +211,7 @@ impl ConfigMountOptions {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_memory_size(mem_str: &str) -> Result<usize, Error> {
|
||||
fn parse_memory_size(mem_str: &str) -> Result<usize> {
|
||||
const UNIT2FACTOR: [(&str, usize); 5] = [
|
||||
("KB", 1024),
|
||||
("MB", 1024 * 1024),
|
||||
@ -242,13 +224,13 @@ fn parse_memory_size(mem_str: &str) -> Result<usize, Error> {
|
||||
let (unit, factor) = UNIT2FACTOR
|
||||
.iter()
|
||||
.position(|(unit, _)| mem_str.ends_with(unit))
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "No unit"))
|
||||
.ok_or_else(|| errno!(EINVAL, "No unit"))
|
||||
.map(|unit_i| &UNIT2FACTOR[unit_i])?;
|
||||
let number = match mem_str[0..mem_str.len() - unit.len()]
|
||||
.trim()
|
||||
.parse::<usize>()
|
||||
{
|
||||
Err(_) => return errno!(EINVAL, "No number"),
|
||||
Err(_) => return_errno!(EINVAL, "No number"),
|
||||
Ok(number) => number,
|
||||
};
|
||||
Ok(number * factor)
|
||||
|
@ -9,10 +9,13 @@ const ENCLAVE_PATH: &'static str = ".occlum/build/lib/libocclum.signed.so";
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 {
|
||||
// Init the log infrastructure first so that log messages will be printed afterwards
|
||||
util::log::init();
|
||||
|
||||
let (path, args) = match parse_arguments(path_buf, argv) {
|
||||
Ok(path_and_args) => path_and_args,
|
||||
Err(_) => {
|
||||
Err(e) => {
|
||||
error!("invalid arguments for LibOS: {}", e.backtrace());
|
||||
return EXIT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
};
|
||||
@ -24,7 +27,10 @@ pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char
|
||||
panic::catch_unwind(|| {
|
||||
backtrace::__rust_begin_short_backtrace(|| match do_boot(&path, &args) {
|
||||
Ok(()) => 0,
|
||||
Err(err) => EXIT_STATUS_INTERNAL_ERROR,
|
||||
Err(e) => {
|
||||
error!("failed to boot up LibOS: {}", e.backtrace());
|
||||
EXIT_STATUS_INTERNAL_ERROR
|
||||
}
|
||||
})
|
||||
})
|
||||
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
@ -36,7 +42,10 @@ pub extern "C" fn libos_run(host_tid: i32) -> i32 {
|
||||
panic::catch_unwind(|| {
|
||||
backtrace::__rust_begin_short_backtrace(|| match do_run(host_tid as pid_t) {
|
||||
Ok(exit_status) => exit_status,
|
||||
Err(err) => EXIT_STATUS_INTERNAL_ERROR,
|
||||
Err(e) => {
|
||||
error!("failed to execute a process: {}", e.backtrace());
|
||||
EXIT_STATUS_INTERNAL_ERROR
|
||||
}
|
||||
})
|
||||
})
|
||||
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
@ -53,7 +62,7 @@ const EXIT_STATUS_INTERNAL_ERROR: i32 = 127;
|
||||
fn parse_arguments(
|
||||
path_buf: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
) -> Result<(String, Vec<CString>), Error> {
|
||||
) -> Result<(String, Vec<CString>)> {
|
||||
let path_string = {
|
||||
let path_cstring = clone_cstring_safely(path_buf)?;
|
||||
path_cstring.to_string_lossy().into_owned()
|
||||
@ -61,11 +70,11 @@ fn parse_arguments(
|
||||
let program_cstring = {
|
||||
let program_osstr = Path::new(&path_string)
|
||||
.file_name()
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
|
||||
.ok_or_else(|| errno!(EINVAL, "invalid path"))?;
|
||||
let program_str = program_osstr
|
||||
.to_str()
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
|
||||
CString::new(program_str).or_else(|_| errno!(EINVAL, "Invalid path"))?
|
||||
.ok_or_else(|| errno!(EINVAL, "invalid path"))?;
|
||||
CString::new(program_str).map_err(|e| errno!(e))?
|
||||
};
|
||||
|
||||
let mut args = clone_cstrings_safely(argv)?;
|
||||
@ -74,7 +83,7 @@ fn parse_arguments(
|
||||
}
|
||||
|
||||
// TODO: make sure do_boot can only be called once
|
||||
fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
||||
fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<()> {
|
||||
// info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
||||
util::mpx_util::mpx_enable()?;
|
||||
|
||||
@ -87,7 +96,7 @@ fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
// TODO: make sure do_run() cannot be called after do_boot()
|
||||
fn do_run(host_tid: pid_t) -> Result<i32, Error> {
|
||||
fn do_run(host_tid: pid_t) -> Result<i32> {
|
||||
let exit_status = process::run_task(host_tid)?;
|
||||
|
||||
// sync file system
|
||||
|
@ -1,257 +0,0 @@
|
||||
use prelude::*;
|
||||
use std::{convert, error, ffi, fmt};
|
||||
|
||||
// TODO: remove errno.h
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Error {
|
||||
pub errno: Errno,
|
||||
pub desc: &'static str,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn new(errno: Errno, desc: &'static str) -> Error {
|
||||
let ret = Error { errno, desc };
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<(Errno, &'static str)> for Error {
|
||||
fn from(info: (Errno, &'static str)) -> Error {
|
||||
Error::new(info.0, info.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<std::io::Error> for Error {
|
||||
fn from(info: std::io::Error) -> Error {
|
||||
Error::new(
|
||||
Errno::from_errno(info.raw_os_error().unwrap()),
|
||||
"std::io::Error",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<std::ffi::NulError> for Error {
|
||||
fn from(info: std::ffi::NulError) -> Error {
|
||||
Error::new(Errno::EINVAL, "std::ffi::NulError")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
self.desc
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error: {} ({})", self.desc, self.errno)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum Errno {
|
||||
EUNDEF = 0,
|
||||
EPERM = 1,
|
||||
ENOENT = 2,
|
||||
ESRCH = 3,
|
||||
EINTR = 4,
|
||||
EIO = 5,
|
||||
ENXIO = 6,
|
||||
E2BIG = 7,
|
||||
ENOEXEC = 8,
|
||||
EBADF = 9,
|
||||
ECHILD = 10,
|
||||
EAGAIN = 11,
|
||||
ENOMEM = 12,
|
||||
EACCES = 13,
|
||||
EFAULT = 14,
|
||||
ENOTBLK = 15,
|
||||
EBUSY = 16,
|
||||
EEXIST = 17,
|
||||
EXDEV = 18,
|
||||
ENODEV = 19,
|
||||
ENOTDIR = 20,
|
||||
EISDIR = 21,
|
||||
EINVAL = 22,
|
||||
ENFILE = 23,
|
||||
EMFILE = 24,
|
||||
ENOTTY = 25,
|
||||
ETXTBSY = 26,
|
||||
EFBIG = 27,
|
||||
ENOSPC = 28,
|
||||
ESPIPE = 29,
|
||||
EROFS = 30,
|
||||
EMLINK = 31,
|
||||
EPIPE = 32,
|
||||
EDOM = 33,
|
||||
ERANGE = 34,
|
||||
EDEADLK = 35,
|
||||
ENAMETOOLONG = 36,
|
||||
ENOLCK = 37,
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
EWOULDBLOCK = 41,
|
||||
ENOMSG = 42,
|
||||
EIDRM = 43,
|
||||
ECHRNG = 44,
|
||||
EL2NSYNC = 45,
|
||||
EL3HLT = 46,
|
||||
EL3RST = 47,
|
||||
ELNRNG = 48,
|
||||
EUNATCH = 49,
|
||||
ENOCSI = 50,
|
||||
EL2HLT = 51,
|
||||
EBADE = 52,
|
||||
EBADR = 53,
|
||||
EXFULL = 54,
|
||||
ENOANO = 55,
|
||||
EBADRQC = 56,
|
||||
EBADSLT = 57,
|
||||
EDEADLOCK = 58,
|
||||
EBFONT = 59,
|
||||
ENOSTR = 60,
|
||||
ENODATA = 61,
|
||||
ETIME = 62,
|
||||
ENOSR = 63,
|
||||
ENONET = 64,
|
||||
ENOPKG = 65,
|
||||
EREMOTE = 66,
|
||||
ENOLINK = 67,
|
||||
EADV = 68,
|
||||
ESRMNT = 69,
|
||||
ECOMM = 70,
|
||||
EPROTO = 71,
|
||||
EMULTIHOP = 72,
|
||||
EDOTDOT = 73,
|
||||
EBADMSG = 74,
|
||||
EOVERFLOW = 75,
|
||||
ENOTUNIQ = 76,
|
||||
EBADFD = 77,
|
||||
EREMCHG = 78,
|
||||
ELIBACC = 79,
|
||||
ELIBBAD = 80,
|
||||
ELIBSCN = 81,
|
||||
ELIBMAX = 82,
|
||||
ELIBEXEC = 83,
|
||||
EILSEQ = 84,
|
||||
ERESTART = 85,
|
||||
ESTRPIPE = 86,
|
||||
EUSERS = 87,
|
||||
ENOTSOCK = 88,
|
||||
EDESTADDRREQ = 89,
|
||||
EMSGSIZE = 90,
|
||||
EPROTOTYPE = 91,
|
||||
ENOPROTOOPT = 92,
|
||||
EPROTONOSUPPORT = 93,
|
||||
ESOCKTNOSUPPORT = 94,
|
||||
EOPNOTSUPP = 95,
|
||||
EPFNOSUPPORT = 96,
|
||||
EAFNOSUPPORT = 97,
|
||||
EADDRINUSE = 98,
|
||||
EADDRNOTAVAIL = 99,
|
||||
ENETDOWN = 100,
|
||||
ENETUNREACH = 101,
|
||||
ENETRESET = 102,
|
||||
ECONNABORTED = 103,
|
||||
ECONNRESET = 104,
|
||||
ENOBUFS = 105,
|
||||
EISCONN = 106,
|
||||
ENOTCONN = 107,
|
||||
ESHUTDOWN = 108,
|
||||
ETOOMANYREFS = 109,
|
||||
ETIMEDOUT = 110,
|
||||
ECONNREFUSED = 111,
|
||||
EHOSTDOWN = 112,
|
||||
EHOSTUNREACH = 113,
|
||||
EALREADY = 114,
|
||||
EINPROGRESS = 115,
|
||||
ESTALE = 116,
|
||||
EUCLEAN = 117,
|
||||
ENOTNAM = 118,
|
||||
ENAVAIL = 119,
|
||||
EISNAM = 120,
|
||||
EREMOTEIO = 121,
|
||||
EDQUOT = 122,
|
||||
ENOMEDIUM = 123,
|
||||
EMEDIUMTYPE = 124,
|
||||
ECANCELED = 125,
|
||||
ENOKEY = 126,
|
||||
EKEYEXPIRED = 127,
|
||||
EKEYREVOKED = 128,
|
||||
EKEYREJECTED = 129,
|
||||
EOWNERDEAD = 130,
|
||||
ENOTRECOVERABLE = 131,
|
||||
ERFKILL = 132,
|
||||
EHWPOISON = 133,
|
||||
}
|
||||
|
||||
impl Errno {
|
||||
pub fn as_retval(&self) -> i32 {
|
||||
-(*self as i32)
|
||||
}
|
||||
pub fn from_errno(mut errno: i32) -> Self {
|
||||
if errno < 0 || errno > 133 {
|
||||
errno = 0;
|
||||
}
|
||||
unsafe { core::mem::transmute(errno as u8) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Errno {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"errno = {}, \"{}\"",
|
||||
*self as u32,
|
||||
match *self {
|
||||
Errno::EPERM => "Operation not permitted",
|
||||
Errno::ENOENT => "No such file or directory",
|
||||
Errno::ESRCH => "No such process",
|
||||
Errno::EINTR => "Interrupted system call",
|
||||
Errno::EIO => "I/O error",
|
||||
Errno::ENXIO => "No such device or address",
|
||||
Errno::E2BIG => "Argument list too long",
|
||||
Errno::ENOEXEC => "Exec format error",
|
||||
Errno::EBADF => "Bad file number",
|
||||
Errno::ECHILD => "No child processes",
|
||||
Errno::EAGAIN => "Try again",
|
||||
Errno::ENOMEM => "Out of memory",
|
||||
Errno::EACCES => "Permission denied",
|
||||
Errno::EFAULT => "Bad address",
|
||||
Errno::ENOTBLK => "Block device required",
|
||||
Errno::EBUSY => "Device or resource busy",
|
||||
Errno::EEXIST => "File exists",
|
||||
Errno::EXDEV => "Cross-device link",
|
||||
Errno::ENODEV => "No such device",
|
||||
Errno::ENOTDIR => "Not a directory",
|
||||
Errno::EISDIR => "Is a directory",
|
||||
Errno::EINVAL => "Invalid argument",
|
||||
Errno::ENFILE => "File table overflow",
|
||||
Errno::EMFILE => "Too many open files",
|
||||
Errno::ENOTTY => "Not a typewriter",
|
||||
Errno::ETXTBSY => "Text file busy",
|
||||
Errno::EFBIG => "File too large",
|
||||
Errno::ENOSPC => "No space left on device",
|
||||
Errno::ESPIPE => "Illegal seek",
|
||||
Errno::EROFS => "Read-only file system",
|
||||
Errno::EMLINK => "Too many links",
|
||||
Errno::EPIPE => "Broken pipe",
|
||||
Errno::EDOM => "Math argument out of domain of func",
|
||||
Errno::ERANGE => "Math result not representable",
|
||||
Errno::EDEADLK => "Resource deadlock would occur",
|
||||
Errno::ENAMETOOLONG => "File name too long",
|
||||
Errno::ENOLCK => "No record locks available",
|
||||
Errno::ENOSYS => "Function not implemented",
|
||||
Errno::ENOTEMPTY => "Directory not empty",
|
||||
_ => "Unknown error",
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
65
src/libos/src/error/backtrace.rs
Normal file
65
src/libos/src/error/backtrace.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErrorBacktrace<'a> {
|
||||
next_error: Option<&'a Error>,
|
||||
}
|
||||
|
||||
impl<'a> ErrorBacktrace<'a> {
|
||||
fn new(last_error: &'a Error) -> ErrorBacktrace {
|
||||
ErrorBacktrace {
|
||||
next_error: Some(last_error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for ErrorBacktrace<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let error_strings: Vec<String> = self.clone().map(|e| e.to_string()).collect();
|
||||
let error_backtrace = error_strings.join("\n Caused by ");
|
||||
write!(f, "{}", error_backtrace)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ErrorBacktrace<'a> {
|
||||
type Item = &'a Error;
|
||||
|
||||
fn next(&mut self) -> Option<&'a Error> {
|
||||
if let Some(this_error) = self.next_error {
|
||||
self.next_error = this_error.get_cause().as_ref().map(|e| -> &Error { &e });
|
||||
return Some(this_error);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn cause_err<F>(self, f: F) -> Error
|
||||
where
|
||||
F: FnOnce(&Error) -> Error,
|
||||
{
|
||||
let old_err = self;
|
||||
let mut new_err = f(&old_err);
|
||||
*new_err.get_cause_mut() = Some(Box::new(old_err));
|
||||
new_err
|
||||
}
|
||||
|
||||
pub fn backtrace(&self) -> ErrorBacktrace {
|
||||
ErrorBacktrace::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ResultExt<T> {
|
||||
fn cause_err<F>(self, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Error) -> Error;
|
||||
}
|
||||
|
||||
impl<T> ResultExt<T> for Result<T> {
|
||||
fn cause_err<F>(self, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Error) -> Error,
|
||||
{
|
||||
self.map_err(|old_e| old_e.cause_err(f))
|
||||
}
|
||||
}
|
207
src/libos/src/error/errno.rs
Normal file
207
src/libos/src/error/errno.rs
Normal file
@ -0,0 +1,207 @@
|
||||
use super::*;
|
||||
|
||||
/// POSIX errno
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum Errno {
|
||||
// Note: we don't define EUNDEF (=0) since a syscall cannot return 0 to
|
||||
// indicate the occurance of an error
|
||||
EPERM = 1,
|
||||
ENOENT = 2,
|
||||
ESRCH = 3,
|
||||
EINTR = 4,
|
||||
EIO = 5,
|
||||
ENXIO = 6,
|
||||
E2BIG = 7,
|
||||
ENOEXEC = 8,
|
||||
EBADF = 9,
|
||||
ECHILD = 10,
|
||||
EAGAIN = 11,
|
||||
ENOMEM = 12,
|
||||
EACCES = 13,
|
||||
EFAULT = 14,
|
||||
ENOTBLK = 15,
|
||||
EBUSY = 16,
|
||||
EEXIST = 17,
|
||||
EXDEV = 18,
|
||||
ENODEV = 19,
|
||||
ENOTDIR = 20,
|
||||
EISDIR = 21,
|
||||
EINVAL = 22,
|
||||
ENFILE = 23,
|
||||
EMFILE = 24,
|
||||
ENOTTY = 25,
|
||||
ETXTBSY = 26,
|
||||
EFBIG = 27,
|
||||
ENOSPC = 28,
|
||||
ESPIPE = 29,
|
||||
EROFS = 30,
|
||||
EMLINK = 31,
|
||||
EPIPE = 32,
|
||||
EDOM = 33,
|
||||
ERANGE = 34,
|
||||
EDEADLK = 35,
|
||||
ENAMETOOLONG = 36,
|
||||
ENOLCK = 37,
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
EWOULDBLOCK = 41,
|
||||
ENOMSG = 42,
|
||||
EIDRM = 43,
|
||||
ECHRNG = 44,
|
||||
EL2NSYNC = 45,
|
||||
EL3HLT = 46,
|
||||
EL3RST = 47,
|
||||
ELNRNG = 48,
|
||||
EUNATCH = 49,
|
||||
ENOCSI = 50,
|
||||
EL2HLT = 51,
|
||||
EBADE = 52,
|
||||
EBADR = 53,
|
||||
EXFULL = 54,
|
||||
ENOANO = 55,
|
||||
EBADRQC = 56,
|
||||
EBADSLT = 57,
|
||||
EDEADLOCK = 58,
|
||||
EBFONT = 59,
|
||||
ENOSTR = 60,
|
||||
ENODATA = 61,
|
||||
ETIME = 62,
|
||||
ENOSR = 63,
|
||||
ENONET = 64,
|
||||
ENOPKG = 65,
|
||||
EREMOTE = 66,
|
||||
ENOLINK = 67,
|
||||
EADV = 68,
|
||||
ESRMNT = 69,
|
||||
ECOMM = 70,
|
||||
EPROTO = 71,
|
||||
EMULTIHOP = 72,
|
||||
EDOTDOT = 73,
|
||||
EBADMSG = 74,
|
||||
EOVERFLOW = 75,
|
||||
ENOTUNIQ = 76,
|
||||
EBADFD = 77,
|
||||
EREMCHG = 78,
|
||||
ELIBACC = 79,
|
||||
ELIBBAD = 80,
|
||||
ELIBSCN = 81,
|
||||
ELIBMAX = 82,
|
||||
ELIBEXEC = 83,
|
||||
EILSEQ = 84,
|
||||
ERESTART = 85,
|
||||
ESTRPIPE = 86,
|
||||
EUSERS = 87,
|
||||
ENOTSOCK = 88,
|
||||
EDESTADDRREQ = 89,
|
||||
EMSGSIZE = 90,
|
||||
EPROTOTYPE = 91,
|
||||
ENOPROTOOPT = 92,
|
||||
EPROTONOSUPPORT = 93,
|
||||
ESOCKTNOSUPPORT = 94,
|
||||
EOPNOTSUPP = 95,
|
||||
EPFNOSUPPORT = 96,
|
||||
EAFNOSUPPORT = 97,
|
||||
EADDRINUSE = 98,
|
||||
EADDRNOTAVAIL = 99,
|
||||
ENETDOWN = 100,
|
||||
ENETUNREACH = 101,
|
||||
ENETRESET = 102,
|
||||
ECONNABORTED = 103,
|
||||
ECONNRESET = 104,
|
||||
ENOBUFS = 105,
|
||||
EISCONN = 106,
|
||||
ENOTCONN = 107,
|
||||
ESHUTDOWN = 108,
|
||||
ETOOMANYREFS = 109,
|
||||
ETIMEDOUT = 110,
|
||||
ECONNREFUSED = 111,
|
||||
EHOSTDOWN = 112,
|
||||
EHOSTUNREACH = 113,
|
||||
EALREADY = 114,
|
||||
EINPROGRESS = 115,
|
||||
ESTALE = 116,
|
||||
EUCLEAN = 117,
|
||||
ENOTNAM = 118,
|
||||
ENAVAIL = 119,
|
||||
EISNAM = 120,
|
||||
EREMOTEIO = 121,
|
||||
EDQUOT = 122,
|
||||
ENOMEDIUM = 123,
|
||||
EMEDIUMTYPE = 124,
|
||||
ECANCELED = 125,
|
||||
ENOKEY = 126,
|
||||
EKEYEXPIRED = 127,
|
||||
EKEYREVOKED = 128,
|
||||
EKEYREJECTED = 129,
|
||||
EOWNERDEAD = 130,
|
||||
ENOTRECOVERABLE = 131,
|
||||
ERFKILL = 132,
|
||||
EHWPOISON = 133,
|
||||
// Note: always keep the last item in sync with ERRNO_MAX
|
||||
}
|
||||
const ERRNO_MAX: u32 = Errno::EHWPOISON as u32;
|
||||
|
||||
impl Errno {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
use self::Errno::*;
|
||||
match *self {
|
||||
EPERM => "Operation not permitted",
|
||||
ENOENT => "No such file or directory",
|
||||
ESRCH => "No such process",
|
||||
EINTR => "Interrupted system call",
|
||||
EIO => "I/O error",
|
||||
ENXIO => "No such device or address",
|
||||
E2BIG => "Argument list too long",
|
||||
ENOEXEC => "Exec format error",
|
||||
EBADF => "Bad file number",
|
||||
ECHILD => "No child processes",
|
||||
EAGAIN => "Try again",
|
||||
ENOMEM => "Out of memory",
|
||||
EACCES => "Permission denied",
|
||||
EFAULT => "Bad address",
|
||||
ENOTBLK => "Block device required",
|
||||
EBUSY => "Device or resource busy",
|
||||
EEXIST => "File exists",
|
||||
EXDEV => "Cross-device link",
|
||||
ENODEV => "No such device",
|
||||
ENOTDIR => "Not a directory",
|
||||
EISDIR => "Is a directory",
|
||||
EINVAL => "Invalid argument",
|
||||
ENFILE => "File table overflow",
|
||||
EMFILE => "Too many open files",
|
||||
ENOTTY => "Not a typewriter",
|
||||
ETXTBSY => "Text file busy",
|
||||
EFBIG => "File too large",
|
||||
ENOSPC => "No space left on device",
|
||||
ESPIPE => "Illegal seek",
|
||||
EROFS => "Read-only file system",
|
||||
EMLINK => "Too many links",
|
||||
EPIPE => "Broken pipe",
|
||||
EDOM => "Math argument out of domain of func",
|
||||
ERANGE => "Math result not representable",
|
||||
EDEADLK => "Resource deadlock would occur",
|
||||
ENAMETOOLONG => "File name too long",
|
||||
ENOLCK => "No record locks available",
|
||||
ENOSYS => "Function not implemented",
|
||||
ENOTEMPTY => "Directory not empty",
|
||||
_ => "Unknown error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Errno {
|
||||
fn from(mut raw_errno: u32) -> Self {
|
||||
if raw_errno > ERRNO_MAX {
|
||||
raw_errno = 0;
|
||||
}
|
||||
unsafe { core::mem::transmute(raw_errno as u8) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Errno {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?} (#{}, {})", *self, *self as u32, self.as_str())
|
||||
}
|
||||
}
|
107
src/libos/src/error/error.rs
Normal file
107
src/libos/src/error/error.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
inner: Error__,
|
||||
location: Option<ErrorLocation>,
|
||||
cause: Option<Box<Error>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Error__ {
|
||||
Embedded((Errno, &'static str)),
|
||||
Boxed(Box<dyn ToErrno + 'static>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ErrorLocation {
|
||||
line: u32,
|
||||
file: &'static str,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn embeded(inner: (Errno, &'static str), location: Option<ErrorLocation>) -> Error {
|
||||
Error {
|
||||
inner: Error__::Embedded(inner),
|
||||
location: location,
|
||||
cause: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boxed<T>(inner: T, location: Option<ErrorLocation>) -> Error
|
||||
where
|
||||
T: ToErrno + 'static,
|
||||
{
|
||||
Error {
|
||||
inner: Error__::Boxed(Box::new(inner)),
|
||||
location: location,
|
||||
cause: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errno(&self) -> Errno {
|
||||
match &self.inner {
|
||||
Error__::Embedded((errno, _)) => *errno,
|
||||
Error__::Boxed(inner_error) => inner_error.errno(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cause_mut(&mut self) -> &mut Option<Box<Error>> {
|
||||
&mut self.cause
|
||||
}
|
||||
|
||||
pub fn get_cause(&self) -> &Option<Box<Error>> {
|
||||
&self.cause
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorLocation {
|
||||
pub fn new(file: &'static str, line: u32) -> ErrorLocation {
|
||||
ErrorLocation {
|
||||
file: file,
|
||||
line: line,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
self.errno().as_str()
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn std::error::Error> {
|
||||
self.cause.as_ref().map(|e| e as &dyn std::error::Error)
|
||||
}
|
||||
/*
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
self.cause
|
||||
.as_ref()
|
||||
.map(|e| e as &(dyn std::error::Error + 'static))
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.inner)?;
|
||||
if let Some(location) = self.location {
|
||||
write!(f, " {}", location)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error__ {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error__::Embedded((errno, msg)) => write!(f, "{}: {}", errno, msg),
|
||||
Error__::Boxed(inner_error) => write!(f, "{}: {}", inner_error.errno(), inner_error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorLocation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[line = {}, file = {}]", self.line, self.file)
|
||||
}
|
||||
}
|
53
src/libos/src/error/mod.rs
Normal file
53
src/libos/src/error/mod.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use super::*;
|
||||
use std::fmt;
|
||||
|
||||
mod backtrace;
|
||||
mod errno;
|
||||
mod error;
|
||||
mod to_errno;
|
||||
|
||||
pub use self::backtrace::{ErrorBacktrace, ResultExt};
|
||||
pub use self::errno::Errno;
|
||||
pub use self::errno::Errno::*;
|
||||
pub use self::error::{Error, ErrorLocation};
|
||||
pub use self::to_errno::ToErrno;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
macro_rules! errno {
|
||||
($errno_expr: expr, $error_msg: expr) => {{
|
||||
let inner_error = {
|
||||
let errno: Errno = $errno_expr;
|
||||
let msg: &'static str = $error_msg;
|
||||
(errno, msg)
|
||||
};
|
||||
let error = Error::embeded(inner_error, Some(ErrorLocation::new(file!(), line!())));
|
||||
error
|
||||
}};
|
||||
($error_expr: expr) => {{
|
||||
let inner_error = $error_expr;
|
||||
let error = Error::boxed(inner_error, Some(ErrorLocation::new(file!(), line!())));
|
||||
error
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! return_errno {
|
||||
($errno_expr: expr, $error_msg: expr) => {{
|
||||
return Err(errno!($errno_expr, $error_msg));
|
||||
}};
|
||||
($error_expr: expr) => {{
|
||||
return Err(errno!($error_expr));
|
||||
}};
|
||||
}
|
||||
|
||||
// return Err(errno) if libc return -1
|
||||
macro_rules! try_libc {
|
||||
($ret: expr) => {{
|
||||
let ret = unsafe { $ret };
|
||||
if ret == -1 {
|
||||
let errno = unsafe { libc::errno() };
|
||||
return_errno!(Errno::from(errno as u32), "libc error");
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
100
src/libos/src/error/to_errno.rs
Normal file
100
src/libos/src/error/to_errno.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use super::*;
|
||||
|
||||
pub trait ToErrno: fmt::Display + fmt::Debug {
|
||||
fn errno(&self) -> Errno;
|
||||
}
|
||||
|
||||
impl ToErrno for Errno {
|
||||
fn errno(&self) -> Errno {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Error
|
||||
where
|
||||
T: ToErrno + 'static,
|
||||
{
|
||||
fn from(t: T) -> Error {
|
||||
Error::boxed(t, None)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::ErrorKind> for Errno {
|
||||
fn from(kind: std::io::ErrorKind) -> Errno {
|
||||
use std::io::ErrorKind::*;
|
||||
match kind {
|
||||
NotFound => ENOENT,
|
||||
PermissionDenied => EPERM,
|
||||
ConnectionRefused => ECONNREFUSED,
|
||||
ConnectionReset => ECONNRESET,
|
||||
ConnectionAborted => ECONNABORTED,
|
||||
NotConnected => ENOTCONN,
|
||||
AddrInUse => EADDRINUSE,
|
||||
AddrNotAvailable => EADDRNOTAVAIL,
|
||||
BrokenPipe => EPIPE,
|
||||
AlreadyExists => EEXIST,
|
||||
WouldBlock => EWOULDBLOCK,
|
||||
InvalidInput => EINVAL,
|
||||
InvalidData => EBADMSG, /* TODO: correct? */
|
||||
TimedOut => ETIMEDOUT,
|
||||
Interrupted => EINTR,
|
||||
WriteZero => EINVAL,
|
||||
UnexpectedEof => EIO,
|
||||
Other => EIO,
|
||||
_ => EIO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToErrno for std::io::Error {
|
||||
fn errno(&self) -> Errno {
|
||||
Errno::from(self.kind())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToErrno for std::ffi::NulError {
|
||||
fn errno(&self) -> Errno {
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
impl ToErrno for std::num::ParseIntError {
|
||||
fn errno(&self) -> Errno {
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
impl ToErrno for serde_json::Error {
|
||||
fn errno(&self) -> Errno {
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
impl ToErrno for rcore_fs::vfs::FsError {
|
||||
fn errno(&self) -> Errno {
|
||||
use rcore_fs::vfs::FsError;
|
||||
match *self {
|
||||
FsError::NotSupported => ENOSYS,
|
||||
FsError::NotFile => EISDIR,
|
||||
FsError::IsDir => EISDIR,
|
||||
FsError::NotDir => ENOTDIR,
|
||||
FsError::EntryNotFound => ENOENT,
|
||||
FsError::EntryExist => EEXIST,
|
||||
FsError::NotSameFs => EXDEV,
|
||||
FsError::InvalidParam => EINVAL,
|
||||
FsError::NoDeviceSpace => ENOMEM,
|
||||
FsError::DirRemoved => ENOENT,
|
||||
FsError::DirNotEmpty => ENOTEMPTY,
|
||||
FsError::WrongFs => EINVAL,
|
||||
FsError::DeviceError => EIO,
|
||||
FsError::SymLoop => ELOOP,
|
||||
FsError::NoDevice => ENXIO,
|
||||
FsError::IOCTLError => EINVAL,
|
||||
FsError::Again => EAGAIN,
|
||||
FsError::Busy => EBUSY,
|
||||
FsError::WrProtected => EROFS,
|
||||
FsError::NoIntegrity => EIO,
|
||||
FsError::PermError => EPERM,
|
||||
}
|
||||
}
|
||||
}
|
@ -167,11 +167,11 @@ impl CpuId {
|
||||
cpuid
|
||||
}
|
||||
|
||||
fn lookup_cpuid_from_cache(&self, cpuid_input: CpuIdInput) -> Result<CpuIdResult, Error> {
|
||||
fn lookup_cpuid_from_cache(&self, cpuid_input: CpuIdInput) -> Result<CpuIdResult> {
|
||||
self.cache
|
||||
.lookup(&cpuid_input)
|
||||
.map(|result| result.clone())
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "cpuid_result not found"))
|
||||
.ok_or_else(|| errno!(ENOENT, "cpuid_result not found"))
|
||||
}
|
||||
|
||||
pub fn get_max_basic_leaf(&self) -> u32 {
|
||||
|
@ -12,8 +12,8 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl AccessModes {
|
||||
pub fn from_u32(bits: u32) -> Result<AccessModes, Error> {
|
||||
AccessModes::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "invalid mode"))
|
||||
pub fn from_u32(bits: u32) -> Result<AccessModes> {
|
||||
AccessModes::from_bits(bits).ok_or_else(|| errno!(EINVAL, "invalid mode"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,8 +25,8 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl AccessFlags {
|
||||
pub fn from_u32(bits: u32) -> Result<AccessFlags, Error> {
|
||||
AccessFlags::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "invalid flags"))
|
||||
pub fn from_u32(bits: u32) -> Result<AccessFlags> {
|
||||
AccessFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "invalid flags"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,19 +37,19 @@ pub fn do_faccessat(
|
||||
path: &str,
|
||||
mode: AccessModes,
|
||||
flags: AccessFlags,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<()> {
|
||||
info!(
|
||||
"faccessat: dirfd: {:?}, path: {:?}, mode: {:?}, flags: {:?}",
|
||||
dirfd, path, mode, flags
|
||||
);
|
||||
match dirfd {
|
||||
// TODO: handle dirfd
|
||||
Some(dirfd) => errno!(ENOSYS, "cannot accept dirfd"),
|
||||
Some(dirfd) => return_errno!(ENOSYS, "cannot accept dirfd"),
|
||||
None => do_access(path, mode),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_access(path: &str, mode: AccessModes) -> Result<(), Error> {
|
||||
pub fn do_access(path: &str, mode: AccessModes) -> Result<()> {
|
||||
info!("access: path: {:?}, mode: {:?}", path, mode);
|
||||
let current_ref = process::get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
|
@ -4,52 +4,52 @@ use super::*;
|
||||
pub struct DevNull;
|
||||
|
||||
impl File for DevNull {
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize> {
|
||||
Ok(_buf.len())
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
|
||||
Ok(_buf.len())
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
Ok(bufs.iter().map(|buf| buf.len()).sum())
|
||||
}
|
||||
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support reads")
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support reads")
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support reads")
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support reads")
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support reads")
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support reads")
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(EINVAL, "device not support seeks")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(EINVAL, "device not support seeks")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
errno!(EINVAL, "device not support resizing")
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
return_errno!(EINVAL, "device not support resizing")
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
errno!(ENOTDIR, "device is not a directory")
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
return_errno!(ENOTDIR, "device is not a directory")
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
|
@ -8,21 +8,21 @@ extern "C" {
|
||||
}
|
||||
|
||||
impl File for DevRandom {
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
||||
let buf = _buf.as_mut_ptr();
|
||||
let size = _buf.len();
|
||||
let status = unsafe { sgx_read_rand(buf, size) };
|
||||
if status != sgx_status_t::SGX_SUCCESS {
|
||||
return errno!(EAGAIN, "failed to get random number from sgx");
|
||||
return_errno!(EAGAIN, "failed to get random number from sgx");
|
||||
}
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
|
||||
self.read(_buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut total_nbytes = 0;
|
||||
for buf in bufs {
|
||||
match self.read(buf) {
|
||||
@ -41,40 +41,40 @@ impl File for DevRandom {
|
||||
Ok(total_nbytes)
|
||||
}
|
||||
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(EINVAL, "device not support seeks")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(EINVAL, "device not support seeks")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
errno!(EINVAL, "device not support resizing")
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
return_errno!(EINVAL, "device not support resizing")
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
errno!(ENOTDIR, "device is not a directory")
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
return_errno!(ENOTDIR, "device is not a directory")
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
|
@ -4,18 +4,18 @@ use super::*;
|
||||
pub struct DevZero;
|
||||
|
||||
impl File for DevZero {
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<usize> {
|
||||
for b in _buf.iter_mut() {
|
||||
*b = 0;
|
||||
}
|
||||
Ok(_buf.len())
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
|
||||
self.read(_buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut total_nbytes = 0;
|
||||
for buf in bufs {
|
||||
total_nbytes += self.read(buf)?;
|
||||
@ -23,40 +23,40 @@ impl File for DevZero {
|
||||
Ok(total_nbytes)
|
||||
}
|
||||
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn write(&self, _buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
errno!(EINVAL, "device not support writes")
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
return_errno!(EINVAL, "device not support writes")
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(EINVAL, "device not support seeks")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(EINVAL, "device not support seeks")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
errno!(EINVAL, "device not support resizing")
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
return_errno!(EINVAL, "device not support resizing")
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
errno!(ENOTDIR, "device is not a directory")
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
return_errno!(ENOTDIR, "device is not a directory")
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
|
@ -5,18 +5,18 @@ use std::fmt;
|
||||
use std::io::SeekFrom;
|
||||
|
||||
pub trait File: Debug + Sync + Send + Any {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error>;
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error>;
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error>;
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error>;
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error>;
|
||||
fn metadata(&self) -> Result<Metadata, Error>;
|
||||
fn set_len(&self, len: u64) -> Result<(), Error>;
|
||||
fn sync_all(&self) -> Result<(), Error>;
|
||||
fn sync_data(&self) -> Result<(), Error>;
|
||||
fn read_entry(&self) -> Result<String, Error>;
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize>;
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize>;
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize>;
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t>;
|
||||
fn metadata(&self) -> Result<Metadata>;
|
||||
fn set_len(&self, len: u64) -> Result<()>;
|
||||
fn sync_all(&self) -> Result<()>;
|
||||
fn sync_data(&self) -> Result<()>;
|
||||
fn read_entry(&self) -> Result<String>;
|
||||
fn as_any(&self) -> &Any;
|
||||
}
|
||||
|
||||
@ -34,9 +34,9 @@ impl SgxFile {
|
||||
is_readable: bool,
|
||||
is_writable: bool,
|
||||
is_append: bool,
|
||||
) -> Result<SgxFile, Error> {
|
||||
) -> Result<SgxFile> {
|
||||
if !is_readable && !is_writable {
|
||||
return errno!(EINVAL, "Invalid permissions");
|
||||
return_errno!(EINVAL, "Invalid permissions");
|
||||
}
|
||||
|
||||
Ok(SgxFile {
|
||||
@ -52,67 +52,67 @@ impl SgxFile {
|
||||
}
|
||||
|
||||
impl File for SgxFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.read(buf)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.write(buf)
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.seek(SeekFrom::Start(offset as u64))?;
|
||||
inner.read(buf)
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.seek(SeekFrom::Start(offset as u64))?;
|
||||
inner.write(buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.readv(bufs)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.writev(bufs)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.seek(pos)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -133,9 +133,9 @@ struct SgxFileInner {
|
||||
}
|
||||
|
||||
impl SgxFileInner {
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
if !self.is_writable {
|
||||
return errno!(EINVAL, "File not writable");
|
||||
return_errno!(EINVAL, "File not writable");
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
@ -147,13 +147,9 @@ impl SgxFileInner {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
// TODO: recover from error
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos).map_err(|e| errno!(e))?;
|
||||
|
||||
let write_len = {
|
||||
file.write(buf)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
let write_len = { file.write(buf).map_err(|e| errno!(e))? };
|
||||
|
||||
if !self.is_append {
|
||||
self.pos += write_len;
|
||||
@ -161,28 +157,24 @@ impl SgxFileInner {
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
if !self.is_readable {
|
||||
return errno!(EINVAL, "File not readable");
|
||||
return_errno!(EINVAL, "File not readable");
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos).map_err(|e| errno!(e))?;
|
||||
|
||||
let read_len = {
|
||||
file.read(buf)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
let read_len = { file.read(buf).map_err(|e| errno!(e))? };
|
||||
|
||||
self.pos += read_len;
|
||||
Ok(read_len)
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<off_t> {
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
@ -196,23 +188,20 @@ impl SgxFileInner {
|
||||
let backward_offset = (-relative_offset) as usize;
|
||||
if self.pos < backward_offset {
|
||||
// underflow
|
||||
return errno!(EINVAL, "Invalid seek position");
|
||||
return_errno!(EINVAL, "Invalid seek position");
|
||||
}
|
||||
SeekFrom::Start((self.pos - backward_offset) as u64)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.pos = file
|
||||
.seek(pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?
|
||||
as usize;
|
||||
self.pos = file.seek(pos).map_err(|e| errno!(e))? as usize;
|
||||
Ok(self.pos as off_t)
|
||||
}
|
||||
|
||||
pub fn writev(&mut self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
pub fn writev(&mut self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
if !self.is_writable {
|
||||
return errno!(EINVAL, "File not writable");
|
||||
return_errno!(EINVAL, "File not writable");
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
@ -223,8 +212,7 @@ impl SgxFileInner {
|
||||
} else {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos).map_err(|e| errno!(e))?;
|
||||
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -238,7 +226,7 @@ impl SgxFileInner {
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
// a complete failure
|
||||
0 => return errno!(EINVAL, "Failed to write"),
|
||||
0 => return_errno!(EINVAL, "Failed to write"),
|
||||
// a partially failure
|
||||
_ => break,
|
||||
}
|
||||
@ -250,17 +238,16 @@ impl SgxFileInner {
|
||||
Ok(total_bytes)
|
||||
}
|
||||
|
||||
fn readv(&mut self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&mut self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
if !self.is_readable {
|
||||
return errno!(EINVAL, "File not readable");
|
||||
return_errno!(EINVAL, "File not readable");
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos).map_err(|e| errno!(e))?;
|
||||
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -274,7 +261,7 @@ impl SgxFileInner {
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
// a complete failure
|
||||
0 => return errno!(EINVAL, "Failed to write"),
|
||||
0 => return_errno!(EINVAL, "Failed to write"),
|
||||
// a partially failure
|
||||
_ => break,
|
||||
}
|
||||
@ -309,33 +296,28 @@ impl StdoutFile {
|
||||
}
|
||||
|
||||
impl File for StdoutFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "Stdout does not support read")
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
return_errno!(EBADF, "Stdout does not support read")
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
let write_len = {
|
||||
self.inner
|
||||
.lock()
|
||||
.write(buf)
|
||||
.map_err(|e| (Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let write_len = { self.inner.lock().write(buf).map_err(|e| errno!(e))? };
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
self.read(buf)
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
self.write(buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "Stdout does not support read")
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
return_errno!(EBADF, "Stdout does not support read")
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
let mut guard = self.inner.lock();
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -349,7 +331,7 @@ impl File for StdoutFile {
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
// a complete failure
|
||||
0 => return errno!(EINVAL, "Failed to write"),
|
||||
0 => return_errno!(EINVAL, "Failed to write"),
|
||||
// a partially failure
|
||||
_ => break,
|
||||
}
|
||||
@ -359,11 +341,11 @@ impl File for StdoutFile {
|
||||
Ok(total_bytes)
|
||||
}
|
||||
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Stdout does not support seek")
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Stdout does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
@ -382,21 +364,21 @@ impl File for StdoutFile {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_len(&self, _len: u64) -> Result<(), Error> {
|
||||
errno!(EINVAL, "Stdout does not support set_len")
|
||||
fn set_len(&self, _len: u64) -> Result<()> {
|
||||
return_errno!(EINVAL, "Stdout does not support set_len")
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
self.sync_data()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
self.inner.lock().flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
errno!(ENOTDIR, "Stdout does not support read_entry")
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
return_errno!(ENOTDIR, "Stdout does not support read_entry")
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
@ -426,29 +408,24 @@ impl StdinFile {
|
||||
}
|
||||
|
||||
impl File for StdinFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let read_len = {
|
||||
self.inner
|
||||
.lock()
|
||||
.read(buf)
|
||||
.map_err(|e| (Errno::EINVAL, "Failed to read"))?
|
||||
};
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let read_len = { self.inner.lock().read(buf).map_err(|e| errno!(e))? };
|
||||
Ok(read_len)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "Stdin does not support write")
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EBADF, "Stdin does not support write")
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut guard = self.inner.lock();
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -462,7 +439,7 @@ impl File for StdinFile {
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
// a complete failure
|
||||
0 => return errno!(EINVAL, "Failed to write"),
|
||||
0 => return_errno!(EINVAL, "Failed to write"),
|
||||
// a partially failure
|
||||
_ => break,
|
||||
}
|
||||
@ -472,15 +449,15 @@ impl File for StdinFile {
|
||||
Ok(total_bytes)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "Stdin does not support write")
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
return_errno!(EBADF, "Stdin does not support write")
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Stdin does not support seek")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Stdin does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
@ -499,20 +476,20 @@ impl File for StdinFile {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_len(&self, _len: u64) -> Result<(), Error> {
|
||||
errno!(EINVAL, "Stdin does not support set_len")
|
||||
fn set_len(&self, _len: u64) -> Result<()> {
|
||||
return_errno!(EINVAL, "Stdin does not support set_len")
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
self.sync_data()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
errno!(ENOTDIR, "Stdin does not support read_entry")
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
return_errno!(ENOTDIR, "Stdin does not support read_entry")
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
|
@ -24,7 +24,7 @@ impl FileTable {
|
||||
fd: FileDesc,
|
||||
min_fd: FileDesc,
|
||||
close_on_spawn: bool,
|
||||
) -> Result<FileDesc, Error> {
|
||||
) -> Result<FileDesc> {
|
||||
let file_ref = self.get(fd)?;
|
||||
|
||||
let min_fd = min_fd as usize;
|
||||
@ -86,38 +86,38 @@ impl FileTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, fd: FileDesc) -> Result<FileRef, Error> {
|
||||
pub fn get(&self, fd: FileDesc) -> Result<FileRef> {
|
||||
let entry = self.get_entry(fd)?;
|
||||
Ok(entry.file.clone())
|
||||
}
|
||||
|
||||
pub fn get_entry(&self, fd: FileDesc) -> Result<&FileTableEntry, Error> {
|
||||
pub fn get_entry(&self, fd: FileDesc) -> Result<&FileTableEntry> {
|
||||
if fd as usize >= self.table.len() {
|
||||
return errno!(EBADF, "Invalid file descriptor");
|
||||
return_errno!(EBADF, "Invalid file descriptor");
|
||||
}
|
||||
|
||||
let table = &self.table;
|
||||
match table[fd as usize].as_ref() {
|
||||
Some(table_entry) => Ok(table_entry),
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
None => return_errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_entry_mut(&mut self, fd: FileDesc) -> Result<&mut FileTableEntry, Error> {
|
||||
pub fn get_entry_mut(&mut self, fd: FileDesc) -> Result<&mut FileTableEntry> {
|
||||
if fd as usize >= self.table.len() {
|
||||
return errno!(EBADF, "Invalid file descriptor");
|
||||
return_errno!(EBADF, "Invalid file descriptor");
|
||||
}
|
||||
|
||||
let table = &mut self.table;
|
||||
match table[fd as usize].as_mut() {
|
||||
Some(table_entry) => Ok(table_entry),
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
None => return_errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn del(&mut self, fd: FileDesc) -> Result<FileRef, Error> {
|
||||
pub fn del(&mut self, fd: FileDesc) -> Result<FileRef> {
|
||||
if fd as usize >= self.table.len() {
|
||||
return errno!(EBADF, "Invalid file descriptor");
|
||||
return_errno!(EBADF, "Invalid file descriptor");
|
||||
}
|
||||
|
||||
let mut del_table_entry = None;
|
||||
@ -128,7 +128,7 @@ impl FileTable {
|
||||
self.num_fds -= 1;
|
||||
Ok(del_table_entry.file)
|
||||
}
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
None => return_errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,19 +18,19 @@ pub struct OpenOptions {
|
||||
}
|
||||
|
||||
impl File for INodeFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
if !self.options.read {
|
||||
return errno!(EBADF, "File not readable");
|
||||
return_errno!(EBADF, "File not readable");
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
let len = self.inode.read_at(*offset, buf)?;
|
||||
let len = self.inode.read_at(*offset, buf).map_err(|e| errno!(e))?;
|
||||
*offset += len;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if !self.options.write {
|
||||
return errno!(EBADF, "File not writable");
|
||||
return_errno!(EBADF, "File not writable");
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
if self.options.append {
|
||||
@ -42,25 +42,25 @@ impl File for INodeFile {
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
if !self.options.read {
|
||||
return errno!(EBADF, "File not readable");
|
||||
return_errno!(EBADF, "File not readable");
|
||||
}
|
||||
let len = self.inode.read_at(offset, buf)?;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
if !self.options.write {
|
||||
return errno!(EBADF, "File not writable");
|
||||
return_errno!(EBADF, "File not writable");
|
||||
}
|
||||
let len = self.inode.write_at(offset, buf)?;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
if !self.options.read {
|
||||
return errno!(EBADF, "File not readable");
|
||||
return_errno!(EBADF, "File not readable");
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
let mut total_len = 0;
|
||||
@ -77,9 +77,9 @@ impl File for INodeFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
if !self.options.write {
|
||||
return errno!(EBADF, "File not writable");
|
||||
return_errno!(EBADF, "File not writable");
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
if self.options.append {
|
||||
@ -100,7 +100,7 @@ impl File for INodeFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
*offset = match pos {
|
||||
SeekFrom::Start(off) => off as usize,
|
||||
@ -110,32 +110,32 @@ impl File for INodeFile {
|
||||
Ok(*offset as i64)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
let metadata = self.inode.metadata()?;
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
if !self.options.write {
|
||||
return errno!(EBADF, "File not writable. Can't set len.");
|
||||
return_errno!(EBADF, "File not writable. Can't set len.");
|
||||
}
|
||||
self.inode.resize(len as usize)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
self.inode.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
self.inode.sync_data()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
if !self.options.read {
|
||||
return errno!(EBADF, "File not readable. Can't read entry.");
|
||||
return_errno!(EBADF, "File not readable. Can't read entry.");
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
let name = self.inode.get_entry(*offset)?;
|
||||
@ -149,12 +149,12 @@ impl File for INodeFile {
|
||||
}
|
||||
|
||||
impl INodeFile {
|
||||
pub fn open(inode: Arc<INode>, options: OpenOptions) -> Result<Self, Error> {
|
||||
pub fn open(inode: Arc<INode>, options: OpenOptions) -> Result<Self> {
|
||||
if (options.read && !inode.allow_read()?) {
|
||||
return errno!(EBADF, "File not readable");
|
||||
return_errno!(EBADF, "File not readable");
|
||||
}
|
||||
if (options.write && !inode.allow_write()?) {
|
||||
return errno!(EBADF, "File not writable");
|
||||
return_errno!(EBADF, "File not writable");
|
||||
}
|
||||
|
||||
Ok(INodeFile {
|
||||
@ -165,36 +165,6 @@ impl INodeFile {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert VFS Error to libc error code
|
||||
impl From<FsError> for Error {
|
||||
fn from(error: FsError) -> Self {
|
||||
let errno = match error {
|
||||
FsError::NotSupported => ENOSYS,
|
||||
FsError::NotFile => EISDIR,
|
||||
FsError::IsDir => EISDIR,
|
||||
FsError::NotDir => ENOTDIR,
|
||||
FsError::EntryNotFound => ENOENT,
|
||||
FsError::EntryExist => EEXIST,
|
||||
FsError::NotSameFs => EXDEV,
|
||||
FsError::InvalidParam => EINVAL,
|
||||
FsError::NoDeviceSpace => ENOMEM,
|
||||
FsError::DirRemoved => ENOENT,
|
||||
FsError::DirNotEmpty => ENOTEMPTY,
|
||||
FsError::WrongFs => EINVAL,
|
||||
FsError::DeviceError => EIO,
|
||||
FsError::SymLoop => ELOOP,
|
||||
FsError::NoDevice => ENXIO,
|
||||
FsError::IOCTLError => EINVAL,
|
||||
FsError::Again => EAGAIN,
|
||||
FsError::Busy => EBUSY,
|
||||
FsError::WrProtected => EROFS,
|
||||
FsError::NoIntegrity => EROFS,
|
||||
FsError::PermError => EPERM,
|
||||
};
|
||||
Error::new(errno, "")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for INodeFile {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
@ -207,13 +177,13 @@ impl Debug for INodeFile {
|
||||
}
|
||||
|
||||
pub trait INodeExt {
|
||||
fn read_as_vec(&self) -> Result<Vec<u8>, Error>;
|
||||
fn allow_write(&self) -> Result<bool, Error>;
|
||||
fn allow_read(&self) -> Result<bool, Error>;
|
||||
fn read_as_vec(&self) -> Result<Vec<u8>>;
|
||||
fn allow_write(&self) -> Result<bool>;
|
||||
fn allow_read(&self) -> Result<bool>;
|
||||
}
|
||||
|
||||
impl INodeExt for INode {
|
||||
fn read_as_vec(&self) -> Result<Vec<u8>, Error> {
|
||||
fn read_as_vec(&self) -> Result<Vec<u8>> {
|
||||
let size = self.metadata()?.size;
|
||||
let mut buf = Vec::with_capacity(size);
|
||||
unsafe {
|
||||
@ -223,14 +193,14 @@ impl INodeExt for INode {
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn allow_write(&self) -> Result<bool, Error> {
|
||||
fn allow_write(&self) -> Result<bool> {
|
||||
let info = self.metadata()?;
|
||||
let perms = info.mode as u32;
|
||||
let writable = (perms & S_IWUSR) == S_IWUSR;
|
||||
Ok(writable)
|
||||
}
|
||||
|
||||
fn allow_read(&self) -> Result<bool, Error> {
|
||||
fn allow_read(&self) -> Result<bool> {
|
||||
let info = self.metadata()?;
|
||||
let perms = info.mode as u32;
|
||||
let readable = (perms & S_IRUSR) == S_IRUSR;
|
||||
|
@ -13,7 +13,7 @@ pub fn do_select(
|
||||
writefds: &mut libc::fd_set,
|
||||
exceptfds: &mut libc::fd_set,
|
||||
timeout: Option<libc::timeval>,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<usize> {
|
||||
info!("select: nfds: {}", nfds);
|
||||
// convert libos fd to Linux fd
|
||||
let mut host_to_libos_fd = [0; libc::FD_SETSIZE];
|
||||
@ -108,7 +108,7 @@ pub fn do_select(
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize, Error> {
|
||||
pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize> {
|
||||
info!(
|
||||
"poll: {:?}, timeout: {}",
|
||||
polls.iter().map(|p| p.fd).collect::<Vec<_>>(),
|
||||
@ -143,7 +143,7 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize, Erro
|
||||
warn!("poll unix socket is unimplemented, spin for read");
|
||||
return Ok(1);
|
||||
} else {
|
||||
return errno!(EBADF, "not a socket");
|
||||
return_errno!(EBADF, "not a socket");
|
||||
}
|
||||
}
|
||||
let ret = try_libc!(libc::ocall::poll(
|
||||
@ -155,7 +155,7 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize, Erro
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
pub fn do_epoll_create1(flags: c_int) -> Result<FileDesc, Error> {
|
||||
pub fn do_epoll_create1(flags: c_int) -> Result<FileDesc> {
|
||||
info!("epoll_create1: flags: {}", flags);
|
||||
|
||||
let epoll = EpollFile::new()?;
|
||||
@ -177,7 +177,7 @@ pub fn do_epoll_ctl(
|
||||
op: c_int,
|
||||
fd: FileDesc,
|
||||
event: *const libc::epoll_event,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<()> {
|
||||
info!("epoll_ctl: epfd: {}, op: {:?}, fd: {}", epfd, op, fd);
|
||||
|
||||
let current_ref = process::get_current();
|
||||
@ -196,7 +196,7 @@ pub fn do_epoll_wait(
|
||||
epfd: FileDesc,
|
||||
events: &mut [libc::epoll_event],
|
||||
timeout: c_int,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<usize> {
|
||||
info!(
|
||||
"epoll_wait: epfd: {}, len: {:?}, timeout: {}",
|
||||
epfd,
|
||||
@ -245,7 +245,7 @@ pub struct EpollFile {
|
||||
}
|
||||
|
||||
impl EpollFile {
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
pub fn new() -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: SgxMutex::new(EpollFileInner::new()?),
|
||||
})
|
||||
@ -259,7 +259,7 @@ struct EpollFileInner {
|
||||
// FIXME: What if a Linux fd is closed but still in an epoll?
|
||||
impl EpollFileInner {
|
||||
/// Create a new Linux epoll file descriptor
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
pub fn new() -> Result<Self> {
|
||||
let ret = try_libc!(libc::ocall::epoll_create1(0));
|
||||
Ok(EpollFileInner { epoll_fd: ret })
|
||||
}
|
||||
@ -269,7 +269,7 @@ impl EpollFileInner {
|
||||
op: c_int,
|
||||
host_fd: FileDesc,
|
||||
event: *const libc::epoll_event,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<()> {
|
||||
let ret = try_libc!(libc::ocall::epoll_ctl(
|
||||
self.epoll_fd,
|
||||
op,
|
||||
@ -281,11 +281,7 @@ impl EpollFileInner {
|
||||
|
||||
/// Wait for an I/O event on the epoll.
|
||||
/// Returns the number of file descriptors ready for the requested I/O.
|
||||
pub fn wait(
|
||||
&mut self,
|
||||
events: &mut [libc::epoll_event],
|
||||
timeout: c_int,
|
||||
) -> Result<usize, Error> {
|
||||
pub fn wait(&mut self, events: &mut [libc::epoll_event], timeout: c_int) -> Result<usize> {
|
||||
let ret = try_libc!(libc::ocall::epoll_wait(
|
||||
self.epoll_fd,
|
||||
events.as_mut_ptr(),
|
||||
@ -305,51 +301,51 @@ impl Drop for EpollFileInner {
|
||||
}
|
||||
|
||||
impl File for EpollFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Epoll does not support seek")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Epoll does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -368,13 +364,13 @@ impl Debug for EpollFile {
|
||||
}
|
||||
|
||||
pub trait AsEpoll {
|
||||
fn as_epoll(&self) -> Result<&EpollFile, Error>;
|
||||
fn as_epoll(&self) -> Result<&EpollFile>;
|
||||
}
|
||||
|
||||
impl AsEpoll for FileRef {
|
||||
fn as_epoll(&self) -> Result<&EpollFile, Error> {
|
||||
fn as_epoll(&self) -> Result<&EpollFile> {
|
||||
self.as_any()
|
||||
.downcast_ref::<EpollFile>()
|
||||
.ok_or(Error::new(Errno::EBADF, "not a epoll"))
|
||||
.ok_or_else(|| errno!(EBADF, "not a epoll"))
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
use prelude::*;
|
||||
use super::*;
|
||||
|
||||
use process::Process;
|
||||
use rcore_fs::vfs::{FileType, FsError, INode, Metadata, Timespec};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::sgxfs as fs_impl;
|
||||
use {process, std};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub use self::access::{do_access, do_faccessat, AccessFlags, AccessModes, AT_FDCWD};
|
||||
use self::dev_null::DevNull;
|
||||
use self::dev_random::DevRandom;
|
||||
@ -38,7 +38,7 @@ mod sgx_impl;
|
||||
mod socket_file;
|
||||
mod unix_socket;
|
||||
|
||||
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc> {
|
||||
let flags = OpenFlags::from_bits_truncate(flags);
|
||||
info!(
|
||||
"open: path: {:?}, flags: {:?}, mode: {:#o}",
|
||||
@ -61,7 +61,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
Ok(fd)
|
||||
}
|
||||
|
||||
pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result<usize, Error> {
|
||||
pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result<usize> {
|
||||
info!("write: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -69,7 +69,7 @@ pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result<usize, Error> {
|
||||
file_ref.write(buf)
|
||||
}
|
||||
|
||||
pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
||||
info!("read: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -77,7 +77,7 @@ pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
file_ref.read(buf)
|
||||
}
|
||||
|
||||
pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result<usize> {
|
||||
info!("writev: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -85,7 +85,7 @@ pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
file_ref.writev(bufs)
|
||||
}
|
||||
|
||||
pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
info!("readv: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -93,7 +93,7 @@ pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
file_ref.readv(bufs)
|
||||
}
|
||||
|
||||
pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result<usize, Error> {
|
||||
pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result<usize> {
|
||||
info!("pwrite: fd: {}, offset: {}", fd, offset);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -101,7 +101,7 @@ pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result<usize, Error
|
||||
file_ref.write_at(offset, buf)
|
||||
}
|
||||
|
||||
pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result<usize, Error> {
|
||||
pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result<usize> {
|
||||
info!("pread: fd: {}, offset: {}", fd, offset);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -109,12 +109,12 @@ pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result<usize, Er
|
||||
file_ref.read_at(offset, buf)
|
||||
}
|
||||
|
||||
pub fn do_stat(path: &str) -> Result<Stat, Error> {
|
||||
pub fn do_stat(path: &str) -> Result<Stat> {
|
||||
warn!("stat is partial implemented as lstat");
|
||||
do_lstat(path)
|
||||
}
|
||||
|
||||
pub fn do_fstat(fd: u32) -> Result<Stat, Error> {
|
||||
pub fn do_fstat(fd: u32) -> Result<Stat> {
|
||||
info!("fstat: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -124,7 +124,7 @@ pub fn do_fstat(fd: u32) -> Result<Stat, Error> {
|
||||
Ok(stat)
|
||||
}
|
||||
|
||||
pub fn do_lstat(path: &str) -> Result<Stat, Error> {
|
||||
pub fn do_lstat(path: &str) -> Result<Stat> {
|
||||
info!("lstat: path: {}", path);
|
||||
|
||||
let current_ref = process::get_current();
|
||||
@ -134,14 +134,14 @@ pub fn do_lstat(path: &str) -> Result<Stat, Error> {
|
||||
Ok(stat)
|
||||
}
|
||||
|
||||
pub fn do_lseek(fd: FileDesc, offset: SeekFrom) -> Result<off_t, Error> {
|
||||
pub fn do_lseek(fd: FileDesc, offset: SeekFrom) -> Result<off_t> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().lock().unwrap().get(fd)?;
|
||||
file_ref.seek(offset)
|
||||
}
|
||||
|
||||
pub fn do_fsync(fd: FileDesc) -> Result<(), Error> {
|
||||
pub fn do_fsync(fd: FileDesc) -> Result<()> {
|
||||
info!("fsync: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -150,7 +150,7 @@ pub fn do_fsync(fd: FileDesc) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_fdatasync(fd: FileDesc) -> Result<(), Error> {
|
||||
pub fn do_fdatasync(fd: FileDesc) -> Result<()> {
|
||||
info!("fdatasync: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -159,7 +159,7 @@ pub fn do_fdatasync(fd: FileDesc) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_truncate(path: &str, len: usize) -> Result<(), Error> {
|
||||
pub fn do_truncate(path: &str, len: usize) -> Result<()> {
|
||||
info!("truncate: path: {:?}, len: {}", path, len);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -167,7 +167,7 @@ pub fn do_truncate(path: &str, len: usize) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<(), Error> {
|
||||
pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<()> {
|
||||
info!("ftruncate: fd: {}, len: {}", fd, len);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -176,7 +176,7 @@ pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result<usize> {
|
||||
info!(
|
||||
"getdents64: fd: {}, buf: {:?}, buf_size: {}",
|
||||
fd,
|
||||
@ -188,24 +188,30 @@ pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let file_ref = current_process.get_files().lock().unwrap().get(fd)?;
|
||||
let info = file_ref.metadata()?;
|
||||
if info.type_ != FileType::Dir {
|
||||
return errno!(ENOTDIR, "");
|
||||
return_errno!(ENOTDIR, "");
|
||||
}
|
||||
let mut writer = unsafe { DirentBufWriter::new(buf) };
|
||||
loop {
|
||||
let name = match file_ref.read_entry() {
|
||||
Err(e) if e.errno == ENOENT => break,
|
||||
r => r,
|
||||
}?;
|
||||
Err(e) => {
|
||||
let errno = e.errno();
|
||||
if errno == ENOENT {
|
||||
break;
|
||||
}
|
||||
return Err(e.cause_err(|_| errno!(errno, "failed to read entry")));
|
||||
}
|
||||
Ok(name) => name,
|
||||
};
|
||||
// TODO: get ino from dirent
|
||||
let ok = writer.try_write(0, 0, &name);
|
||||
if !ok {
|
||||
break;
|
||||
return_errno!(EINVAL, "the given buffer is too small");
|
||||
}
|
||||
}
|
||||
Ok(writer.written_size)
|
||||
}
|
||||
|
||||
pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
pub fn do_close(fd: FileDesc) -> Result<()> {
|
||||
info!("close: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -215,7 +221,7 @@ pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
|
||||
pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2]> {
|
||||
info!("pipe2: flags: {:#x}", flags);
|
||||
let flags = OpenFlags::from_bits_truncate(flags);
|
||||
let current_ref = process::get_current();
|
||||
@ -231,7 +237,7 @@ pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
|
||||
Ok([reader_fd, writer_fd])
|
||||
}
|
||||
|
||||
pub fn do_dup(old_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
pub fn do_dup(old_fd: FileDesc) -> Result<FileDesc> {
|
||||
let current_ref = process::get_current();
|
||||
let current = current_ref.lock().unwrap();
|
||||
let file_table_ref = current.get_files();
|
||||
@ -241,7 +247,7 @@ pub fn do_dup(old_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
||||
pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc> {
|
||||
let current_ref = process::get_current();
|
||||
let current = current_ref.lock().unwrap();
|
||||
let file_table_ref = current.get_files();
|
||||
@ -253,7 +259,7 @@ pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
||||
pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDesc, Error> {
|
||||
pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDesc> {
|
||||
let flags = OpenFlags::from_bits_truncate(flags);
|
||||
let current_ref = process::get_current();
|
||||
let current = current_ref.lock().unwrap();
|
||||
@ -261,20 +267,20 @@ pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDes
|
||||
let mut file_table = file_table_ref.lock().unwrap();
|
||||
let file = file_table.get(old_fd)?;
|
||||
if old_fd == new_fd {
|
||||
return errno!(EINVAL, "old_fd must not be equal to new_fd");
|
||||
return_errno!(EINVAL, "old_fd must not be equal to new_fd");
|
||||
}
|
||||
let close_on_spawn = flags.contains(OpenFlags::CLOEXEC);
|
||||
file_table.put_at(new_fd, file, close_on_spawn);
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
||||
pub fn do_sync() -> Result<(), Error> {
|
||||
pub fn do_sync() -> Result<()> {
|
||||
info!("sync:");
|
||||
ROOT_INODE.fs().sync()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_chdir(path: &str) -> Result<(), Error> {
|
||||
pub fn do_chdir(path: &str) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
info!("chdir: path: {:?}", path);
|
||||
@ -282,13 +288,13 @@ pub fn do_chdir(path: &str) -> Result<(), Error> {
|
||||
let inode = current_process.lookup_inode(path)?;
|
||||
let info = inode.metadata()?;
|
||||
if info.type_ != FileType::Dir {
|
||||
return errno!(ENOTDIR, "");
|
||||
return_errno!(ENOTDIR, "");
|
||||
}
|
||||
current_process.change_cwd(path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_rename(oldpath: &str, newpath: &str) -> Result<(), Error> {
|
||||
pub fn do_rename(oldpath: &str, newpath: &str) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath);
|
||||
@ -301,7 +307,7 @@ pub fn do_rename(oldpath: &str, newpath: &str) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_mkdir(path: &str, mode: usize) -> Result<(), Error> {
|
||||
pub fn do_mkdir(path: &str, mode: usize) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
// TODO: check pathname
|
||||
@ -310,16 +316,16 @@ pub fn do_mkdir(path: &str, mode: usize) -> Result<(), Error> {
|
||||
let (dir_path, file_name) = split_path(&path);
|
||||
let inode = current_process.lookup_inode(dir_path)?;
|
||||
if inode.find(file_name).is_ok() {
|
||||
return errno!(EEXIST, "");
|
||||
return_errno!(EEXIST, "");
|
||||
}
|
||||
if !inode.allow_write()? {
|
||||
return errno!(EPERM, "dir cannot be written");
|
||||
return_errno!(EPERM, "dir cannot be written");
|
||||
}
|
||||
inode.create(file_name, FileType::Dir, mode as u32)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_rmdir(path: &str) -> Result<(), Error> {
|
||||
pub fn do_rmdir(path: &str) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
info!("rmdir: path: {:?}", path);
|
||||
@ -328,13 +334,13 @@ pub fn do_rmdir(path: &str) -> Result<(), Error> {
|
||||
let dir_inode = current_process.lookup_inode(dir_path)?;
|
||||
let file_inode = dir_inode.find(file_name)?;
|
||||
if file_inode.metadata()?.type_ != FileType::Dir {
|
||||
return errno!(ENOTDIR, "rmdir on not directory");
|
||||
return_errno!(ENOTDIR, "rmdir on not directory");
|
||||
}
|
||||
dir_inode.unlink(file_name)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_link(oldpath: &str, newpath: &str) -> Result<(), Error> {
|
||||
pub fn do_link(oldpath: &str, newpath: &str) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
info!("link: oldpath: {:?}, newpath: {:?}", oldpath, newpath);
|
||||
@ -346,7 +352,7 @@ pub fn do_link(oldpath: &str, newpath: &str) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_unlink(path: &str) -> Result<(), Error> {
|
||||
pub fn do_unlink(path: &str) -> Result<()> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
info!("unlink: path: {:?}", path);
|
||||
@ -355,7 +361,7 @@ pub fn do_unlink(path: &str) -> Result<(), Error> {
|
||||
let dir_inode = current_process.lookup_inode(dir_path)?;
|
||||
let file_inode = dir_inode.find(file_name)?;
|
||||
if file_inode.metadata()?.type_ == FileType::Dir {
|
||||
return errno!(EISDIR, "unlink on directory");
|
||||
return_errno!(EISDIR, "unlink on directory");
|
||||
}
|
||||
dir_inode.unlink(file_name)?;
|
||||
Ok(())
|
||||
@ -366,7 +372,7 @@ pub fn do_sendfile(
|
||||
in_fd: FileDesc,
|
||||
offset: Option<off_t>,
|
||||
count: usize,
|
||||
) -> Result<(usize, usize), Error> {
|
||||
) -> Result<(usize, usize)> {
|
||||
// (len, offset)
|
||||
info!(
|
||||
"sendfile: out: {}, in: {}, offset: {:?}, count: {}",
|
||||
@ -400,7 +406,7 @@ pub fn do_sendfile(
|
||||
while bytes_written < read_len {
|
||||
let write_len = out_file.write(&buffer[bytes_written..])?;
|
||||
if write_len == 0 {
|
||||
return errno!(EBADF, "sendfile write return 0");
|
||||
return_errno!(EBADF, "sendfile write return 0");
|
||||
}
|
||||
bytes_written += write_len;
|
||||
}
|
||||
@ -418,7 +424,7 @@ extern "C" {
|
||||
|
||||
impl Process {
|
||||
/// Open a file on the process. But DO NOT add it to file table.
|
||||
pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result<Box<File>, Error> {
|
||||
pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result<Box<File>> {
|
||||
if path == "/dev/null" {
|
||||
return Ok(Box::new(DevNull));
|
||||
}
|
||||
@ -434,13 +440,13 @@ impl Process {
|
||||
match dir_inode.find(file_name) {
|
||||
Ok(file_inode) => {
|
||||
if flags.contains(OpenFlags::EXCLUSIVE) {
|
||||
return errno!(EEXIST, "file exists");
|
||||
return_errno!(EEXIST, "file exists");
|
||||
}
|
||||
file_inode
|
||||
}
|
||||
Err(FsError::EntryNotFound) => {
|
||||
if !dir_inode.allow_write()? {
|
||||
return errno!(EPERM, "file cannot be created");
|
||||
return_errno!(EPERM, "file cannot be created");
|
||||
}
|
||||
dir_inode.create(file_name, FileType::File, mode)?
|
||||
}
|
||||
@ -453,7 +459,7 @@ impl Process {
|
||||
}
|
||||
|
||||
/// Lookup INode from the cwd of the process
|
||||
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, Error> {
|
||||
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>> {
|
||||
debug!("lookup_inode: cwd: {:?}, path: {:?}", self.get_cwd(), path);
|
||||
if path.len() > 0 && path.as_bytes()[0] == b'/' {
|
||||
// absolute path
|
||||
@ -727,7 +733,7 @@ pub enum FcntlCmd {
|
||||
|
||||
impl FcntlCmd {
|
||||
#[deny(unreachable_patterns)]
|
||||
pub fn from_raw(cmd: u32, arg: u64) -> Result<FcntlCmd, Error> {
|
||||
pub fn from_raw(cmd: u32, arg: u64) -> Result<FcntlCmd> {
|
||||
Ok(match cmd as c_int {
|
||||
libc::F_DUPFD => FcntlCmd::DupFd(arg as FileDesc),
|
||||
libc::F_DUPFD_CLOEXEC => FcntlCmd::DupFdCloexec(arg as FileDesc),
|
||||
@ -735,12 +741,12 @@ impl FcntlCmd {
|
||||
libc::F_SETFD => FcntlCmd::SetFd(arg as u32),
|
||||
libc::F_GETFL => FcntlCmd::GetFl(),
|
||||
libc::F_SETFL => FcntlCmd::SetFl(arg as u32),
|
||||
_ => return errno!(EINVAL, "invalid command"),
|
||||
_ => return_errno!(EINVAL, "invalid command"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize, Error> {
|
||||
pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize> {
|
||||
info!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd);
|
||||
let current_ref = process::get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
@ -796,7 +802,7 @@ pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize, Error> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result<usize> {
|
||||
info!("readlink: path: {:?}", path);
|
||||
match path {
|
||||
"/proc/self/exe" => {
|
||||
@ -810,7 +816,7 @@ pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
}
|
||||
_ => {
|
||||
// TODO: support symbolic links
|
||||
errno!(EINVAL, "not a symbolic link")
|
||||
return_errno!(EINVAL, "not a symbolic link")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub struct Pipe {
|
||||
}
|
||||
|
||||
impl Pipe {
|
||||
pub fn new() -> Result<Pipe, Error> {
|
||||
pub fn new() -> Result<Pipe> {
|
||||
let mut ring_buf = RingBuf::new(PIPE_BUF_SIZE);
|
||||
Ok(Pipe {
|
||||
reader: PipeReader {
|
||||
@ -31,24 +31,24 @@ pub struct PipeReader {
|
||||
}
|
||||
|
||||
impl File for PipeReader {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let ringbuf = self.inner.lock().unwrap();
|
||||
ringbuf.read(buf)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "PipeReader does not support write")
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
return_errno!(EBADF, "PipeReader does not support write")
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut ringbuf = self.inner.lock().unwrap();
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -72,31 +72,31 @@ impl File for PipeReader {
|
||||
Ok(total_bytes)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "PipeReader does not support write")
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
return_errno!(EBADF, "PipeReader does not support write")
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Pipe does not support seek")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Pipe does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -114,27 +114,27 @@ pub struct PipeWriter {
|
||||
}
|
||||
|
||||
impl File for PipeWriter {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "PipeWriter does not support read")
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
return_errno!(EBADF, "PipeWriter does not support read")
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let ringbuf = self.inner.lock().unwrap();
|
||||
ringbuf.write(buf)
|
||||
}
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
errno!(EBADF, "PipeWriter does not support read")
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
return_errno!(EBADF, "PipeWriter does not support read")
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
let ringbuf = self.inner.lock().unwrap();
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
@ -158,27 +158,27 @@ impl File for PipeWriter {
|
||||
Ok(total_bytes)
|
||||
}
|
||||
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Pipe does not support seek")
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Pipe does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -13,34 +13,38 @@ use rcore_fs_sefs::SEFS;
|
||||
lazy_static! {
|
||||
/// The root of file system
|
||||
pub static ref ROOT_INODE: Arc<INode> = {
|
||||
fn init_root_inode() -> Result<Arc<INode>> {
|
||||
let mount_config = &config::LIBOS_CONFIG.mount;
|
||||
let root_inode = {
|
||||
let rootfs = open_root_fs_according_to(mount_config)?;
|
||||
rootfs.root_inode()
|
||||
};
|
||||
mount_nonroot_fs_according_to(mount_config, &root_inode)?;
|
||||
Ok(root_inode)
|
||||
}
|
||||
|
||||
let rootfs = open_root_fs_according_to(mount_config)
|
||||
.expect("failed to create or open SEFS for /");
|
||||
let root = rootfs.root_inode();
|
||||
|
||||
mount_nonroot_fs_according_to(mount_config, &root)
|
||||
.expect("failed to create or open other FS");
|
||||
|
||||
root
|
||||
init_root_inode().unwrap_or_else(|e| {
|
||||
error!("failed to init root inode: {}", e.backtrace());
|
||||
panic!();
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
fn open_root_fs_according_to(mount_config: &Vec<ConfigMount>) -> Result<Arc<MountFS>, Error> {
|
||||
fn open_root_fs_according_to(mount_config: &Vec<ConfigMount>) -> Result<Arc<MountFS>> {
|
||||
let (root_sefs_mac, root_sefs_source) = {
|
||||
let root_mount_config = mount_config
|
||||
.iter()
|
||||
.find(|m| m.target == Path::new("/"))
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "The mount point at / is not specified"))?;
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the mount point at / is not specified"))?;
|
||||
|
||||
if root_mount_config.type_ != ConfigMountFsType::TYPE_SEFS {
|
||||
return errno!(EINVAL, "The mount point at / must be SEFS");
|
||||
return_errno!(EINVAL, "The mount point at / must be SEFS");
|
||||
}
|
||||
if !root_mount_config.options.integrity_only {
|
||||
return errno!(EINVAL, "The root SEFS at / must be integrity-only");
|
||||
return_errno!(EINVAL, "The root SEFS at / must be integrity-only");
|
||||
}
|
||||
if root_mount_config.source.is_none() {
|
||||
return errno!(
|
||||
return_errno!(
|
||||
EINVAL,
|
||||
"The root SEFS must be given a source path (on host)"
|
||||
);
|
||||
@ -60,20 +64,17 @@ fn open_root_fs_according_to(mount_config: &Vec<ConfigMount>) -> Result<Arc<Moun
|
||||
Ok(root_mountable_sefs)
|
||||
}
|
||||
|
||||
fn mount_nonroot_fs_according_to(
|
||||
mount_config: &Vec<ConfigMount>,
|
||||
root: &MNode,
|
||||
) -> Result<(), Error> {
|
||||
fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode) -> Result<()> {
|
||||
for mc in mount_config {
|
||||
if mc.target == Path::new("/") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !mc.target.is_absolute() {
|
||||
return errno!(EINVAL, "The target path must be absolute");
|
||||
return_errno!(EINVAL, "The target path must be absolute");
|
||||
}
|
||||
if mc.target.parent().unwrap() != Path::new("/") {
|
||||
return errno!(EINVAL, "The target mount point must be under /");
|
||||
return_errno!(EINVAL, "The target mount point must be under /");
|
||||
}
|
||||
let target_dirname = mc.target.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
@ -81,10 +82,10 @@ fn mount_nonroot_fs_according_to(
|
||||
match mc.type_ {
|
||||
TYPE_SEFS => {
|
||||
if mc.options.integrity_only {
|
||||
return errno!(EINVAL, "Cannot mount integrity-only SEFS at non-root path");
|
||||
return_errno!(EINVAL, "Cannot mount integrity-only SEFS at non-root path");
|
||||
}
|
||||
if mc.source.is_none() {
|
||||
return errno!(EINVAL, "Source is expected for SEFS");
|
||||
return_errno!(EINVAL, "Source is expected for SEFS");
|
||||
}
|
||||
let source_path = mc.source.as_ref().unwrap();
|
||||
let sefs = {
|
||||
@ -105,7 +106,7 @@ fn mount_nonroot_fs_according_to(
|
||||
}
|
||||
TYPE_HOSTFS => {
|
||||
if mc.source.is_none() {
|
||||
return errno!(EINVAL, "Source is expected for HostFS");
|
||||
return_errno!(EINVAL, "Source is expected for HostFS");
|
||||
}
|
||||
let source_path = mc.source.as_ref().unwrap();
|
||||
|
||||
@ -121,15 +122,15 @@ fn mount_nonroot_fs_according_to(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount_fs_at(fs: Arc<dyn FileSystem>, parent_inode: &MNode, dirname: &str) -> Result<(), Error> {
|
||||
fn mount_fs_at(fs: Arc<dyn FileSystem>, parent_inode: &MNode, dirname: &str) -> Result<()> {
|
||||
let mount_dir = match parent_inode.find(false, dirname) {
|
||||
Ok(existing_dir) => {
|
||||
if existing_dir.metadata()?.type_ != FileType::Dir {
|
||||
return errno!(EIO, "not a directory");
|
||||
return_errno!(EIO, "not a directory");
|
||||
}
|
||||
existing_dir
|
||||
}
|
||||
Err(_) => return errno!(ENOENT, "Mount point does not exist"),
|
||||
Err(_) => return_errno!(ENOENT, "Mount point does not exist"),
|
||||
};
|
||||
mount_dir.mount(fs);
|
||||
Ok(())
|
||||
|
@ -129,8 +129,8 @@ impl Storage for SgxStorage {
|
||||
if file_id == "metadata" && self.root_mac.is_some() {
|
||||
let root_file_mac = file.get_mac().expect("Failed to get mac");
|
||||
if root_file_mac != self.root_mac.unwrap() {
|
||||
println!(
|
||||
"Expected MAC = {:#?}, actual MAC = {:?}",
|
||||
error!(
|
||||
"MAC validation for metadata file failed: expected = {:#?}, found = {:?}",
|
||||
self.root_mac.unwrap(),
|
||||
root_file_mac
|
||||
);
|
||||
|
@ -8,7 +8,7 @@ pub struct SocketFile {
|
||||
}
|
||||
|
||||
impl SocketFile {
|
||||
pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<Self> {
|
||||
let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol));
|
||||
Ok(SocketFile { fd: ret })
|
||||
}
|
||||
@ -18,7 +18,7 @@ impl SocketFile {
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
flags: c_int,
|
||||
) -> Result<Self, Error> {
|
||||
) -> Result<Self> {
|
||||
let ret = try_libc!(libc::ocall::accept4(self.fd, addr, addr_len, flags));
|
||||
Ok(SocketFile { fd: ret })
|
||||
}
|
||||
@ -42,7 +42,7 @@ impl Drop for SocketFile {
|
||||
}
|
||||
|
||||
impl File for SocketFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let ret = try_libc!(libc::ocall::read(
|
||||
self.fd,
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
@ -51,7 +51,7 @@ impl File for SocketFile {
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let ret = try_libc!(libc::ocall::write(
|
||||
self.fd,
|
||||
buf.as_ptr() as *const c_void,
|
||||
@ -60,15 +60,15 @@ impl File for SocketFile {
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
self.read(buf)
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
self.write(buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
match self.read(buf) {
|
||||
@ -82,7 +82,7 @@ impl File for SocketFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
match self.write(buf) {
|
||||
@ -96,11 +96,11 @@ impl File for SocketFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "Socket does not support seek")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "Socket does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
@ -119,19 +119,19 @@ impl File for SocketFile {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -141,13 +141,13 @@ impl File for SocketFile {
|
||||
}
|
||||
|
||||
pub trait AsSocket {
|
||||
fn as_socket(&self) -> Result<&SocketFile, Error>;
|
||||
fn as_socket(&self) -> Result<&SocketFile>;
|
||||
}
|
||||
|
||||
impl AsSocket for FileRef {
|
||||
fn as_socket(&self) -> Result<&SocketFile, Error> {
|
||||
fn as_socket(&self) -> Result<&SocketFile> {
|
||||
self.as_any()
|
||||
.downcast_ref::<SocketFile>()
|
||||
.ok_or(Error::new(Errno::EBADF, "not a socket"))
|
||||
.ok_or_else(|| errno!(EBADF, "not a socket"))
|
||||
}
|
||||
}
|
||||
|
@ -11,25 +11,25 @@ pub struct UnixSocketFile {
|
||||
}
|
||||
|
||||
impl File for UnixSocketFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.read(buf)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.write(buf)
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
self.read(buf)
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
self.write(buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
@ -44,7 +44,7 @@ impl File for UnixSocketFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
@ -59,11 +59,11 @@ impl File for UnixSocketFile {
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "UnixSocket does not support seek")
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t> {
|
||||
return_errno!(ESPIPE, "UnixSocket does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
fn metadata(&self) -> Result<Metadata> {
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
@ -82,19 +82,19 @@ impl File for UnixSocketFile {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
fn set_len(&self, len: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
fn sync_all(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
fn sync_data(&self) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
fn read_entry(&self) -> Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -104,24 +104,24 @@ impl File for UnixSocketFile {
|
||||
}
|
||||
|
||||
impl UnixSocketFile {
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self> {
|
||||
let inner = UnixSocket::new(socket_type, protocol)?;
|
||||
Ok(UnixSocketFile {
|
||||
inner: Mutex::new(inner),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn bind(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
pub fn bind(&self, path: impl AsRef<str>) -> Result<()> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.bind(path)
|
||||
}
|
||||
|
||||
pub fn listen(&self) -> Result<(), Error> {
|
||||
pub fn listen(&self) -> Result<()> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.listen()
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> Result<UnixSocketFile, Error> {
|
||||
pub fn accept(&self) -> Result<UnixSocketFile> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let new_socket = inner.accept()?;
|
||||
Ok(UnixSocketFile {
|
||||
@ -129,17 +129,17 @@ impl UnixSocketFile {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connect(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
pub fn connect(&self, path: impl AsRef<str>) -> Result<()> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.connect(path)
|
||||
}
|
||||
|
||||
pub fn poll(&self) -> Result<(bool, bool, bool), Error> {
|
||||
pub fn poll(&self) -> Result<(bool, bool, bool)> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.poll()
|
||||
}
|
||||
|
||||
pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<(), Error> {
|
||||
pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<()> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.ioctl(cmd, argp)
|
||||
}
|
||||
@ -152,14 +152,14 @@ impl Debug for UnixSocketFile {
|
||||
}
|
||||
|
||||
pub trait AsUnixSocket {
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error>;
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile>;
|
||||
}
|
||||
|
||||
impl AsUnixSocket for FileRef {
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error> {
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile> {
|
||||
self.as_any()
|
||||
.downcast_ref::<UnixSocketFile>()
|
||||
.ok_or(Error::new(Errno::EBADF, "not a unix socket"))
|
||||
.ok_or_else(|| errno!(EBADF, "not a unix socket"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,38 +176,38 @@ enum Status {
|
||||
|
||||
impl UnixSocket {
|
||||
/// C/S 1: Create a new unix socket
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self> {
|
||||
if socket_type == libc::SOCK_STREAM && protocol == 0 {
|
||||
Ok(UnixSocket {
|
||||
obj: None,
|
||||
status: Status::None,
|
||||
})
|
||||
} else {
|
||||
errno!(ENOSYS, "unimplemented unix socket type")
|
||||
return_errno!(ENOSYS, "unimplemented unix socket type")
|
||||
}
|
||||
}
|
||||
|
||||
/// Server 2: Bind the socket to a file system path
|
||||
pub fn bind(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
pub fn bind(&mut self, path: impl AsRef<str>) -> Result<()> {
|
||||
// TODO: check permission
|
||||
if self.obj.is_some() {
|
||||
return errno!(EINVAL, "The socket is already bound to an address.");
|
||||
return_errno!(EINVAL, "The socket is already bound to an address.");
|
||||
}
|
||||
self.obj = Some(UnixSocketObject::create(path)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Server 3: Listen to a socket
|
||||
pub fn listen(&mut self) -> Result<(), Error> {
|
||||
pub fn listen(&mut self) -> Result<()> {
|
||||
self.status = Status::Listening;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Server 4: Accept a connection on listening.
|
||||
pub fn accept(&mut self) -> Result<UnixSocket, Error> {
|
||||
pub fn accept(&mut self) -> Result<UnixSocket> {
|
||||
match self.status {
|
||||
Status::Listening => {}
|
||||
_ => return errno!(EINVAL, "unix socket is not listening"),
|
||||
_ => return_errno!(EINVAL, "unix socket is not listening"),
|
||||
};
|
||||
// FIXME: Block. Now spin loop.
|
||||
let socket = loop {
|
||||
@ -220,12 +220,12 @@ impl UnixSocket {
|
||||
}
|
||||
|
||||
/// Client 2: Connect to a path
|
||||
pub fn connect(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
pub fn connect(&mut self, path: impl AsRef<str>) -> Result<()> {
|
||||
if let Status::Listening = self.status {
|
||||
return errno!(EINVAL, "unix socket is listening?");
|
||||
return_errno!(EINVAL, "unix socket is listening?");
|
||||
}
|
||||
let obj =
|
||||
UnixSocketObject::get(path).ok_or(Error::new(EINVAL, "unix socket path not found"))?;
|
||||
let obj = UnixSocketObject::get(path)
|
||||
.ok_or_else(|| errno!(EINVAL, "unix socket path not found"))?;
|
||||
let (channel1, channel2) = Channel::new_pair();
|
||||
self.status = Status::Connected(channel1);
|
||||
obj.push(UnixSocket {
|
||||
@ -235,15 +235,15 @@ impl UnixSocket {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.channel()?.reader.read(buf)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
self.channel()?.writer.write(buf)
|
||||
}
|
||||
|
||||
pub fn poll(&self) -> Result<(bool, bool, bool), Error> {
|
||||
pub fn poll(&self) -> Result<(bool, bool, bool)> {
|
||||
// (read, write, error)
|
||||
let channel = self.channel()?;
|
||||
let r = channel.reader.can_read();
|
||||
@ -251,7 +251,7 @@ impl UnixSocket {
|
||||
Ok((r, w, false))
|
||||
}
|
||||
|
||||
pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<(), Error> {
|
||||
pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<()> {
|
||||
const FIONREAD: c_int = 0x541B; // Get the number of bytes to read
|
||||
if cmd == FIONREAD {
|
||||
let bytes_to_read = self.channel()?.reader.bytes_to_read();
|
||||
@ -261,15 +261,15 @@ impl UnixSocket {
|
||||
Ok(())
|
||||
} else {
|
||||
warn!("ioctl for unix socket is unimplemented");
|
||||
errno!(ENOSYS, "ioctl for unix socket is unimplemented")
|
||||
return_errno!(ENOSYS, "ioctl for unix socket is unimplemented")
|
||||
}
|
||||
}
|
||||
|
||||
fn channel(&self) -> Result<&Channel, Error> {
|
||||
fn channel(&self) -> Result<&Channel> {
|
||||
if let Status::Connected(channel) = &self.status {
|
||||
Ok(channel)
|
||||
} else {
|
||||
errno!(EBADF, "UnixSocket is not connected")
|
||||
return_errno!(EBADF, "UnixSocket is not connected")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -301,10 +301,10 @@ impl UnixSocketObject {
|
||||
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||
paths.get(path.as_ref()).map(|obj| obj.clone())
|
||||
}
|
||||
fn create(path: impl AsRef<str>) -> Result<Arc<Self>, Error> {
|
||||
fn create(path: impl AsRef<str>) -> Result<Arc<Self>> {
|
||||
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||
if paths.contains_key(path.as_ref()) {
|
||||
return errno!(EADDRINUSE, "unix socket path already exists");
|
||||
return_errno!(EADDRINUSE, "unix socket path already exists");
|
||||
}
|
||||
let obj = Arc::new(UnixSocketObject {
|
||||
path: path.as_ref().to_string(),
|
||||
|
@ -37,11 +37,18 @@ use std::backtrace::{self, PrintFormat};
|
||||
use std::ffi::CStr; // a borrowed C string
|
||||
use std::panic;
|
||||
|
||||
use error::*;
|
||||
use prelude::*;
|
||||
|
||||
// Override prelude::Result with error::Result
|
||||
use error::Result;
|
||||
|
||||
#[macro_use]
|
||||
mod prelude;
|
||||
#[macro_use]
|
||||
mod error;
|
||||
mod config;
|
||||
mod entry;
|
||||
mod errno;
|
||||
mod exception;
|
||||
mod fs;
|
||||
mod misc;
|
||||
@ -51,8 +58,6 @@ mod time;
|
||||
mod util;
|
||||
mod vm;
|
||||
|
||||
use prelude::*;
|
||||
|
||||
// Export system calls
|
||||
pub use syscall::*;
|
||||
// Export ECalls
|
||||
|
@ -65,7 +65,7 @@ pub enum resource_t {
|
||||
const RLIMIT_COUNT: usize = 15;
|
||||
|
||||
impl resource_t {
|
||||
pub fn from_u32(bits: u32) -> Result<resource_t, Error> {
|
||||
pub fn from_u32(bits: u32) -> Result<resource_t> {
|
||||
match bits {
|
||||
0 => Ok(resource_t::RLIMIT_CPU),
|
||||
1 => Ok(resource_t::RLIMIT_FSIZE),
|
||||
@ -82,7 +82,7 @@ impl resource_t {
|
||||
12 => Ok(resource_t::RLIMIT_MSGQUEUE),
|
||||
13 => Ok(resource_t::RLIMIT_NICE),
|
||||
14 => Ok(resource_t::RLIMIT_RTPRIO),
|
||||
_ => errno!(EINVAL, "invalid resource"),
|
||||
_ => return_errno!(EINVAL, "invalid resource"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,11 +92,11 @@ pub fn do_prlimit(
|
||||
resource: resource_t,
|
||||
new_limit: Option<&rlimit_t>,
|
||||
old_limit: Option<&mut rlimit_t>,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<()> {
|
||||
let process_ref = if pid == 0 {
|
||||
process::get_current()
|
||||
} else {
|
||||
process::get(pid)?
|
||||
process::get(pid).cause_err(|_| errno!(ESRCH, "invalid pid"))?
|
||||
};
|
||||
let mut process = process_ref.lock().unwrap();
|
||||
let rlimits_ref = process.get_rlimits();
|
||||
@ -110,10 +110,10 @@ pub fn do_prlimit(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<(), Error> {
|
||||
pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<()> {
|
||||
do_prlimit(0 as pid_t, resource, None, Some(old_limit))
|
||||
}
|
||||
|
||||
pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<(), Error> {
|
||||
pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<()> {
|
||||
do_prlimit(0 as pid_t, resource, Some(new_limit), None)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ pub struct utsname_t {
|
||||
domainname: [u8; 65],
|
||||
}
|
||||
|
||||
pub fn do_uname(name: &mut utsname_t) -> Result<(), Error> {
|
||||
pub fn do_uname(name: &mut utsname_t) -> Result<()> {
|
||||
copy_from_cstr_to_u8_array(&SYSNAME, &mut name.sysname);
|
||||
copy_from_cstr_to_u8_array(&NODENAME, &mut name.nodename);
|
||||
copy_from_cstr_to_u8_array(&RELEASE, &mut name.release);
|
||||
|
@ -1,32 +1,16 @@
|
||||
pub use sgx_trts::libc;
|
||||
pub use sgx_trts::libc::off_t;
|
||||
pub use sgx_types::*;
|
||||
|
||||
use std;
|
||||
|
||||
//pub use {elf_helper, errno, file, file_table, fs, mm, process, syscall, vma, };
|
||||
|
||||
pub use std::cell::{Cell, RefCell};
|
||||
pub use std::marker::{Send, Sync};
|
||||
pub use std::result::Result;
|
||||
pub use std::cmp::{max, min};
|
||||
pub use std::collections::{HashMap, VecDeque};
|
||||
pub use std::fmt::{Debug, Display};
|
||||
pub use std::prelude::v1::*;
|
||||
pub use std::sync::{
|
||||
Arc, SgxMutex, SgxMutexGuard, SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard,
|
||||
};
|
||||
//pub use std::borrow::BorrowMut;
|
||||
pub use std::borrow::ToOwned;
|
||||
pub use std::boxed::Box;
|
||||
pub use std::cmp::{max, min};
|
||||
pub use std::cmp::{Ordering, PartialOrd};
|
||||
pub use std::collections::{HashMap, VecDeque};
|
||||
pub use std::fmt::{Debug, Display};
|
||||
pub use std::io::{Read, Seek, SeekFrom, Write};
|
||||
pub use std::iter::Iterator;
|
||||
pub use std::rc::Rc;
|
||||
pub use std::string::{String, ToString};
|
||||
pub use std::vec::Vec;
|
||||
|
||||
pub use errno::Errno;
|
||||
pub use errno::Errno::*;
|
||||
pub use errno::Error;
|
||||
|
||||
macro_rules! debug_trace {
|
||||
() => {
|
||||
@ -34,38 +18,6 @@ macro_rules! debug_trace {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! errno {
|
||||
($errno: ident, $msg: expr) => {{
|
||||
error!(
|
||||
"ERROR: {} ({}, line {} in file {})",
|
||||
$errno,
|
||||
$msg,
|
||||
line!(),
|
||||
file!()
|
||||
);
|
||||
Err(Error::new($errno, $msg))
|
||||
}};
|
||||
}
|
||||
|
||||
// return Err(errno) if libc return -1
|
||||
macro_rules! try_libc {
|
||||
($ret: expr) => {{
|
||||
let ret = unsafe { $ret };
|
||||
if ret == -1 {
|
||||
let errno = unsafe { libc::errno() };
|
||||
// println will cause libc ocall and overwrite errno
|
||||
error!(
|
||||
"ERROR from libc: {} (line {} in file {})",
|
||||
errno,
|
||||
line!(),
|
||||
file!()
|
||||
);
|
||||
return Err(Error::new(Errno::from_errno(errno), "libc error"));
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||
debug_assert!(align != 0 && align.is_power_of_two());
|
||||
align_down(addr + (align - 1), align)
|
||||
|
@ -10,18 +10,18 @@ pub enum ArchPrctlCode {
|
||||
}
|
||||
|
||||
impl ArchPrctlCode {
|
||||
pub fn from_u32(bits: u32) -> Result<ArchPrctlCode, Error> {
|
||||
pub fn from_u32(bits: u32) -> Result<ArchPrctlCode> {
|
||||
match bits {
|
||||
0x1001 => Ok(ArchPrctlCode::ARCH_SET_GS),
|
||||
0x1002 => Ok(ArchPrctlCode::ARCH_SET_FS),
|
||||
0x1003 => Ok(ArchPrctlCode::ARCH_GET_FS),
|
||||
0x1004 => Ok(ArchPrctlCode::ARCH_GET_GS),
|
||||
_ => errno!(EINVAL, "Unknown code for arch_prctl"),
|
||||
_ => return_errno!(EINVAL, "Unknown code for arch_prctl"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<(), Error> {
|
||||
pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<()> {
|
||||
info!(
|
||||
"do_arch_prctl: code: {:?}, addr: {:#o}",
|
||||
code, addr as usize
|
||||
@ -42,7 +42,7 @@ pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<(), Error>
|
||||
}
|
||||
}
|
||||
ArchPrctlCode::ARCH_SET_GS | ArchPrctlCode::ARCH_GET_GS => {
|
||||
return errno!(EINVAL, "GS cannot be accessed from the user space");
|
||||
return_errno!(EINVAL, "GS cannot be accessed from the user space");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -64,7 +64,7 @@ pub fn do_exit(exit_status: i32) {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result<pid_t, Error> {
|
||||
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result<pid_t> {
|
||||
let current_ref = get_current();
|
||||
let waiter = {
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
@ -91,7 +91,7 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res
|
||||
any_child_to_wait_for = true;
|
||||
}
|
||||
if !any_child_to_wait_for {
|
||||
return errno!(ECHILD, "No such child");
|
||||
return_errno!(ECHILD, "No such child");
|
||||
}
|
||||
|
||||
let waiter = Waiter::new(child_filter);
|
||||
|
@ -21,7 +21,7 @@ pub enum FutexOp {
|
||||
const FUTEX_OP_MASK: u32 = 0x0000_000F;
|
||||
|
||||
impl FutexOp {
|
||||
pub fn from_u32(bits: u32) -> Result<FutexOp, Error> {
|
||||
pub fn from_u32(bits: u32) -> Result<FutexOp> {
|
||||
match bits {
|
||||
0 => Ok(FutexOp::FUTEX_WAIT),
|
||||
1 => Ok(FutexOp::FUTEX_WAKE),
|
||||
@ -33,7 +33,7 @@ impl FutexOp {
|
||||
7 => Ok(FutexOp::FUTEX_UNLOCK_PI),
|
||||
8 => Ok(FutexOp::FUTEX_TRYLOCK_PI),
|
||||
9 => Ok(FutexOp::FUTEX_WAIT_BITSET),
|
||||
_ => errno!(EINVAL, "Unknown futex op"),
|
||||
_ => return_errno!(EINVAL, "Unknown futex op"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,12 +47,12 @@ bitflags! {
|
||||
const FUTEX_FLAGS_MASK: u32 = 0xFFFF_FFF0;
|
||||
|
||||
impl FutexFlags {
|
||||
pub fn from_u32(bits: u32) -> Result<FutexFlags, Error> {
|
||||
FutexFlags::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "Unknown futex flags"))
|
||||
pub fn from_u32(bits: u32) -> Result<FutexFlags> {
|
||||
FutexFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown futex flags"))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags), Error> {
|
||||
pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags)> {
|
||||
let op = {
|
||||
let op_bits = bits & FUTEX_OP_MASK;
|
||||
FutexOp::from_u32(op_bits)?
|
||||
@ -65,7 +65,7 @@ pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags), E
|
||||
}
|
||||
|
||||
/// Do futex wait
|
||||
pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<(), Error> {
|
||||
pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<()> {
|
||||
let futex_key = FutexKey::new(futex_addr);
|
||||
let futex_item = FUTEX_TABLE.lock().unwrap().get_or_new_item(futex_key);
|
||||
|
||||
@ -76,7 +76,7 @@ pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
/// Do futex wake
|
||||
pub fn futex_wake(futex_addr: *const i32, max_count: usize) -> Result<usize, Error> {
|
||||
pub fn futex_wake(futex_addr: *const i32, max_count: usize) -> Result<usize> {
|
||||
let futex_key = FutexKey::new(futex_addr);
|
||||
let futex_item = FUTEX_TABLE.lock().unwrap().get_item(futex_key)?;
|
||||
let count = futex_item.wake(max_count);
|
||||
@ -167,12 +167,12 @@ impl FutexTable {
|
||||
item.clone()
|
||||
}
|
||||
|
||||
pub fn get_item(&mut self, key: FutexKey) -> Result<FutexItemRef, Error> {
|
||||
pub fn get_item(&mut self, key: FutexKey) -> Result<FutexItemRef> {
|
||||
let table = &mut self.table;
|
||||
table
|
||||
.get_mut(&key)
|
||||
.map(|item| item.clone())
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "futex key cannot be found"))
|
||||
.ok_or_else(|| errno!(ENOENT, "futex key cannot be found"))
|
||||
}
|
||||
|
||||
pub fn put_item(&mut self, item: FutexItemRef) {
|
||||
|
@ -33,7 +33,7 @@ impl Process {
|
||||
vm_ref: ProcessVMRef,
|
||||
file_table_ref: FileTableRef,
|
||||
rlimits_ref: ResourceLimitsRef,
|
||||
) -> Result<(pid_t, ProcessRef), Error> {
|
||||
) -> Result<(pid_t, ProcessRef)> {
|
||||
let new_pid = process_table::alloc_pid();
|
||||
let new_process_ref = Arc::new(SgxMutex::new(Process {
|
||||
task: task,
|
||||
|
@ -14,13 +14,13 @@ pub fn remove(pid: pid_t) {
|
||||
PROCESS_TABLE.lock().unwrap().remove(&pid);
|
||||
}
|
||||
|
||||
pub fn get(pid: pid_t) -> Result<ProcessRef, Error> {
|
||||
pub fn get(pid: pid_t) -> Result<ProcessRef> {
|
||||
PROCESS_TABLE
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&pid)
|
||||
.map(|pr| pr.clone())
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "process not found"))
|
||||
.ok_or_else(|| errno!(ENOENT, "process not found"))
|
||||
}
|
||||
|
||||
static NEXT_PID: AtomicU32 = AtomicU32::new(1);
|
||||
|
@ -61,7 +61,7 @@ impl CpuSet {
|
||||
}
|
||||
|
||||
impl std::fmt::LowerHex for CpuSet {
|
||||
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
for byte in &(self.vec) {
|
||||
try!(fmtr.write_fmt(format_args!("{:02x}", byte)));
|
||||
}
|
||||
@ -70,7 +70,7 @@ impl std::fmt::LowerHex for CpuSet {
|
||||
}
|
||||
|
||||
impl std::fmt::UpperHex for CpuSet {
|
||||
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
for byte in &(self.vec) {
|
||||
try!(fmtr.write_fmt(format_args!("{:02X}", byte)));
|
||||
}
|
||||
@ -78,14 +78,14 @@ impl std::fmt::UpperHex for CpuSet {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_host_tid(pid: pid_t) -> Result<pid_t, Error> {
|
||||
fn find_host_tid(pid: pid_t) -> Result<pid_t> {
|
||||
let process_ref = if pid == 0 { get_current() } else { get(pid)? };
|
||||
let mut process = process_ref.lock().unwrap();
|
||||
let host_tid = process.get_host_tid();
|
||||
Ok(host_tid)
|
||||
}
|
||||
|
||||
pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result<i32, Error> {
|
||||
pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result<i32> {
|
||||
let host_tid = match pid {
|
||||
0 => 0,
|
||||
_ => find_host_tid(pid)?,
|
||||
@ -98,13 +98,13 @@ pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result<i32, Err
|
||||
ocall_sched_getaffinity(&mut ret, &mut error, host_tid as i32, cpusize, buf);
|
||||
}
|
||||
if (ret < 0) {
|
||||
let errno = Errno::from_errno(error);
|
||||
return errno!(errno, "ocall_sched_getaffinity failed");
|
||||
let errno = Errno::from(error as u32);
|
||||
return_errno!(errno, "ocall_sched_getaffinity failed");
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result<i32, Error> {
|
||||
pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result<i32> {
|
||||
let host_tid = match pid {
|
||||
0 => 0,
|
||||
_ => find_host_tid(pid)?,
|
||||
@ -117,8 +117,8 @@ pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result<i32, Error>
|
||||
ocall_sched_setaffinity(&mut ret, &mut error, host_tid as i32, cpusize, buf);
|
||||
}
|
||||
if (ret < 0) {
|
||||
let errno = Errno::from_errno(error);
|
||||
return errno!(errno, "ocall_sched_setaffinity failed");
|
||||
let errno = Errno::from(error as u32);
|
||||
return_errno!(errno, "ocall_sched_setaffinity failed");
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ pub struct ProgramHeaderInfo {
|
||||
pub entry_num: usize,
|
||||
}
|
||||
|
||||
pub fn get_program_header_info(elf_file: &ElfFile) -> Result<ProgramHeaderInfo, Error> {
|
||||
pub fn get_program_header_info(elf_file: &ElfFile) -> Result<ProgramHeaderInfo> {
|
||||
let elf_header = &elf_file.header.pt2;
|
||||
Ok(ProgramHeaderInfo {
|
||||
addr: elf_header.ph_offset() as usize,
|
||||
@ -22,37 +22,37 @@ pub fn get_program_header_info(elf_file: &ElfFile) -> Result<ProgramHeaderInfo,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
pub fn print_program_headers(elf_file: &ElfFile) -> Result<()> {
|
||||
println!("Program headers:");
|
||||
let ph_iter = elf_file.program_iter();
|
||||
for sect in ph_iter {
|
||||
program::sanity_check(sect, &elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "sanity check for program header failed"))?;
|
||||
println!("\t{:?}", sect.get_type());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
pub fn print_sections(elf_file: &ElfFile) -> Result<()> {
|
||||
println!("Sections:");
|
||||
let mut sect_iter = elf_file.section_iter();
|
||||
sect_iter.next(); // Skip the first, dummy section
|
||||
for sect in sect_iter {
|
||||
sections::sanity_check(sect, &elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "sanity check for program header failed"))?;
|
||||
let sec_name = sect
|
||||
.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get section name"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get section name"))?;
|
||||
println!("\t{}\n{:?}", sec_name, sect);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<()> {
|
||||
let rela_entries = get_rela_entries(elf_file, ".rela.plt")
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get .pltrel entries"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get .pltrel entries"))?;
|
||||
let dynsym_entries = get_dynsym_entries(elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get .dynsym entries"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get .dynsym entries"))?;
|
||||
|
||||
println!(".rela.plt section:");
|
||||
for entry in rela_entries {
|
||||
@ -68,15 +68,13 @@ pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
let dynsym_entry = &dynsym_entries[symidx];
|
||||
let dynsym_name = dynsym_entry
|
||||
.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get the name of a dynamic symbol"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get the name of a dynamic symbol"))?;
|
||||
println!("\t\t{} = {:?}", dynsym_name, dynsym_entry);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_data_program_header<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<ProgramHeader<'a>, Error> {
|
||||
pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<ProgramHeader<'a>> {
|
||||
let mut ph_iter = elf_file.program_iter();
|
||||
ph_iter
|
||||
.find(|&ph| {
|
||||
@ -85,12 +83,10 @@ pub fn get_data_program_header<'b, 'a: 'b>(
|
||||
&& ph.flags().is_write()
|
||||
&& ph.flags().is_read()
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get the data segment").into())
|
||||
.ok_or_else(|| errno!(ENOEXEC, "failed to get the data segment"))
|
||||
}
|
||||
|
||||
pub fn get_code_program_header<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<ProgramHeader<'a>, Error> {
|
||||
pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<ProgramHeader<'a>> {
|
||||
let mut ph_iter = elf_file.program_iter();
|
||||
ph_iter
|
||||
.find(|&ph| {
|
||||
@ -99,15 +95,15 @@ pub fn get_code_program_header<'b, 'a: 'b>(
|
||||
&& !ph.flags().is_write()
|
||||
&& ph.flags().is_read()
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get the code segment").into())
|
||||
.ok_or_else(|| errno!(ENOEXEC, "failed to get the code segment"))
|
||||
}
|
||||
|
||||
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<usize, Error> {
|
||||
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<usize> {
|
||||
let elf_header = &elf_file.header.pt2;
|
||||
Ok(elf_header.entry_point() as usize)
|
||||
}
|
||||
|
||||
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64], Error> {
|
||||
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64]> {
|
||||
elf_file
|
||||
.find_section_by_name(".symtab")
|
||||
.and_then(|symtab_section| symtab_section.get_data(&elf_file).ok())
|
||||
@ -115,13 +111,13 @@ pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Ent
|
||||
sections::SectionData::SymbolTable64(entries) => Some(entries),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into())
|
||||
.ok_or_else(|| errno!(ENOEXEC, "failed get the symbol entries"))
|
||||
}
|
||||
|
||||
pub fn get_rela_entries<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
sec_name: &'b str,
|
||||
) -> Result<&'a [Rela<P64>], Error> {
|
||||
) -> Result<&'a [Rela<P64>]> {
|
||||
elf_file
|
||||
.find_section_by_name(sec_name)
|
||||
.and_then(|plt_rela_section| plt_rela_section.get_data(&elf_file).ok())
|
||||
@ -129,12 +125,10 @@ pub fn get_rela_entries<'b, 'a: 'b>(
|
||||
sections::SectionData::Rela64(entries) => Some(entries),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into())
|
||||
.ok_or_else(|| errno!(ENOEXEC, "failed to get .rela.plt entries"))
|
||||
}
|
||||
|
||||
pub fn get_dynsym_entries<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<&'a [DynEntry64], Error> {
|
||||
pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [DynEntry64]> {
|
||||
elf_file
|
||||
.find_section_by_name(".dynsym")
|
||||
.and_then(|dynamic_section| dynamic_section.get_data(&elf_file).ok())
|
||||
@ -142,5 +136,5 @@ pub fn get_dynsym_entries<'b, 'a: 'b>(
|
||||
sections::SectionData::DynSymbolTable64(entries) => Some(entries),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into())
|
||||
.ok_or_else(|| errno!(ENOEXEC, "failed to get .dynsym entries"))
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ pub fn do_init(
|
||||
argv: &[CString],
|
||||
envp: &[CString],
|
||||
auxtbl: &AuxTable,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<usize> {
|
||||
let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? };
|
||||
let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?;
|
||||
let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?;
|
||||
@ -75,9 +75,9 @@ pub struct StackBuf {
|
||||
}
|
||||
|
||||
impl StackBuf {
|
||||
pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf, Error> {
|
||||
pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf> {
|
||||
if stack_top % 16 != 0 || stack_size == 0 || stack_top < stack_size {
|
||||
return errno!(EINVAL, "Invalid stack range");
|
||||
return_errno!(EINVAL, "Invalid stack range");
|
||||
};
|
||||
Ok(StackBuf {
|
||||
stack_top: stack_top,
|
||||
@ -86,7 +86,7 @@ impl StackBuf {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn put(&self, val: u64) -> Result<*const u64, Error> {
|
||||
pub fn put(&self, val: u64) -> Result<*const u64> {
|
||||
let val_ptr = self.alloc(8, 8)? as *mut u64;
|
||||
unsafe {
|
||||
ptr::write(val_ptr, val);
|
||||
@ -94,7 +94,7 @@ impl StackBuf {
|
||||
Ok(val_ptr as *const u64)
|
||||
}
|
||||
|
||||
pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T, Error>
|
||||
pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@ -120,7 +120,7 @@ impl StackBuf {
|
||||
Ok(base_ptr as *const T)
|
||||
}
|
||||
|
||||
pub fn put_cstr(&self, cstr: &CStr) -> Result<*const u8, Error> {
|
||||
pub fn put_cstr(&self, cstr: &CStr) -> Result<*const u8> {
|
||||
let bytes = cstr.to_bytes_with_nul();
|
||||
self.put_slice(bytes)
|
||||
}
|
||||
@ -129,12 +129,12 @@ impl StackBuf {
|
||||
self.stack_pos.get()
|
||||
}
|
||||
|
||||
fn alloc(&self, size: usize, align: usize) -> Result<*mut u8, Error> {
|
||||
fn alloc(&self, size: usize, align: usize) -> Result<*mut u8> {
|
||||
let new_pos = {
|
||||
let old_pos = self.stack_pos.get();
|
||||
let new_pos = align_down(old_pos - size, align);
|
||||
if new_pos < self.stack_bottom {
|
||||
return errno!(ENOMEM, "No enough space in buffer");
|
||||
return_errno!(ENOMEM, "No enough space in buffer");
|
||||
}
|
||||
new_pos
|
||||
};
|
||||
@ -147,7 +147,7 @@ impl StackBuf {
|
||||
fn clone_cstrings_on_stack<'a, 'b>(
|
||||
stack: &'a StackBuf,
|
||||
cstrings: &'b [CString],
|
||||
) -> Result<Vec<&'a CStr>, Error> {
|
||||
) -> Result<Vec<&'a CStr>> {
|
||||
let mut cstrs_cloned = Vec::new();
|
||||
for cs in cstrings.iter().rev() {
|
||||
let cstrp_cloned = stack.put_cstr(cs)?;
|
||||
@ -158,7 +158,7 @@ fn clone_cstrings_on_stack<'a, 'b>(
|
||||
Ok(cstrs_cloned)
|
||||
}
|
||||
|
||||
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<(), Error> {
|
||||
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<()> {
|
||||
// For every key-value pair, dump the value first, then the key
|
||||
stack.put(0 as u64);
|
||||
stack.put(AuxKey::AT_NULL as u64);
|
||||
@ -169,10 +169,7 @@ fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Re
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dump_cstrptrs_on_stack<'a, 'b>(
|
||||
stack: &'a StackBuf,
|
||||
strptrs: &'b [&'a CStr],
|
||||
) -> Result<(), Error> {
|
||||
fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr]) -> Result<()> {
|
||||
stack.put(0 as u64); // End with a NULL pointer
|
||||
for sp in strptrs.iter().rev() {
|
||||
stack.put(sp.as_ptr() as u64);
|
||||
@ -233,9 +230,9 @@ impl AuxTable {
|
||||
}
|
||||
|
||||
impl AuxTable {
|
||||
pub fn set(&mut self, key: AuxKey, val: u64) -> Result<(), Error> {
|
||||
pub fn set(&mut self, key: AuxKey, val: u64) -> Result<()> {
|
||||
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
|
||||
return errno!(EINVAL, "Illegal key");
|
||||
return_errno!(EINVAL, "Illegal key");
|
||||
}
|
||||
self.table
|
||||
.entry(key)
|
||||
|
@ -8,7 +8,7 @@ pub fn do_init(
|
||||
elf_buf: &[u8],
|
||||
ldso_elf_file: &ElfFile,
|
||||
ldso_elf_buf: &[u8],
|
||||
) -> Result<ProcessVM, Error> {
|
||||
) -> Result<ProcessVM> {
|
||||
// Alloc all virtual memory areas
|
||||
let mut code_seg = get_code_segment(elf_file)?;
|
||||
let mut data_seg = get_data_segment(elf_file)?;
|
||||
@ -34,7 +34,8 @@ pub fn do_init(
|
||||
let mut process_vm = ProcessVMBuilder::new(code_size, data_size)
|
||||
.ldso_code_size(ldso_code_size)
|
||||
.ldso_data_size(ldso_data_size)
|
||||
.build()?;
|
||||
.build()
|
||||
.cause_err(|e| errno!(e.errno(), "failed to create process VM"))?;
|
||||
|
||||
// Load code and data
|
||||
let process_base_addr = process_vm.get_code_range().start();
|
||||
@ -57,7 +58,7 @@ pub fn do_init(
|
||||
Ok(process_vm)
|
||||
}
|
||||
|
||||
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
|
||||
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<()> {
|
||||
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?;
|
||||
for rela_entry in rela_entries {
|
||||
/*
|
||||
@ -84,7 +85,7 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Err
|
||||
Ok(())
|
||||
}
|
||||
/*
|
||||
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
|
||||
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<()> {
|
||||
let syscall_addr = __occlum_syscall as *const () as usize;
|
||||
|
||||
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.plt")?;
|
||||
|
@ -38,17 +38,23 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
envp: &[CString],
|
||||
file_actions: &[FileAction],
|
||||
parent_ref: &ProcessRef,
|
||||
) -> Result<u32, Error> {
|
||||
) -> Result<u32> {
|
||||
let mut elf_buf = {
|
||||
let path = elf_path.as_ref().to_str().unwrap();
|
||||
let inode = parent_ref.lock().unwrap().lookup_inode(path)?;
|
||||
inode.read_as_vec()?
|
||||
let inode = parent_ref
|
||||
.lock()
|
||||
.unwrap()
|
||||
.lookup_inode(path)
|
||||
.map_err(|e| errno!(e.errno(), "cannot find the executable"))?;
|
||||
inode
|
||||
.read_as_vec()
|
||||
.map_err(|e| errno!(e.errno(), "failed to read the executable ELF"))?
|
||||
};
|
||||
let elf_file = {
|
||||
let elf_file =
|
||||
ElfFile::new(&elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
let elf_file = ElfFile::new(&elf_buf)
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to parse the executable ELF"))?;
|
||||
header::sanity_check(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to parse the executable ELF"))?;
|
||||
/*
|
||||
elf_helper::print_program_headers(&elf_file)?;
|
||||
elf_helper::print_sections(&elf_file)?;
|
||||
@ -59,15 +65,22 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
|
||||
let mut ldso_elf_buf = {
|
||||
let ldso_path = "/lib/ld-musl-x86_64.so.1";
|
||||
let ldso_inode = ROOT_INODE.lookup(ldso_path)?;
|
||||
ldso_inode.read_as_vec()?
|
||||
let ldso_inode = ROOT_INODE.lookup(ldso_path).map_err(|e| {
|
||||
errno!(
|
||||
e.errno(),
|
||||
"cannot find the loader at /lib/ld-musl-x86_64.so.1"
|
||||
)
|
||||
})?;
|
||||
ldso_inode
|
||||
.read_as_vec()
|
||||
.map_err(|e| errno!(e.errno(), "failed to read the ld.so ELF"))?
|
||||
};
|
||||
|
||||
let ldso_elf_file = {
|
||||
let ldso_elf_file = ElfFile::new(&ldso_elf_buf)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to parse the ld.so ELF"))?;
|
||||
header::sanity_check(&ldso_elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to parse the ld.so ELF"))?;
|
||||
/*
|
||||
elf_helper::print_program_headers(&elf_file)?;
|
||||
elf_helper::print_sections(&elf_file)?;
|
||||
@ -86,7 +99,7 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
let ldso_base_addr = vm.get_ldso_code_range().start();
|
||||
let ldso_entry = ldso_base_addr + elf_helper::get_start_address(&ldso_elf_file)?;
|
||||
if !vm.get_ldso_code_range().contains(ldso_entry) {
|
||||
return errno!(EINVAL, "Invalid program entry");
|
||||
return_errno!(EINVAL, "Invalid program entry");
|
||||
}
|
||||
ldso_entry
|
||||
};
|
||||
@ -117,7 +130,7 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
Ok(new_pid)
|
||||
}
|
||||
|
||||
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<FileTable, Error> {
|
||||
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<FileTable> {
|
||||
// Usually, we just inherit the file table from the parent
|
||||
let parent = parent_ref.lock().unwrap();
|
||||
let should_inherit_file_table = parent.get_pid() > 0;
|
||||
@ -170,7 +183,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<Fi
|
||||
Ok(file_table)
|
||||
}
|
||||
|
||||
fn init_auxtbl(process_vm: &ProcessVM, elf_file: &ElfFile) -> Result<AuxTable, Error> {
|
||||
fn init_auxtbl(process_vm: &ProcessVM, elf_file: &ElfFile) -> Result<AuxTable> {
|
||||
let mut auxtbl = AuxTable::new();
|
||||
auxtbl.set(AuxKey::AT_PAGESZ, 4096)?;
|
||||
auxtbl.set(AuxKey::AT_UID, 0)?;
|
||||
|
@ -29,25 +29,24 @@ impl Segment {
|
||||
self.mem_size
|
||||
}
|
||||
|
||||
pub fn from_program_header(ph: &ProgramHeader) -> Result<Segment, Error> {
|
||||
pub fn from_program_header(ph: &ProgramHeader) -> Result<Segment> {
|
||||
let ph64 = match ph {
|
||||
ProgramHeader::Ph32(ph) => {
|
||||
return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into());
|
||||
return_errno!(ENOEXEC, "not support 32-bit ELF");
|
||||
}
|
||||
ProgramHeader::Ph64(ph64) => ph64,
|
||||
};
|
||||
if ph64.align > 1 && ((ph64.offset % ph64.align) != (ph64.virtual_addr % ph64.align)) {
|
||||
return Err((
|
||||
Errno::EINVAL,
|
||||
"Memory address and file offset is not equal, per modulo",
|
||||
)
|
||||
.into());
|
||||
return_errno!(
|
||||
EINVAL,
|
||||
"memory address and file offset is not equal, per modulo"
|
||||
);
|
||||
}
|
||||
if ph64.mem_size < ph64.file_size {
|
||||
return Err((Errno::EINVAL, "Memory size must be greater than file size").into());
|
||||
return_errno!(EINVAL, "memory size must be greater than file size");
|
||||
}
|
||||
if !ph64.align.is_power_of_two() {
|
||||
return Err((Errno::EINVAL, "Memory alignment must be a power of two").into());
|
||||
return_errno!(EINVAL, "memory alignment must be a power of two");
|
||||
}
|
||||
|
||||
Ok(Segment {
|
||||
@ -90,15 +89,15 @@ impl Segment {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_code_segment(elf_file: &ElfFile) -> Result<Segment, Error> {
|
||||
pub fn get_code_segment(elf_file: &ElfFile) -> Result<Segment> {
|
||||
let code_ph = elf_helper::get_code_program_header(elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get the program header of code"))?;
|
||||
Segment::from_program_header(&code_ph)
|
||||
}
|
||||
|
||||
pub fn get_data_segment(elf_file: &ElfFile) -> Result<Segment, Error> {
|
||||
pub fn get_data_segment(elf_file: &ElfFile) -> Result<Segment> {
|
||||
let data_ph = elf_helper::get_data_program_header(elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?;
|
||||
.map_err(|e| errno!(ENOEXEC, "failed to get the program header of code"))?;
|
||||
Segment::from_program_header(&data_ph)
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,9 @@ impl Task {
|
||||
user_stack_base: usize,
|
||||
user_stack_limit: usize,
|
||||
user_fs: Option<usize>,
|
||||
) -> Result<Task, Error> {
|
||||
) -> Result<Task> {
|
||||
if !(user_stack_base >= user_rsp && user_rsp > user_stack_limit) {
|
||||
return errno!(EINVAL, "Invalid user stack");
|
||||
return_errno!(EINVAL, "Invalid user stack");
|
||||
}
|
||||
|
||||
// Set the default user fsbase to an address on user stack, which is
|
||||
@ -71,9 +71,9 @@ fn dequeue_task() -> Option<ProcessRef> {
|
||||
NEW_PROCESS_QUEUE.lock().unwrap().pop_front()
|
||||
}
|
||||
|
||||
pub fn run_task(host_tid: pid_t) -> Result<i32, Error> {
|
||||
pub fn run_task(host_tid: pid_t) -> Result<i32> {
|
||||
let new_process: ProcessRef =
|
||||
dequeue_task().ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?;
|
||||
dequeue_task().ok_or_else(|| errno!(EAGAIN, "no new processes to run"))?;
|
||||
set_current(&new_process);
|
||||
|
||||
let (pid, task) = {
|
||||
|
@ -39,7 +39,7 @@ pub fn do_clone(
|
||||
ptid: Option<*mut pid_t>,
|
||||
ctid: Option<*mut pid_t>,
|
||||
new_tls: Option<usize>,
|
||||
) -> Result<pid_t, Error> {
|
||||
) -> Result<pid_t> {
|
||||
info!(
|
||||
"clone: flags: {:?}, stack_addr: {:?}, ptid: {:?}, ctid: {:?}, new_tls: {:?}",
|
||||
flags, user_rsp, ptid, ctid, new_tls
|
||||
@ -107,7 +107,7 @@ pub fn do_clone(
|
||||
Ok(new_thread_pid)
|
||||
}
|
||||
|
||||
pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result<pid_t, Error> {
|
||||
pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result<pid_t> {
|
||||
info!("set_tid_address: tidptr: {:#x}", tidptr as usize);
|
||||
let current_ref = get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
@ -115,7 +115,7 @@ pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result<pid_t, Error> {
|
||||
Ok(current.get_tid())
|
||||
}
|
||||
|
||||
fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange, Error> {
|
||||
fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange> {
|
||||
// The first case is most likely
|
||||
if let Ok(stack_range) = vm.find_mmap_region(user_rsp) {
|
||||
Ok(stack_range)
|
||||
@ -130,6 +130,6 @@ fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange, E
|
||||
}
|
||||
// Invalid
|
||||
else {
|
||||
errno!(ESRCH, "invalid rsp")
|
||||
return_errno!(ESRCH, "invalid rsp")
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
use fs::*;
|
||||
use misc::{resource_t, rlimit_t, utsname_t};
|
||||
use prelude::*;
|
||||
use process::{pid_t, ChildProcessFilter, CloneFlags, CpuSet, FileAction, FutexFlags, FutexOp};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr;
|
||||
@ -22,6 +21,7 @@ use super::*;
|
||||
|
||||
use self::consts::*;
|
||||
use std::any::Any;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
|
||||
// Use the internal syscall wrappers from sgx_tstd
|
||||
//use std::libc_fs as fs;
|
||||
@ -302,9 +302,14 @@ pub extern "C" fn dispatch_syscall(
|
||||
info!("=> {:?}", ret);
|
||||
|
||||
match ret {
|
||||
Ok(code) => code as isize,
|
||||
Err(e) if e.errno.as_retval() == 0 => panic!("undefined errno"),
|
||||
Err(e) => e.errno.as_retval() as isize,
|
||||
Ok(retval) => retval as isize,
|
||||
Err(e) => {
|
||||
warn!("{}", e.backtrace());
|
||||
|
||||
let retval = -(e.errno() as isize);
|
||||
debug_assert!(retval == 0);
|
||||
retval
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +355,7 @@ pub struct FdOp {
|
||||
path: *const i8,
|
||||
}
|
||||
|
||||
fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>, Error> {
|
||||
fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>> {
|
||||
let mut file_actions = Vec::new();
|
||||
|
||||
let mut fdop_ptr = fdop_ptr;
|
||||
@ -370,7 +375,7 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>, E
|
||||
fd: fdop.fd,
|
||||
},
|
||||
_ => {
|
||||
return errno!(EINVAL, "Unknown file action command");
|
||||
return_errno!(EINVAL, "Unknown file action command");
|
||||
}
|
||||
};
|
||||
file_actions.push(file_action);
|
||||
@ -387,7 +392,7 @@ fn do_spawn(
|
||||
argv: *const *const i8,
|
||||
envp: *const *const i8,
|
||||
fdop_list: *const FdOp,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
check_mut_ptr(child_pid_ptr)?;
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let argv = clone_cstrings_safely(argv)?;
|
||||
@ -411,7 +416,7 @@ pub fn do_clone(
|
||||
ptid: *mut pid_t,
|
||||
ctid: *mut pid_t,
|
||||
new_tls: usize,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
let flags = CloneFlags::from_bits_truncate(flags);
|
||||
check_mut_ptr(stack_addr as *mut u64)?;
|
||||
let ptid = {
|
||||
@ -444,7 +449,7 @@ pub fn do_clone(
|
||||
Ok(child_pid as isize)
|
||||
}
|
||||
|
||||
pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result<isize, Error> {
|
||||
pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result<isize> {
|
||||
check_ptr(futex_addr)?;
|
||||
let (futex_op, futex_flags) = process::futex_op_and_flags_from_u32(futex_op)?;
|
||||
match futex_op {
|
||||
@ -452,28 +457,28 @@ pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result
|
||||
FutexOp::FUTEX_WAKE => {
|
||||
let max_count = {
|
||||
if futex_val < 0 {
|
||||
return errno!(EINVAL, "the count must not be negative");
|
||||
return_errno!(EINVAL, "the count must not be negative");
|
||||
}
|
||||
futex_val as usize
|
||||
};
|
||||
process::futex_wake(futex_addr, max_count).map(|count| count as isize)
|
||||
}
|
||||
_ => errno!(ENOSYS, "the futex operation is not supported"),
|
||||
_ => return_errno!(ENOSYS, "the futex operation is not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
fn do_open(path: *const i8, flags: u32, mode: u32) -> Result<isize, Error> {
|
||||
fn do_open(path: *const i8, flags: u32, mode: u32) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let fd = fs::do_open(&path, flags, mode)?;
|
||||
Ok(fd as isize)
|
||||
}
|
||||
|
||||
fn do_close(fd: FileDesc) -> Result<isize, Error> {
|
||||
fn do_close(fd: FileDesc) -> Result<isize> {
|
||||
fs::do_close(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result<isize, Error> {
|
||||
fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_mut_array(buf, size)?;
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, size) }
|
||||
@ -482,7 +487,7 @@ fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result<isize, Error> {
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result<isize, Error> {
|
||||
fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_array(buf, size)?;
|
||||
unsafe { std::slice::from_raw_parts(buf, size) }
|
||||
@ -491,10 +496,10 @@ fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result<isize, Error> {
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result<isize, Error> {
|
||||
fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result<isize> {
|
||||
let count = {
|
||||
if count < 0 {
|
||||
return errno!(EINVAL, "Invalid count of iovec");
|
||||
return_errno!(EINVAL, "Invalid count of iovec");
|
||||
}
|
||||
count as usize
|
||||
};
|
||||
@ -516,10 +521,10 @@ fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result<isize, Err
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result<isize, Error> {
|
||||
fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result<isize> {
|
||||
let count = {
|
||||
if count < 0 {
|
||||
return errno!(EINVAL, "Invalid count of iovec");
|
||||
return_errno!(EINVAL, "Invalid count of iovec");
|
||||
}
|
||||
count as usize
|
||||
};
|
||||
@ -541,7 +546,7 @@ fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result<isize, Error>
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result<isize, Error> {
|
||||
fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_mut_array(buf, size)?;
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, size) }
|
||||
@ -550,7 +555,7 @@ fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result<is
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result<isize, Error> {
|
||||
fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_array(buf, size)?;
|
||||
unsafe { std::slice::from_raw_parts(buf, size) }
|
||||
@ -559,7 +564,7 @@ fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
@ -570,7 +575,7 @@ fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result<isize> {
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
let stat = fs::do_fstat(fd)?;
|
||||
@ -580,7 +585,7 @@ fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
@ -591,12 +596,12 @@ fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize, Error> {
|
||||
fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize> {
|
||||
let seek_from = match whence {
|
||||
0 => {
|
||||
// SEEK_SET
|
||||
if offset < 0 {
|
||||
return errno!(EINVAL, "Invalid offset");
|
||||
return_errno!(EINVAL, "Invalid offset");
|
||||
}
|
||||
SeekFrom::Start(offset as u64)
|
||||
}
|
||||
@ -609,7 +614,7 @@ fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize, Error> {
|
||||
SeekFrom::End(offset)
|
||||
}
|
||||
_ => {
|
||||
return errno!(EINVAL, "Invalid whence");
|
||||
return_errno!(EINVAL, "Invalid whence");
|
||||
}
|
||||
};
|
||||
|
||||
@ -617,28 +622,28 @@ fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize, Error> {
|
||||
Ok(offset as isize)
|
||||
}
|
||||
|
||||
fn do_fsync(fd: FileDesc) -> Result<isize, Error> {
|
||||
fn do_fsync(fd: FileDesc) -> Result<isize> {
|
||||
fs::do_fsync(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_fdatasync(fd: FileDesc) -> Result<isize, Error> {
|
||||
fn do_fdatasync(fd: FileDesc) -> Result<isize> {
|
||||
fs::do_fdatasync(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_truncate(path: *const i8, len: usize) -> Result<isize, Error> {
|
||||
fn do_truncate(path: *const i8, len: usize) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_truncate(&path, len)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_ftruncate(fd: FileDesc, len: usize) -> Result<isize, Error> {
|
||||
fn do_ftruncate(fd: FileDesc, len: usize) -> Result<isize> {
|
||||
fs::do_ftruncate(fd, len)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result<isize, Error> {
|
||||
fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_mut_array(buf, buf_size)?;
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, buf_size) }
|
||||
@ -647,7 +652,7 @@ fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result<isize, E
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_sync() -> Result<isize, Error> {
|
||||
fn do_sync() -> Result<isize> {
|
||||
fs::do_sync()?;
|
||||
Ok(0)
|
||||
}
|
||||
@ -659,14 +664,14 @@ fn do_mmap(
|
||||
flags: i32,
|
||||
fd: FileDesc,
|
||||
offset: off_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
let perms = VMPerms::from_u32(perms as u32)?;
|
||||
let flags = MMapFlags::from_u32(flags as u32)?;
|
||||
let addr = vm::do_mmap(addr, size, perms, flags, fd, offset as usize)?;
|
||||
Ok(addr as isize)
|
||||
}
|
||||
|
||||
fn do_munmap(addr: usize, size: usize) -> Result<isize, Error> {
|
||||
fn do_munmap(addr: usize, size: usize) -> Result<isize> {
|
||||
vm::do_munmap(addr, size)?;
|
||||
Ok(0)
|
||||
}
|
||||
@ -677,22 +682,22 @@ fn do_mremap(
|
||||
new_size: usize,
|
||||
flags: i32,
|
||||
new_addr: usize,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
warn!("mremap: not implemented!");
|
||||
errno!(ENOSYS, "not supported yet")
|
||||
return_errno!(ENOSYS, "not supported yet")
|
||||
}
|
||||
|
||||
fn do_mprotect(addr: usize, len: usize, prot: u32) -> Result<isize, Error> {
|
||||
fn do_mprotect(addr: usize, len: usize, prot: u32) -> Result<isize> {
|
||||
// TODO: implement it
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_brk(new_brk_addr: usize) -> Result<isize, Error> {
|
||||
fn do_brk(new_brk_addr: usize) -> Result<isize> {
|
||||
let ret_brk_addr = vm::do_brk(new_brk_addr)?;
|
||||
Ok(ret_brk_addr as isize)
|
||||
}
|
||||
|
||||
fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result<isize, Error> {
|
||||
fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result<isize> {
|
||||
if !_exit_status.is_null() {
|
||||
check_mut_ptr(_exit_status)?;
|
||||
}
|
||||
@ -723,45 +728,45 @@ fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result<isize, Error> {
|
||||
}
|
||||
}
|
||||
|
||||
fn do_getpid() -> Result<isize, Error> {
|
||||
fn do_getpid() -> Result<isize> {
|
||||
let pid = process::do_getpid();
|
||||
Ok(pid as isize)
|
||||
}
|
||||
|
||||
fn do_gettid() -> Result<isize, Error> {
|
||||
fn do_gettid() -> Result<isize> {
|
||||
let tid = process::do_gettid();
|
||||
Ok(tid as isize)
|
||||
}
|
||||
|
||||
fn do_getppid() -> Result<isize, Error> {
|
||||
fn do_getppid() -> Result<isize> {
|
||||
let ppid = process::do_getppid();
|
||||
Ok(ppid as isize)
|
||||
}
|
||||
|
||||
fn do_getpgid() -> Result<isize, Error> {
|
||||
fn do_getpgid() -> Result<isize> {
|
||||
let pgid = process::do_getpgid();
|
||||
Ok(pgid as isize)
|
||||
}
|
||||
|
||||
// TODO: implement uid, gid, euid, egid
|
||||
|
||||
fn do_getuid() -> Result<isize, Error> {
|
||||
fn do_getuid() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_getgid() -> Result<isize, Error> {
|
||||
fn do_getgid() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_geteuid() -> Result<isize, Error> {
|
||||
fn do_geteuid() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_getegid() -> Result<isize, Error> {
|
||||
fn do_getegid() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result<isize, Error> {
|
||||
fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result<isize> {
|
||||
check_mut_array(fds_u, 2)?;
|
||||
// TODO: how to deal with open flags???
|
||||
let fds = fs::do_pipe2(flags as u32)?;
|
||||
@ -772,23 +777,23 @@ fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_dup(old_fd: FileDesc) -> Result<isize, Error> {
|
||||
fn do_dup(old_fd: FileDesc) -> Result<isize> {
|
||||
let new_fd = fs::do_dup(old_fd)?;
|
||||
Ok(new_fd as isize)
|
||||
}
|
||||
|
||||
fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<isize, Error> {
|
||||
fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<isize> {
|
||||
let new_fd = fs::do_dup2(old_fd, new_fd)?;
|
||||
Ok(new_fd as isize)
|
||||
}
|
||||
|
||||
fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<isize, Error> {
|
||||
fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<isize> {
|
||||
let new_fd = fs::do_dup3(old_fd, new_fd, flags)?;
|
||||
Ok(new_fd as isize)
|
||||
}
|
||||
|
||||
// TODO: handle tz: timezone_t
|
||||
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize, Error> {
|
||||
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize> {
|
||||
check_mut_ptr(tv_u)?;
|
||||
let tv = time::do_gettimeofday();
|
||||
unsafe {
|
||||
@ -797,7 +802,7 @@ fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result<isize, Error> {
|
||||
fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result<isize> {
|
||||
check_mut_ptr(ts_u)?;
|
||||
let clockid = time::ClockID::from_raw(clockid)?;
|
||||
let ts = time::do_clock_gettime(clockid)?;
|
||||
@ -829,15 +834,15 @@ fn do_unknown(
|
||||
arg3: isize,
|
||||
arg4: isize,
|
||||
arg5: isize,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
warn!(
|
||||
"unknown or unsupported syscall (# = {}): {:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
|
||||
num, arg0, arg1, arg2, arg3, arg4, arg5
|
||||
);
|
||||
errno!(ENOSYS, "Unknown syscall")
|
||||
return_errno!(ENOSYS, "Unknown syscall")
|
||||
}
|
||||
|
||||
fn do_getcwd(buf: *mut u8, size: usize) -> Result<isize, Error> {
|
||||
fn do_getcwd(buf: *mut u8, size: usize) -> Result<isize> {
|
||||
let safe_buf = {
|
||||
check_mut_array(buf, size)?;
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, size) }
|
||||
@ -846,20 +851,20 @@ fn do_getcwd(buf: *mut u8, size: usize) -> Result<isize, Error> {
|
||||
let mut proc = proc_ref.lock().unwrap();
|
||||
let cwd = proc.get_cwd();
|
||||
if cwd.len() + 1 > safe_buf.len() {
|
||||
return errno!(ERANGE, "buf is not long enough");
|
||||
return_errno!(ERANGE, "buf is not long enough");
|
||||
}
|
||||
safe_buf[..cwd.len()].copy_from_slice(cwd.as_bytes());
|
||||
safe_buf[cwd.len()] = 0;
|
||||
Ok(buf as isize)
|
||||
}
|
||||
|
||||
fn do_chdir(path: *const i8) -> Result<isize, Error> {
|
||||
fn do_chdir(path: *const i8) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_chdir(&path)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result<isize, Error> {
|
||||
fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result<isize> {
|
||||
let oldpath = clone_cstring_safely(oldpath)?
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
@ -870,19 +875,19 @@ fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_mkdir(path: *const i8, mode: usize) -> Result<isize, Error> {
|
||||
fn do_mkdir(path: *const i8, mode: usize) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_mkdir(&path, mode)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_rmdir(path: *const i8) -> Result<isize, Error> {
|
||||
fn do_rmdir(path: *const i8) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_rmdir(&path)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_link(oldpath: *const i8, newpath: *const i8) -> Result<isize, Error> {
|
||||
fn do_link(oldpath: *const i8, newpath: *const i8) -> Result<isize> {
|
||||
let oldpath = clone_cstring_safely(oldpath)?
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
@ -893,13 +898,13 @@ fn do_link(oldpath: *const i8, newpath: *const i8) -> Result<isize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_unlink(path: *const i8) -> Result<isize, Error> {
|
||||
fn do_unlink(path: *const i8) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_unlink(&path)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_readlink(path: *const i8, buf: *mut u8, size: usize) -> Result<isize, Error> {
|
||||
fn do_readlink(path: *const i8, buf: *mut u8, size: usize) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let buf = {
|
||||
check_array(buf, size)?;
|
||||
@ -914,7 +919,7 @@ fn do_sendfile(
|
||||
in_fd: FileDesc,
|
||||
offset_ptr: *mut off_t,
|
||||
count: usize,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
let offset = if offset_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
@ -931,12 +936,12 @@ fn do_sendfile(
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result<isize, Error> {
|
||||
fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result<isize> {
|
||||
let cmd = FcntlCmd::from_raw(cmd, arg)?;
|
||||
fs::do_fcntl(fd, &cmd)
|
||||
}
|
||||
|
||||
fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result<isize, Error> {
|
||||
fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result<isize> {
|
||||
info!("ioctl: fd: {}, cmd: {}, argp: {:?}", fd, cmd, argp);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
@ -950,30 +955,30 @@ fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result<isize, Error>
|
||||
Ok(0)
|
||||
} else {
|
||||
warn!("ioctl is unimplemented");
|
||||
errno!(ENOSYS, "ioctl is unimplemented")
|
||||
return_errno!(ENOSYS, "ioctl is unimplemented")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_arch_prctl(code: u32, addr: *mut usize) -> Result<isize, Error> {
|
||||
fn do_arch_prctl(code: u32, addr: *mut usize) -> Result<isize> {
|
||||
let code = process::ArchPrctlCode::from_u32(code)?;
|
||||
check_mut_ptr(addr)?;
|
||||
process::do_arch_prctl(code, addr).map(|_| 0)
|
||||
}
|
||||
|
||||
fn do_set_tid_address(tidptr: *mut pid_t) -> Result<isize, Error> {
|
||||
fn do_set_tid_address(tidptr: *mut pid_t) -> Result<isize> {
|
||||
check_mut_ptr(tidptr)?;
|
||||
process::do_set_tid_address(tidptr).map(|tid| tid as isize)
|
||||
}
|
||||
|
||||
fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result<isize, Error> {
|
||||
fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result<isize> {
|
||||
// Construct safe Rust types
|
||||
let mut buf_slice = {
|
||||
check_mut_array(buf, cpusize)?;
|
||||
if cpusize == 0 {
|
||||
return errno!(EINVAL, "cpuset size must be greater than zero");
|
||||
return_errno!(EINVAL, "cpuset size must be greater than zero");
|
||||
}
|
||||
if buf as *const _ == std::ptr::null() {
|
||||
return errno!(EFAULT, "cpuset mask must NOT be null");
|
||||
return_errno!(EFAULT, "cpuset mask must NOT be null");
|
||||
}
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, cpusize) }
|
||||
};
|
||||
@ -986,15 +991,15 @@ fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Resul
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result<isize, Error> {
|
||||
fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result<isize> {
|
||||
// Convert unsafe C types into safe Rust types
|
||||
let cpuset = {
|
||||
check_array(buf, cpusize)?;
|
||||
if cpusize == 0 {
|
||||
return errno!(EINVAL, "cpuset size must be greater than zero");
|
||||
return_errno!(EINVAL, "cpuset size must be greater than zero");
|
||||
}
|
||||
if buf as *const _ == std::ptr::null() {
|
||||
return errno!(EFAULT, "cpuset mask must NOT be null");
|
||||
return_errno!(EFAULT, "cpuset mask must NOT be null");
|
||||
}
|
||||
CpuSet::from_raw_buf(buf, cpusize)
|
||||
};
|
||||
@ -1004,7 +1009,7 @@ fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Res
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize, Error> {
|
||||
fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize> {
|
||||
info!(
|
||||
"socket: domain: {}, socket_type: {}, protocol: {}",
|
||||
domain, socket_type, protocol
|
||||
@ -1028,11 +1033,7 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
|
||||
Ok(fd as isize)
|
||||
}
|
||||
|
||||
fn do_connect(
|
||||
fd: c_int,
|
||||
addr: *const libc::sockaddr,
|
||||
addr_len: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
fn do_connect(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result<isize> {
|
||||
info!(
|
||||
"connect: fd: {}, addr: {:?}, addr_len: {}",
|
||||
fd, addr, addr_len
|
||||
@ -1052,7 +1053,7 @@ fn do_connect(
|
||||
unix_socket.connect(path)?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1061,7 +1062,7 @@ fn do_accept4(
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
flags: c_int,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"accept4: fd: {}, addr: {:?}, addr_len: {:?}, flags: {:#x}",
|
||||
fd, addr, addr_len, flags
|
||||
@ -1087,11 +1088,11 @@ fn do_accept4(
|
||||
|
||||
Ok(new_fd as isize)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize> {
|
||||
info!("shutdown: fd: {}, how: {}", fd, how);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
@ -1100,15 +1101,11 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
|
||||
Ok(ret as isize)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_bind(
|
||||
fd: c_int,
|
||||
addr: *const libc::sockaddr,
|
||||
addr_len: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result<isize> {
|
||||
info!("bind: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
@ -1126,11 +1123,11 @@ fn do_bind(
|
||||
unix_socket.bind(path)?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize> {
|
||||
info!("listen: fd: {}, backlog: {}", fd, backlog);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
@ -1142,7 +1139,7 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||
unix_socket.listen()?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1152,7 +1149,7 @@ fn do_setsockopt(
|
||||
optname: c_int,
|
||||
optval: *const c_void,
|
||||
optlen: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"setsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||
fd, level, optname, optval, optlen
|
||||
@ -1173,7 +1170,7 @@ fn do_setsockopt(
|
||||
warn!("setsockopt for unix socket is unimplemented");
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1183,7 +1180,7 @@ fn do_getsockopt(
|
||||
optname: c_int,
|
||||
optval: *mut c_void,
|
||||
optlen: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"getsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||
fd, level, optname, optval, optlen
|
||||
@ -1207,7 +1204,7 @@ fn do_getpeername(
|
||||
fd: c_int,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"getpeername: fd: {}, addr: {:?}, addr_len: {:?}",
|
||||
fd, addr, addr_len
|
||||
@ -1220,12 +1217,12 @@ fn do_getpeername(
|
||||
Ok(ret as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
warn!("getpeername for unix socket is unimplemented");
|
||||
errno!(
|
||||
return_errno!(
|
||||
ENOTCONN,
|
||||
"hack for php: Transport endpoint is not connected"
|
||||
)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1233,7 +1230,7 @@ fn do_getsockname(
|
||||
fd: c_int,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"getsockname: fd: {}, addr: {:?}, addr_len: {:?}",
|
||||
fd, addr, addr_len
|
||||
@ -1248,7 +1245,7 @@ fn do_getsockname(
|
||||
warn!("getsockname for unix socket is unimplemented");
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
return_errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1259,7 +1256,7 @@ fn do_sendto(
|
||||
flags: c_int,
|
||||
addr: *const libc::sockaddr,
|
||||
addr_len: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"sendto: fd: {}, base: {:?}, len: {}, addr: {:?}, addr_len: {}",
|
||||
fd, base, len, addr, addr_len
|
||||
@ -1287,7 +1284,7 @@ fn do_recvfrom(
|
||||
flags: c_int,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
info!(
|
||||
"recvfrom: fd: {}, base: {:?}, len: {}, flags: {}, addr: {:?}, addr_len: {:?}",
|
||||
fd, base, len, flags, addr, addr_len
|
||||
@ -1314,10 +1311,10 @@ fn do_select(
|
||||
writefds: *mut libc::fd_set,
|
||||
exceptfds: *mut libc::fd_set,
|
||||
timeout: *const libc::timeval,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
// check arguments
|
||||
if nfds < 0 || nfds >= libc::FD_SETSIZE as c_int {
|
||||
return errno!(EINVAL, "nfds is negative or exceeds the resource limit");
|
||||
return_errno!(EINVAL, "nfds is negative or exceeds the resource limit");
|
||||
}
|
||||
let nfds = nfds as usize;
|
||||
|
||||
@ -1354,7 +1351,7 @@ fn do_select(
|
||||
Ok(n as isize)
|
||||
}
|
||||
|
||||
fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result<isize, Error> {
|
||||
fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result<isize> {
|
||||
check_mut_array(fds, nfds as usize)?;
|
||||
let polls = unsafe { std::slice::from_raw_parts_mut(fds, nfds as usize) };
|
||||
|
||||
@ -1362,14 +1359,14 @@ fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result
|
||||
Ok(n as isize)
|
||||
}
|
||||
|
||||
fn do_epoll_create(size: c_int) -> Result<isize, Error> {
|
||||
fn do_epoll_create(size: c_int) -> Result<isize> {
|
||||
if size <= 0 {
|
||||
return errno!(EINVAL, "size is not positive");
|
||||
return_errno!(EINVAL, "size is not positive");
|
||||
}
|
||||
do_epoll_create1(0)
|
||||
}
|
||||
|
||||
fn do_epoll_create1(flags: c_int) -> Result<isize, Error> {
|
||||
fn do_epoll_create1(flags: c_int) -> Result<isize> {
|
||||
let fd = fs::do_epoll_create1(flags)?;
|
||||
Ok(fd as isize)
|
||||
}
|
||||
@ -1379,7 +1376,7 @@ fn do_epoll_ctl(
|
||||
op: c_int,
|
||||
fd: c_int,
|
||||
event: *const libc::epoll_event,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
if !event.is_null() {
|
||||
check_ptr(event)?;
|
||||
}
|
||||
@ -1392,10 +1389,10 @@ fn do_epoll_wait(
|
||||
events: *mut libc::epoll_event,
|
||||
maxevents: c_int,
|
||||
timeout: c_int,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
let maxevents = {
|
||||
if maxevents <= 0 {
|
||||
return errno!(EINVAL, "maxevents <= 0");
|
||||
return_errno!(EINVAL, "maxevents <= 0");
|
||||
}
|
||||
maxevents as usize
|
||||
};
|
||||
@ -1407,7 +1404,7 @@ fn do_epoll_wait(
|
||||
Ok(count as isize)
|
||||
}
|
||||
|
||||
fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
|
||||
fn do_uname(name: *mut utsname_t) -> Result<isize> {
|
||||
check_mut_ptr(name)?;
|
||||
let name = unsafe { &mut *name };
|
||||
misc::do_uname(name).map(|_| 0)
|
||||
@ -1418,7 +1415,7 @@ fn do_prlimit(
|
||||
resource: u32,
|
||||
new_limit: *const rlimit_t,
|
||||
old_limit: *mut rlimit_t,
|
||||
) -> Result<isize, Error> {
|
||||
) -> Result<isize> {
|
||||
let resource = resource_t::from_u32(resource)?;
|
||||
let new_limit = {
|
||||
if new_limit != ptr::null() {
|
||||
@ -1439,19 +1436,19 @@ fn do_prlimit(
|
||||
misc::do_prlimit(pid, resource, new_limit, old_limit).map(|_| 0)
|
||||
}
|
||||
|
||||
fn do_access(path: *const i8, mode: u32) -> Result<isize, Error> {
|
||||
fn do_access(path: *const i8, mode: u32) -> Result<isize> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let mode = AccessModes::from_u32(mode)?;
|
||||
fs::do_access(&path, mode).map(|_| 0)
|
||||
}
|
||||
|
||||
fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result<isize, Error> {
|
||||
fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result<isize> {
|
||||
let dirfd = if dirfd >= 0 {
|
||||
Some(dirfd as FileDesc)
|
||||
} else if dirfd == AT_FDCWD {
|
||||
None
|
||||
} else {
|
||||
return errno!(EINVAL, "invalid dirfd");
|
||||
return_errno!(EINVAL, "invalid dirfd");
|
||||
};
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let mode = AccessModes::from_u32(mode)?;
|
||||
@ -1461,10 +1458,10 @@ fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result<is
|
||||
|
||||
// TODO: implement signals
|
||||
|
||||
fn do_rt_sigaction() -> Result<isize, Error> {
|
||||
fn do_rt_sigaction() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_rt_sigprocmask() -> Result<isize, Error> {
|
||||
fn do_rt_sigprocmask() -> Result<isize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ pub enum ClockID {
|
||||
|
||||
impl ClockID {
|
||||
#[deny(unreachable_patterns)]
|
||||
pub fn from_raw(clockid: clockid_t) -> Result<ClockID, Error> {
|
||||
pub fn from_raw(clockid: clockid_t) -> Result<ClockID> {
|
||||
Ok(match clockid as i32 {
|
||||
0 => ClockID::CLOCK_REALTIME,
|
||||
1 => ClockID::CLOCK_MONOTONIC,
|
||||
@ -71,12 +71,12 @@ impl ClockID {
|
||||
5 => ClockID::CLOCK_REALTIME_COARSE,
|
||||
6 => ClockID::CLOCK_MONOTONIC_COARSE,
|
||||
7 => ClockID::CLOCK_BOOTTIME,
|
||||
_ => return errno!(EINVAL, "invalid command"),
|
||||
_ => return_errno!(EINVAL, "invalid command"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_clock_gettime(clockid: ClockID) -> Result<timespec_t, Error> {
|
||||
pub fn do_clock_gettime(clockid: ClockID) -> Result<timespec_t> {
|
||||
let mut sec = 0;
|
||||
let mut nsec = 0;
|
||||
unsafe {
|
||||
|
@ -2,14 +2,14 @@ use log::*;
|
||||
|
||||
pub fn init() {
|
||||
static LOGGER: SimpleLogger = SimpleLogger;
|
||||
log::set_logger(&LOGGER).unwrap();
|
||||
log::set_max_level(match option_env!("LOG") {
|
||||
log::set_logger(&LOGGER).expect("logger cannot be set twice");
|
||||
log::set_max_level(match option_env!("LIBOS_LOG") {
|
||||
Some("error") => LevelFilter::Error,
|
||||
Some("warn") => LevelFilter::Warn,
|
||||
Some("info") => LevelFilter::Info,
|
||||
Some("debug") => LevelFilter::Debug,
|
||||
Some("trace") => LevelFilter::Trace,
|
||||
_ => LevelFilter::Off,
|
||||
_ => LevelFilter::Error, // errors are printed be default
|
||||
});
|
||||
}
|
||||
|
||||
@ -22,11 +22,13 @@ impl Log for SimpleLogger {
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
let color = Color::from(record.level());
|
||||
// TODO: add process info
|
||||
println!(
|
||||
"\u{1B}[{}m[{:>5}][{}] {}\u{1B}[0m",
|
||||
//"\u{1B}[{}m[{:>5}][{}] {}\u{1B}[0m",
|
||||
"\u{1B}[{}m[{:>5}] {}\u{1B}[0m",
|
||||
color as u8,
|
||||
record.level(),
|
||||
crate::process::current_pid(),
|
||||
//crate::process::current_pid(),
|
||||
record.args()
|
||||
);
|
||||
}
|
||||
|
@ -8,27 +8,27 @@ pub mod from_user {
|
||||
use super::*;
|
||||
|
||||
/// Check the user pointer is within the readable memory range of the user process
|
||||
pub fn check_ptr<T>(user_ptr: *const T) -> Result<(), Error> {
|
||||
pub fn check_ptr<T>(user_ptr: *const T) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check the mutable user pointer is within the writable memory of the user process
|
||||
pub fn check_mut_ptr<T>(user_ptr: *mut T) -> Result<(), Error> {
|
||||
pub fn check_mut_ptr<T>(user_ptr: *mut T) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check the readonly array is within the readable memory of the user process
|
||||
pub fn check_array<T>(user_buf: *const T, count: usize) -> Result<(), Error> {
|
||||
pub fn check_array<T>(user_buf: *const T, count: usize) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check the mutable array is within the writable memory of the user process
|
||||
pub fn check_mut_array<T>(user_buf: *mut T, count: usize) -> Result<(), Error> {
|
||||
pub fn check_mut_array<T>(user_buf: *mut T, count: usize) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clone a C-string from the user process safely
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString> {
|
||||
check_ptr(out_ptr)?;
|
||||
// TODO: using from_ptr directly is not safe
|
||||
let cstr = unsafe { CStr::from_ptr(out_ptr) };
|
||||
@ -39,7 +39,7 @@ pub mod from_user {
|
||||
/// Clone a C-string array (const char*[]) from the user process safely
|
||||
///
|
||||
/// This array must be ended with a NULL pointer.
|
||||
pub fn clone_cstrings_safely(user_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
|
||||
pub fn clone_cstrings_safely(user_ptr: *const *const c_char) -> Result<Vec<CString>> {
|
||||
let mut cstrings = Vec::new();
|
||||
if user_ptr == ptr::null() {
|
||||
return Ok(cstrings);
|
||||
@ -70,17 +70,20 @@ pub mod from_untrusted {
|
||||
use super::*;
|
||||
|
||||
/// Check the untrusted pointer is outside the enclave
|
||||
pub fn check_ptr<T>(out_ptr: *const T) -> Result<(), Error> {
|
||||
// TODO: implement this!
|
||||
pub fn check_ptr<T>(out_ptr: *const T) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check the untrusted array is outside the enclave
|
||||
pub fn check_array<T>(out_ptr: *const T, count: usize) -> Result<(), Error> {
|
||||
// TODO: implement this!
|
||||
pub fn check_array<T>(out_ptr: *const T, count: usize) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clone a C-string from outside the enclave
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
|
||||
// TODO: strict check!
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString> {
|
||||
check_ptr(out_ptr)?;
|
||||
// TODO: using from_ptr directly is not safe
|
||||
let cstr = unsafe { CStr::from_ptr(out_ptr) };
|
||||
@ -91,7 +94,8 @@ pub mod from_untrusted {
|
||||
/// Clone a C-string array (const char*[]) from outside the enclave
|
||||
///
|
||||
/// This array must be ended with a NULL pointer.
|
||||
pub fn clone_cstrings_safely(out_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
|
||||
// TODO: strict check!
|
||||
pub fn clone_cstrings_safely(out_ptr: *const *const c_char) -> Result<Vec<CString>> {
|
||||
let mut cstrings = Vec::new();
|
||||
if out_ptr == ptr::null() {
|
||||
return Ok(cstrings);
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::*;
|
||||
|
||||
pub fn mpx_enable() -> Result<(), Error> {
|
||||
pub fn mpx_enable() -> Result<()> {
|
||||
match unsafe { __mpx_enable() } {
|
||||
0 => Ok(()),
|
||||
_ => errno!(EPERM, "MPX cannot be enabled"),
|
||||
_ => Err(errno!(EPERM, "MPX cannot be enabled")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,10 +14,10 @@ pub enum MpxReg {
|
||||
BND3,
|
||||
}
|
||||
|
||||
pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<(), Error> {
|
||||
pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<()> {
|
||||
/* Check whether the upper bound overflows the max of 64-bit */
|
||||
if base.checked_add(size).is_none() {
|
||||
return errno!(ERANGE, "Upper bound overflows");
|
||||
return_errno!(ERANGE, "Upper bound overflows");
|
||||
}
|
||||
|
||||
match bndreg {
|
||||
|
@ -122,7 +122,7 @@ impl Drop for RingBufInner {
|
||||
}
|
||||
|
||||
impl RingBufReader {
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut tail = self.inner.get_tail();
|
||||
let mut buf_remain = buf.len();
|
||||
let mut buf_pos = 0;
|
||||
@ -179,9 +179,9 @@ impl Drop for RingBufReader {
|
||||
}
|
||||
|
||||
impl RingBufWriter {
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if self.inner.is_closed() {
|
||||
return errno!(EPIPE, "Reader has been closed");
|
||||
return_errno!(EPIPE, "Reader has been closed");
|
||||
}
|
||||
|
||||
let mut head = self.inner.get_head();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use fs::{File, FileDesc, FileRef};
|
||||
use prelude::*;
|
||||
use process::{get_current, Process, ProcessRef};
|
||||
use std::fmt;
|
||||
|
||||
@ -17,7 +17,7 @@ pub fn do_mmap(
|
||||
flags: MMapFlags,
|
||||
fd: FileDesc,
|
||||
offset: usize,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<usize> {
|
||||
if flags.contains(MMapFlags::MAP_ANONYMOUS) {
|
||||
info!(
|
||||
"mmap: addr: {:#x}, size: {:#x}, perms: {:?}, flags: {:?}",
|
||||
@ -39,7 +39,7 @@ pub fn do_mmap(
|
||||
current_vm.mmap(addr, size, perms, flags, fd, offset)
|
||||
}
|
||||
|
||||
pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> {
|
||||
pub fn do_munmap(addr: usize, size: usize) -> Result<()> {
|
||||
info!("munmap: addr: {:#x}, size: {:#x}", addr, size);
|
||||
let mut current_vm_ref = {
|
||||
let current_ref = get_current();
|
||||
@ -50,7 +50,7 @@ pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> {
|
||||
current_vm.munmap(addr, size)
|
||||
}
|
||||
|
||||
pub fn do_brk(addr: usize) -> Result<usize, Error> {
|
||||
pub fn do_brk(addr: usize) -> Result<usize> {
|
||||
info!("brk: addr: {:#x}", addr);
|
||||
let current_ref = get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
|
@ -41,7 +41,7 @@ impl ProcessVMBuilder {
|
||||
impl_setter_for_process_vm_builder!(stack_size);
|
||||
impl_setter_for_process_vm_builder!(mmap_size);
|
||||
|
||||
pub fn build(self) -> Result<ProcessVM, Error> {
|
||||
pub fn build(self) -> Result<ProcessVM> {
|
||||
self.validate()?;
|
||||
|
||||
let code_size = self.code_size;
|
||||
@ -111,7 +111,7 @@ impl ProcessVMBuilder {
|
||||
}
|
||||
|
||||
// TODO: implement this!
|
||||
fn validate(&self) -> Result<(), Error> {
|
||||
fn validate(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -191,16 +191,16 @@ impl ProcessVM {
|
||||
self.brk
|
||||
}
|
||||
|
||||
pub fn brk(&mut self, new_brk: usize) -> Result<usize, Error> {
|
||||
pub fn brk(&mut self, new_brk: usize) -> Result<usize> {
|
||||
let heap_start = self.heap_range.start();
|
||||
let heap_end = self.heap_range.end();
|
||||
|
||||
if new_brk == 0 {
|
||||
return Ok(self.get_brk());
|
||||
} else if new_brk < heap_start {
|
||||
return errno!(EINVAL, "New brk address is too low");
|
||||
return_errno!(EINVAL, "New brk address is too low");
|
||||
} else if new_brk > heap_end {
|
||||
return errno!(EINVAL, "New brk address is too high");
|
||||
return_errno!(EINVAL, "New brk address is too high");
|
||||
}
|
||||
|
||||
if self.brk < new_brk {
|
||||
@ -219,11 +219,11 @@ impl ProcessVM {
|
||||
flags: MMapFlags,
|
||||
fd: FileDesc,
|
||||
offset: usize,
|
||||
) -> Result<usize, Error> {
|
||||
) -> Result<usize> {
|
||||
let addr_option = {
|
||||
if flags.contains(MMapFlags::MAP_FIXED) {
|
||||
if !self.process_range.range().contains(addr) {
|
||||
return errno!(EINVAL, "Beyond valid memory range");
|
||||
return_errno!(EINVAL, "Beyond valid memory range");
|
||||
}
|
||||
VMMapAddr::Fixed(addr)
|
||||
} else {
|
||||
@ -256,11 +256,11 @@ impl ProcessVM {
|
||||
Ok(mmap_addr)
|
||||
}
|
||||
|
||||
pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> {
|
||||
pub fn munmap(&mut self, addr: usize, size: usize) -> Result<()> {
|
||||
self.mmap_manager.munmap(addr, size)
|
||||
}
|
||||
|
||||
pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange, Error> {
|
||||
pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange> {
|
||||
self.mmap_manager.find_mmap_region(addr)
|
||||
}
|
||||
}
|
||||
@ -289,9 +289,9 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl MMapFlags {
|
||||
pub fn from_u32(bits: u32) -> Result<MMapFlags, Error> {
|
||||
pub fn from_u32(bits: u32) -> Result<MMapFlags> {
|
||||
// TODO: detect non-supporting flags
|
||||
MMapFlags::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown mmap flags").into())
|
||||
MMapFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown mmap flags"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,8 +316,8 @@ impl VMPerms {
|
||||
self.contains(VMPerms::EXEC)
|
||||
}
|
||||
|
||||
pub fn from_u32(bits: u32) -> Result<VMPerms, Error> {
|
||||
VMPerms::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown permission bits").into())
|
||||
pub fn from_u32(bits: u32) -> Result<VMPerms> {
|
||||
VMPerms::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown permission bits"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,12 @@ pub struct UserSpaceVMManager {
|
||||
}
|
||||
|
||||
impl UserSpaceVMManager {
|
||||
pub unsafe fn from(addr: usize, size: usize) -> Result<UserSpaceVMManager, Error> {
|
||||
pub unsafe fn from(addr: usize, size: usize) -> Result<UserSpaceVMManager> {
|
||||
let vm_manager = Arc::new(SgxMutex::new(VMManager::from(addr, size)?));
|
||||
Ok(UserSpaceVMManager { vm_manager })
|
||||
}
|
||||
|
||||
pub fn alloc(&self, size: usize) -> Result<UserSpaceVMRange, Error> {
|
||||
pub fn alloc(&self, size: usize) -> Result<UserSpaceVMRange> {
|
||||
let user_vm_range = unsafe {
|
||||
let mmap_options = VMMapOptionsBuilder::default().size(size).build()?;
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
use super::*;
|
||||
use std::slice;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum VMInitializer {
|
||||
@ -15,7 +14,7 @@ impl Default for VMInitializer {
|
||||
}
|
||||
|
||||
impl VMInitializer {
|
||||
pub fn initialize(&self, buf: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn initialize(&self, buf: &mut [u8]) -> Result<()> {
|
||||
match self {
|
||||
VMInitializer::DoNothing() => {
|
||||
// Do nothing
|
||||
@ -27,7 +26,9 @@ impl VMInitializer {
|
||||
}
|
||||
VMInitializer::LoadFromFile { file, offset } => {
|
||||
// TODO: make sure that read_at does not move file cursor
|
||||
let len = file.read_at(*offset, buf)?;
|
||||
let len = file
|
||||
.read_at(*offset, buf)
|
||||
.cause_err(|_| errno!(EIO, "failed to init memory from file"))?;
|
||||
for b in &mut buf[len..] {
|
||||
*b = 0;
|
||||
}
|
||||
@ -61,20 +62,20 @@ pub struct VMMapOptions {
|
||||
|
||||
// VMMapOptionsBuilder is generated automatically, except the build function
|
||||
impl VMMapOptionsBuilder {
|
||||
pub fn build(&self) -> Result<VMMapOptions, Error> {
|
||||
pub fn build(&self) -> Result<VMMapOptions> {
|
||||
let size = {
|
||||
let size = self
|
||||
.size
|
||||
.ok_or_else(|| (Errno::EINVAL, "Invalid size for mmap"))?;
|
||||
.ok_or_else(|| errno!(EINVAL, "invalid size for mmap"))?;
|
||||
if size == 0 {
|
||||
return errno!(EINVAL, "Invalid size for mmap");
|
||||
return_errno!(EINVAL, "invalid size for mmap");
|
||||
}
|
||||
align_up(size, PAGE_SIZE)
|
||||
};
|
||||
let align = {
|
||||
let align = self.align.unwrap_or(PAGE_SIZE);
|
||||
if align == 0 || align % PAGE_SIZE != 0 {
|
||||
return errno!(EINVAL, "Invalid size for mmap");
|
||||
return_errno!(EINVAL, "invalid size for mmap");
|
||||
}
|
||||
align
|
||||
};
|
||||
@ -89,7 +90,7 @@ impl VMMapOptionsBuilder {
|
||||
}
|
||||
VMMapAddr::Fixed(addr) => {
|
||||
if addr % align != 0 {
|
||||
return errno!(EINVAL, "Unaligned addr for fixed mmap");
|
||||
return_errno!(EINVAL, "unaligned addr for fixed mmap");
|
||||
}
|
||||
VMMapAddr::Fixed(addr)
|
||||
}
|
||||
@ -129,7 +130,7 @@ pub struct VMManager {
|
||||
}
|
||||
|
||||
impl VMManager {
|
||||
pub fn from(addr: usize, size: usize) -> Result<VMManager, Error> {
|
||||
pub fn from(addr: usize, size: usize) -> Result<VMManager> {
|
||||
let range = VMRange::from(addr, addr + size)?;
|
||||
let sub_ranges = {
|
||||
let start = range.start();
|
||||
@ -145,7 +146,7 @@ impl VMManager {
|
||||
&self.range
|
||||
}
|
||||
|
||||
pub fn mmap(&mut self, options: &VMMapOptions) -> Result<usize, Error> {
|
||||
pub fn mmap(&mut self, options: &VMMapOptions) -> Result<usize> {
|
||||
// TODO: respect options.align when mmap
|
||||
let addr = *options.addr();
|
||||
let size = *options.size();
|
||||
@ -163,7 +164,7 @@ impl VMManager {
|
||||
unsafe {
|
||||
let buf_ptr = new_subrange.start() as *mut u8;
|
||||
let buf_size = new_subrange.size() as usize;
|
||||
let buf = slice::from_raw_parts_mut(buf_ptr, buf_size);
|
||||
let buf = std::slice::from_raw_parts_mut(buf_ptr, buf_size);
|
||||
options.initializer.initialize(buf)?;
|
||||
}
|
||||
|
||||
@ -173,10 +174,10 @@ impl VMManager {
|
||||
Ok(new_subrange_addr)
|
||||
}
|
||||
|
||||
pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> {
|
||||
pub fn munmap(&mut self, addr: usize, size: usize) -> Result<()> {
|
||||
let size = {
|
||||
if size == 0 {
|
||||
return errno!(EINVAL, "size of munmap must not be zero");
|
||||
return_errno!(EINVAL, "size of munmap must not be zero");
|
||||
}
|
||||
align_up(size, PAGE_SIZE)
|
||||
};
|
||||
@ -211,22 +212,15 @@ impl VMManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange, Error> {
|
||||
pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange> {
|
||||
self.sub_ranges
|
||||
.iter()
|
||||
.find(|subrange| subrange.contains(addr))
|
||||
.ok_or(Error::new(
|
||||
Errno::ESRCH,
|
||||
"no mmap regions that contains the address",
|
||||
))
|
||||
.ok_or_else(|| errno!(ESRCH, "no mmap regions that contains the address"))
|
||||
}
|
||||
|
||||
// Find the free subrange that satisfies the constraints of size and address
|
||||
fn find_free_subrange(
|
||||
&mut self,
|
||||
size: usize,
|
||||
addr: VMMapAddr,
|
||||
) -> Result<(usize, VMRange), Error> {
|
||||
fn find_free_subrange(&mut self, size: usize, addr: VMMapAddr) -> Result<(usize, VMRange)> {
|
||||
// TODO: reduce the complexity from O(N) to O(log(N)), where N is
|
||||
// the number of existing subranges.
|
||||
|
||||
@ -268,13 +262,13 @@ impl VMManager {
|
||||
// Must have free_range.start == addr
|
||||
VMMapAddr::Fixed(addr) => {
|
||||
if free_range.start() > addr {
|
||||
return errno!(ENOMEM, "Not enough memory for fixed mmap");
|
||||
return_errno!(ENOMEM, "not enough memory for fixed mmap");
|
||||
}
|
||||
if !free_range.contains(addr) {
|
||||
continue;
|
||||
}
|
||||
if free_range.end() - addr < size {
|
||||
return errno!(ENOMEM, "Not enough memory for fixed mmap");
|
||||
return_errno!(ENOMEM, "not enough memory for fixed mmap");
|
||||
}
|
||||
free_range.start = addr;
|
||||
let insert_idx = idx + 1;
|
||||
@ -291,7 +285,7 @@ impl VMManager {
|
||||
}
|
||||
|
||||
if result_free_range.is_none() {
|
||||
return errno!(ENOMEM, "Cannot find enough memory");
|
||||
return_errno!(ENOMEM, "not enough memory");
|
||||
}
|
||||
|
||||
let free_range = result_free_range.unwrap();
|
||||
@ -324,9 +318,9 @@ pub struct VMRange {
|
||||
}
|
||||
|
||||
impl VMRange {
|
||||
pub fn from(start: usize, end: usize) -> Result<VMRange, Error> {
|
||||
pub fn from(start: usize, end: usize) -> Result<VMRange> {
|
||||
if start % PAGE_SIZE != 0 || end % PAGE_SIZE != 0 || start > end {
|
||||
return errno!(EINVAL, "invalid start or end");
|
||||
return_errno!(EINVAL, "invalid start or end");
|
||||
}
|
||||
Ok(VMRange {
|
||||
start: start,
|
||||
|
Loading…
Reference in New Issue
Block a user