Initial error refactor
This commit is contained in:
committed by
Jakub Konka
parent
85a41d449c
commit
14aaffd46f
32
src/ctx.rs
32
src/ctx.rs
@@ -1,6 +1,6 @@
|
|||||||
use crate::fdentry::FdEntry;
|
use crate::fdentry::FdEntry;
|
||||||
use crate::sys::{dev_null, errno_from_ioerror};
|
use crate::sys::dev_null;
|
||||||
use crate::{host, Result};
|
use crate::{host, Error, Result};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
@@ -33,7 +33,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
pub fn args<S: AsRef<str>>(mut self, args: impl Iterator<Item = S>) -> Result<Self> {
|
pub fn args<S: AsRef<str>>(mut self, args: impl Iterator<Item = S>) -> Result<Self> {
|
||||||
let args: Result<Vec<CString>> = args
|
let args: Result<Vec<CString>> = args
|
||||||
.map(|arg| CString::new(arg.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE))
|
.map(|arg| CString::new(arg.as_ref()).map_err(|_| Error::ENOTCAPABLE))
|
||||||
.collect();
|
.collect();
|
||||||
self.args = args?;
|
self.args = args?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
@@ -41,7 +41,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
pub fn arg(mut self, arg: &str) -> Result<Self> {
|
pub fn arg(mut self, arg: &str) -> Result<Self> {
|
||||||
self.args
|
self.args
|
||||||
.push(CString::new(arg).map_err(|_| host::__WASI_ENOTCAPABLE)?);
|
.push(CString::new(arg).map_err(|_| Error::ENOTCAPABLE)?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,8 +58,8 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
pub fn env<S: AsRef<str>>(mut self, k: S, v: S) -> Result<Self> {
|
pub fn env<S: AsRef<str>>(mut self, k: S, v: S) -> Result<Self> {
|
||||||
self.env.insert(
|
self.env.insert(
|
||||||
CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?,
|
CString::new(k.as_ref()).map_err(|_| Error::ENOTCAPABLE)?,
|
||||||
CString::new(v.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?,
|
CString::new(v.as_ref()).map_err(|_| Error::ENOTCAPABLE)?,
|
||||||
);
|
);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
@@ -71,11 +71,11 @@ impl WasiCtxBuilder {
|
|||||||
let env: Result<HashMap<CString, CString>> = envs
|
let env: Result<HashMap<CString, CString>> = envs
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let (k, v) = t.borrow();
|
let (k, v) = t.borrow();
|
||||||
let k = CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE);
|
let k = CString::new(k.as_ref()).map_err(|_| Error::ENOTCAPABLE);
|
||||||
let v = CString::new(v.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE);
|
let v = CString::new(v.as_ref()).map_err(|_| Error::ENOTCAPABLE);
|
||||||
match (k, v) {
|
match (k, v) {
|
||||||
(Ok(k), Ok(v)) => Ok((k, v)),
|
(Ok(k), Ok(v)) => Ok((k, v)),
|
||||||
_ => Err(host::__WASI_ENOTCAPABLE),
|
_ => Err(Error::ENOTCAPABLE),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -92,12 +92,12 @@ impl WasiCtxBuilder {
|
|||||||
// startup code starts looking at fd 3 for preopens
|
// startup code starts looking at fd 3 for preopens
|
||||||
let mut preopen_fd = 3;
|
let mut preopen_fd = 3;
|
||||||
for (guest_path, dir) in self.preopens {
|
for (guest_path, dir) in self.preopens {
|
||||||
if !dir.metadata().map_err(errno_from_ioerror)?.is_dir() {
|
if !dir.metadata()?.is_dir() {
|
||||||
return Err(host::__WASI_EBADF);
|
return Err(Error::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
while self.fds.contains_key(&preopen_fd) {
|
while self.fds.contains_key(&preopen_fd) {
|
||||||
preopen_fd = preopen_fd.checked_add(1).ok_or(host::__WASI_ENFILE)?;
|
preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?;
|
||||||
}
|
}
|
||||||
let mut fe = FdEntry::from(dir)?;
|
let mut fe = FdEntry::from(dir)?;
|
||||||
fe.preopen_path = Some(guest_path);
|
fe.preopen_path = Some(guest_path);
|
||||||
@@ -161,7 +161,7 @@ impl WasiCtx {
|
|||||||
if let Some(fe) = self.fds.get(&fd) {
|
if let Some(fe) = self.fds.get(&fd) {
|
||||||
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
|
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
|
||||||
} else {
|
} else {
|
||||||
Err(host::__WASI_EBADF)
|
Err(Error::EBADF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ impl WasiCtx {
|
|||||||
if let Some(fe) = self.fds.get_mut(&fd) {
|
if let Some(fe) = self.fds.get_mut(&fd) {
|
||||||
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
|
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
|
||||||
} else {
|
} else {
|
||||||
Err(host::__WASI_EBADF)
|
Err(Error::EBADF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ impl WasiCtx {
|
|||||||
rights_inheriting: host::__wasi_rights_t,
|
rights_inheriting: host::__wasi_rights_t,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if !fe.rights_base & rights_base != 0 || !fe.rights_inheriting & rights_inheriting != 0 {
|
if !fe.rights_base & rights_base != 0 || !fe.rights_inheriting & rights_inheriting != 0 {
|
||||||
Err(host::__WASI_ENOTCAPABLE)
|
Err(Error::ENOTCAPABLE)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ impl WasiCtx {
|
|||||||
if let Some(next_fd) = fd.checked_add(1) {
|
if let Some(next_fd) = fd.checked_add(1) {
|
||||||
fd = next_fd;
|
fd = next_fd;
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EMFILE);
|
return Err(Error::EMFILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.fds.insert(fd, fe);
|
self.fds.insert(fd, fe);
|
||||||
|
|||||||
223
src/error.rs
Normal file
223
src/error.rs
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
use crate::host;
|
||||||
|
use crate::sys::errno_from_ioerror;
|
||||||
|
use std::num::TryFromIntError;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum WasiError {
|
||||||
|
ESUCCESS = 0,
|
||||||
|
E2BIG = 1,
|
||||||
|
EACCES = 2,
|
||||||
|
EADDRINUSE = 3,
|
||||||
|
EADDRNOTAVAIL = 4,
|
||||||
|
EAFNOSUPPORT = 5,
|
||||||
|
EAGAIN = 6,
|
||||||
|
EALREADY = 7,
|
||||||
|
EBADF = 8,
|
||||||
|
EBADMSG = 9,
|
||||||
|
EBUSY = 10,
|
||||||
|
ECANCELED = 11,
|
||||||
|
ECHILD = 12,
|
||||||
|
ECONNABORTED = 13,
|
||||||
|
ECONNREFUSED = 14,
|
||||||
|
ECONNRESET = 15,
|
||||||
|
EDEADLK = 16,
|
||||||
|
EDESTADDRREQ = 17,
|
||||||
|
EDOM = 18,
|
||||||
|
EDQUOT = 19,
|
||||||
|
EEXIST = 20,
|
||||||
|
EFAULT = 21,
|
||||||
|
EFBIG = 22,
|
||||||
|
EHOSTUNREACH = 23,
|
||||||
|
EIDRM = 24,
|
||||||
|
EILSEQ = 25,
|
||||||
|
EINPROGRESS = 26,
|
||||||
|
EINTR = 27,
|
||||||
|
EINVAL = 28,
|
||||||
|
EIO = 29,
|
||||||
|
EISCONN = 30,
|
||||||
|
EISDIR = 31,
|
||||||
|
ELOOP = 32,
|
||||||
|
EMFILE = 33,
|
||||||
|
EMLINK = 34,
|
||||||
|
EMSGSIZE = 35,
|
||||||
|
EMULTIHOP = 36,
|
||||||
|
ENAMETOOLONG = 37,
|
||||||
|
ENETDOWN = 38,
|
||||||
|
ENETRESET = 39,
|
||||||
|
ENETUNREACH = 40,
|
||||||
|
ENFILE = 41,
|
||||||
|
ENOBUFS = 42,
|
||||||
|
ENODEV = 43,
|
||||||
|
ENOENT = 44,
|
||||||
|
ENOEXEC = 45,
|
||||||
|
ENOLCK = 46,
|
||||||
|
ENOLINK = 47,
|
||||||
|
ENOMEM = 48,
|
||||||
|
ENOMSG = 49,
|
||||||
|
ENOPROTOOPT = 50,
|
||||||
|
ENOSPC = 51,
|
||||||
|
ENOSYS = 52,
|
||||||
|
ENOTCONN = 53,
|
||||||
|
ENOTDIR = 54,
|
||||||
|
ENOTEMPTY = 55,
|
||||||
|
ENOTRECOVERABLE = 56,
|
||||||
|
ENOTSOCK = 57,
|
||||||
|
ENOTSUP = 58,
|
||||||
|
ENOTTY = 59,
|
||||||
|
ENXIO = 60,
|
||||||
|
EOVERFLOW = 61,
|
||||||
|
EOWNERDEAD = 62,
|
||||||
|
EPERM = 63,
|
||||||
|
EPIPE = 64,
|
||||||
|
EPROTO = 65,
|
||||||
|
EPROTONOSUPPORT = 66,
|
||||||
|
EPROTOTYPE = 67,
|
||||||
|
ERANGE = 68,
|
||||||
|
EROFS = 69,
|
||||||
|
ESPIPE = 70,
|
||||||
|
ESRCH = 71,
|
||||||
|
ESTALE = 72,
|
||||||
|
ETIMEDOUT = 73,
|
||||||
|
ETXTBSY = 74,
|
||||||
|
EXDEV = 75,
|
||||||
|
ENOTCAPABLE = 76,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiError {
|
||||||
|
pub fn as_raw_errno(&self) -> host::__wasi_errno_t {
|
||||||
|
*self as host::__wasi_errno_t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Error {
|
||||||
|
Wasi(WasiError),
|
||||||
|
Io(std::io::Error),
|
||||||
|
#[cfg(unix)]
|
||||||
|
Nix(nix::Error),
|
||||||
|
#[cfg(windows)]
|
||||||
|
Win(winx::winerror::WinError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WasiError> for Error {
|
||||||
|
fn from(err: WasiError) -> Self {
|
||||||
|
Self::Wasi(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl From<nix::Error> for Error {
|
||||||
|
fn from(err: nix::Error) -> Self {
|
||||||
|
Self::Nix(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
Self::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TryFromIntError> for Error {
|
||||||
|
fn from(_: TryFromIntError) -> Self {
|
||||||
|
Self::Wasi(WasiError::EOVERFLOW)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl From<winx::winerror::WinError> for Error {
|
||||||
|
fn from(err: winx::winerror::WinError) -> Self {
|
||||||
|
Self::Win(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub(crate) fn as_wasi_errno(&self) -> host::__wasi_errno_t {
|
||||||
|
match self {
|
||||||
|
Self::Wasi(no) => no.as_raw_errno(),
|
||||||
|
#[cfg(unix)]
|
||||||
|
Self::Nix(err) => {
|
||||||
|
crate::sys::host_impl::errno_from_nix(err.as_errno().unwrap()).as_wasi_errno()
|
||||||
|
} // FIXME unwrap
|
||||||
|
Self::Io(e) => errno_from_ioerror(e.to_owned()), // fixme clone
|
||||||
|
#[cfg(windows)]
|
||||||
|
Self::Win(err) => crate::sys::host_impl::errno_from_win(*err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const ESUCCESS: Self = Error::Wasi(WasiError::ESUCCESS);
|
||||||
|
pub const E2BIG: Self = Error::Wasi(WasiError::E2BIG);
|
||||||
|
pub const EACCES: Self = Error::Wasi(WasiError::EACCES);
|
||||||
|
pub const EADDRINUSE: Self = Error::Wasi(WasiError::EADDRINUSE);
|
||||||
|
pub const EADDRNOTAVAIL: Self = Error::Wasi(WasiError::EADDRNOTAVAIL);
|
||||||
|
pub const EAFNOSUPPORT: Self = Error::Wasi(WasiError::EAFNOSUPPORT);
|
||||||
|
pub const EAGAIN: Self = Error::Wasi(WasiError::EAGAIN);
|
||||||
|
pub const EALREADY: Self = Error::Wasi(WasiError::EALREADY);
|
||||||
|
pub const EBADF: Self = Error::Wasi(WasiError::EBADF);
|
||||||
|
pub const EBADMSG: Self = Error::Wasi(WasiError::EBADMSG);
|
||||||
|
pub const EBUSY: Self = Error::Wasi(WasiError::EBUSY);
|
||||||
|
pub const ECANCELED: Self = Error::Wasi(WasiError::ECANCELED);
|
||||||
|
pub const ECHILD: Self = Error::Wasi(WasiError::ECHILD);
|
||||||
|
pub const ECONNABORTED: Self = Error::Wasi(WasiError::ECONNABORTED);
|
||||||
|
pub const ECONNREFUSED: Self = Error::Wasi(WasiError::ECONNREFUSED);
|
||||||
|
pub const ECONNRESET: Self = Error::Wasi(WasiError::ECONNRESET);
|
||||||
|
pub const EDEADLK: Self = Error::Wasi(WasiError::EDEADLK);
|
||||||
|
pub const EDESTADDRREQ: Self = Error::Wasi(WasiError::EDESTADDRREQ);
|
||||||
|
pub const EDOM: Self = Error::Wasi(WasiError::EDOM);
|
||||||
|
pub const EDQUOT: Self = Error::Wasi(WasiError::EDQUOT);
|
||||||
|
pub const EEXIST: Self = Error::Wasi(WasiError::EEXIST);
|
||||||
|
pub const EFAULT: Self = Error::Wasi(WasiError::EFAULT);
|
||||||
|
pub const EFBIG: Self = Error::Wasi(WasiError::EFBIG);
|
||||||
|
pub const EHOSTUNREACH: Self = Error::Wasi(WasiError::EHOSTUNREACH);
|
||||||
|
pub const EIDRM: Self = Error::Wasi(WasiError::EIDRM);
|
||||||
|
pub const EILSEQ: Self = Error::Wasi(WasiError::EILSEQ);
|
||||||
|
pub const EINPROGRESS: Self = Error::Wasi(WasiError::EINPROGRESS);
|
||||||
|
pub const EINTR: Self = Error::Wasi(WasiError::EINTR);
|
||||||
|
pub const EINVAL: Self = Error::Wasi(WasiError::EINVAL);
|
||||||
|
pub const EIO: Self = Error::Wasi(WasiError::EIO);
|
||||||
|
pub const EISCONN: Self = Error::Wasi(WasiError::EISCONN);
|
||||||
|
pub const EISDIR: Self = Error::Wasi(WasiError::EISDIR);
|
||||||
|
pub const ELOOP: Self = Error::Wasi(WasiError::ELOOP);
|
||||||
|
pub const EMFILE: Self = Error::Wasi(WasiError::EMFILE);
|
||||||
|
pub const EMLINK: Self = Error::Wasi(WasiError::EMLINK);
|
||||||
|
pub const EMSGSIZE: Self = Error::Wasi(WasiError::EMSGSIZE);
|
||||||
|
pub const EMULTIHOP: Self = Error::Wasi(WasiError::EMULTIHOP);
|
||||||
|
pub const ENAMETOOLONG: Self = Error::Wasi(WasiError::ENAMETOOLONG);
|
||||||
|
pub const ENETDOWN: Self = Error::Wasi(WasiError::ENETDOWN);
|
||||||
|
pub const ENETRESET: Self = Error::Wasi(WasiError::ENETRESET);
|
||||||
|
pub const ENETUNREACH: Self = Error::Wasi(WasiError::ENETUNREACH);
|
||||||
|
pub const ENFILE: Self = Error::Wasi(WasiError::ENFILE);
|
||||||
|
pub const ENOBUFS: Self = Error::Wasi(WasiError::ENOBUFS);
|
||||||
|
pub const ENODEV: Self = Error::Wasi(WasiError::ENODEV);
|
||||||
|
pub const ENOENT: Self = Error::Wasi(WasiError::ENOENT);
|
||||||
|
pub const ENOEXEC: Self = Error::Wasi(WasiError::ENOEXEC);
|
||||||
|
pub const ENOLCK: Self = Error::Wasi(WasiError::ENOLCK);
|
||||||
|
pub const ENOLINK: Self = Error::Wasi(WasiError::ENOLINK);
|
||||||
|
pub const ENOMEM: Self = Error::Wasi(WasiError::ENOMEM);
|
||||||
|
pub const ENOMSG: Self = Error::Wasi(WasiError::ENOMSG);
|
||||||
|
pub const ENOPROTOOPT: Self = Error::Wasi(WasiError::ENOPROTOOPT);
|
||||||
|
pub const ENOSPC: Self = Error::Wasi(WasiError::ENOSPC);
|
||||||
|
pub const ENOSYS: Self = Error::Wasi(WasiError::ENOSYS);
|
||||||
|
pub const ENOTCONN: Self = Error::Wasi(WasiError::ENOTCONN);
|
||||||
|
pub const ENOTDIR: Self = Error::Wasi(WasiError::ENOTDIR);
|
||||||
|
pub const ENOTEMPTY: Self = Error::Wasi(WasiError::ENOTEMPTY);
|
||||||
|
pub const ENOTRECOVERABLE: Self = Error::Wasi(WasiError::ENOTRECOVERABLE);
|
||||||
|
pub const ENOTSOCK: Self = Error::Wasi(WasiError::ENOTSOCK);
|
||||||
|
pub const ENOTSUP: Self = Error::Wasi(WasiError::ENOTSUP);
|
||||||
|
pub const ENOTTY: Self = Error::Wasi(WasiError::ENOTTY);
|
||||||
|
pub const ENXIO: Self = Error::Wasi(WasiError::ENXIO);
|
||||||
|
pub const EOVERFLOW: Self = Error::Wasi(WasiError::EOVERFLOW);
|
||||||
|
pub const EOWNERDEAD: Self = Error::Wasi(WasiError::EOWNERDEAD);
|
||||||
|
pub const EPERM: Self = Error::Wasi(WasiError::EPERM);
|
||||||
|
pub const EPIPE: Self = Error::Wasi(WasiError::EPIPE);
|
||||||
|
pub const EPROTO: Self = Error::Wasi(WasiError::EPROTO);
|
||||||
|
pub const EPROTONOSUPPORT: Self = Error::Wasi(WasiError::EPROTONOSUPPORT);
|
||||||
|
pub const EPROTOTYPE: Self = Error::Wasi(WasiError::EPROTOTYPE);
|
||||||
|
pub const ERANGE: Self = Error::Wasi(WasiError::ERANGE);
|
||||||
|
pub const EROFS: Self = Error::Wasi(WasiError::EROFS);
|
||||||
|
pub const ESPIPE: Self = Error::Wasi(WasiError::ESPIPE);
|
||||||
|
pub const ESRCH: Self = Error::Wasi(WasiError::ESRCH);
|
||||||
|
pub const ESTALE: Self = Error::Wasi(WasiError::ESTALE);
|
||||||
|
pub const ETIMEDOUT: Self = Error::Wasi(WasiError::ETIMEDOUT);
|
||||||
|
pub const ETXTBSY: Self = Error::Wasi(WasiError::ETXTBSY);
|
||||||
|
pub const EXDEV: Self = Error::Wasi(WasiError::EXDEV);
|
||||||
|
pub const ENOTCAPABLE: Self = Error::Wasi(WasiError::ENOTCAPABLE);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::sys::{errno_from_ioerror, fdentry_impl};
|
use crate::sys::fdentry_impl;
|
||||||
use crate::{host, Result};
|
use crate::{host, Error, Result};
|
||||||
|
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -17,7 +17,7 @@ impl Descriptor {
|
|||||||
pub fn as_file(&self) -> Result<&fs::File> {
|
pub fn as_file(&self) -> Result<&fs::File> {
|
||||||
match self {
|
match self {
|
||||||
Descriptor::File(f) => Ok(f),
|
Descriptor::File(f) => Ok(f),
|
||||||
_ => Err(host::__WASI_EBADF),
|
_ => Err(Error::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +91,7 @@ impl FdEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn duplicate(file: &fs::File) -> Result<Self> {
|
pub fn duplicate(file: &fs::File) -> Result<Self> {
|
||||||
file.try_clone()
|
Self::from(file.try_clone()?)
|
||||||
.map_err(errno_from_ioerror)
|
|
||||||
.and_then(Self::from)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn duplicate_stdin() -> Result<Self> {
|
pub fn duplicate_stdin() -> Result<Self> {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use crate::{host, Result};
|
use crate::{Error, Result};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
|
pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
|
||||||
st.duration_since(UNIX_EPOCH)
|
st.duration_since(UNIX_EPOCH)
|
||||||
.map_err(|_| host::__WASI_EINVAL)? // date earlier than UNIX_EPOCH
|
.map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH
|
||||||
.as_nanos()
|
.as_nanos()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| host::__WASI_EOVERFLOW) // u128 doesn't fit into u64
|
.map_err(|_| Error::EOVERFLOW) // u128 doesn't fit into u64
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! still largely reflects that.
|
//! still largely reflects that.
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
use crate::Result;
|
use crate::{Error, Result};
|
||||||
use std::{io, slice, str};
|
use std::{io, slice, str};
|
||||||
|
|
||||||
pub type void = ::std::os::raw::c_void;
|
pub type void = ::std::os::raw::c_void;
|
||||||
@@ -500,7 +500,7 @@ pub unsafe fn iovec_to_host_mut<'a>(iovec: &'a mut __wasi_iovec_t) -> io::IoSlic
|
|||||||
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_EILSEQ` error is returned.
|
/// `__WASI_EILSEQ` error is returned.
|
||||||
pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
|
pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
|
||||||
str::from_utf8(s).map_err(|_| __WASI_EILSEQ)
|
str::from_utf8(s).map_err(|_| Error::EILSEQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates owned WASI path from byte vector.
|
/// Creates owned WASI path from byte vector.
|
||||||
@@ -508,7 +508,7 @@ pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
|
|||||||
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_EILSEQ` error is returned.
|
/// `__WASI_EILSEQ` error is returned.
|
||||||
pub fn path_from_vec<S: Into<Vec<u8>>>(s: S) -> Result<String> {
|
pub fn path_from_vec<S: Into<Vec<u8>>>(s: S) -> Result<String> {
|
||||||
String::from_utf8(s.into()).map_err(|_| __WASI_EILSEQ)
|
String::from_utf8(s.into()).map_err(|_| Error::EILSEQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use crate::fdentry::{Descriptor, FdEntry};
|
|||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sys::fdentry_impl::determine_type_rights;
|
use crate::sys::fdentry_impl::determine_type_rights;
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
||||||
use crate::sys::{errno_from_ioerror, host_impl, hostcalls_impl};
|
use crate::sys::{host_impl, hostcalls_impl};
|
||||||
use crate::{host, wasm32, Result};
|
use crate::{host, wasm32, Error, Result};
|
||||||
use filetime::{set_file_handle_times, FileTime};
|
use filetime::{set_file_handle_times, FileTime};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -20,11 +20,11 @@ pub(crate) fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasm32::__wasi_fd_t) -> Resul
|
|||||||
if let Some(fdent) = wasi_ctx.fds.get(&fd) {
|
if let Some(fdent) = wasi_ctx.fds.get(&fd) {
|
||||||
// can't close preopened files
|
// can't close preopened files
|
||||||
if fdent.preopen_path.is_some() {
|
if fdent.preopen_path.is_some() {
|
||||||
return Err(host::__WASI_ENOTSUP);
|
return Err(Error::ENOTSUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut fe = wasi_ctx.fds.remove(&fd).ok_or(host::__WASI_EBADF)?;
|
let mut fe = wasi_ctx.fds.remove(&fd).ok_or(Error::EBADF)?;
|
||||||
fe.fd_object.needs_close = true;
|
fe.fd_object.needs_close = true;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -38,7 +38,7 @@ pub(crate) fn fd_datasync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result
|
|||||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_DATASYNC, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_FD_DATASYNC, 0)
|
||||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||||
|
|
||||||
fd.sync_data().map_err(errno_from_ioerror)
|
fd.sync_data().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_pread(
|
pub(crate) fn fd_pread(
|
||||||
@@ -68,7 +68,7 @@ pub(crate) fn fd_pread(
|
|||||||
|
|
||||||
let offset = dec_filesize(offset);
|
let offset = dec_filesize(offset);
|
||||||
if offset > i64::max_value() as u64 {
|
if offset > i64::max_value() as u64 {
|
||||||
return Err(host::__WASI_EIO);
|
return Err(Error::EIO);
|
||||||
}
|
}
|
||||||
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||||
let mut buf = vec![0; buf_size];
|
let mut buf = vec![0; buf_size];
|
||||||
@@ -117,7 +117,7 @@ pub(crate) fn fd_pwrite(
|
|||||||
|
|
||||||
let offset = dec_filesize(offset);
|
let offset = dec_filesize(offset);
|
||||||
if offset > i64::max_value() as u64 {
|
if offset > i64::max_value() as u64 {
|
||||||
return Err(host::__WASI_EIO);
|
return Err(Error::EIO);
|
||||||
}
|
}
|
||||||
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||||
let mut buf = Vec::with_capacity(buf_size);
|
let mut buf = Vec::with_capacity(buf_size);
|
||||||
@@ -160,10 +160,10 @@ pub(crate) fn fd_read(
|
|||||||
let maybe_host_nread = match &mut *fe.fd_object.descriptor {
|
let maybe_host_nread = match &mut *fe.fd_object.descriptor {
|
||||||
Descriptor::File(f) => f.read_vectored(&mut iovs),
|
Descriptor::File(f) => f.read_vectored(&mut iovs),
|
||||||
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
||||||
_ => return Err(host::__WASI_EBADF),
|
_ => return Err(Error::EBADF),
|
||||||
};
|
};
|
||||||
|
|
||||||
let host_nread = maybe_host_nread.map_err(errno_from_ioerror)?;
|
let host_nread = maybe_host_nread?;
|
||||||
|
|
||||||
trace!(" | *nread={:?}", host_nread);
|
trace!(" | *nread={:?}", host_nread);
|
||||||
|
|
||||||
@@ -181,14 +181,14 @@ pub(crate) fn fd_renumber(
|
|||||||
let to = dec_fd(to);
|
let to = dec_fd(to);
|
||||||
|
|
||||||
if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) {
|
if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) {
|
||||||
return Err(host::__WASI_EBADF);
|
return Err(Error::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow renumbering over a pre-opened resource.
|
// Don't allow renumbering over a pre-opened resource.
|
||||||
// TODO: Eventually, we do want to permit this, once libpreopen in
|
// TODO: Eventually, we do want to permit this, once libpreopen in
|
||||||
// userspace is capable of removing entries from its tables as well.
|
// userspace is capable of removing entries from its tables as well.
|
||||||
if wasi_ctx.fds[&from].preopen_path.is_some() || wasi_ctx.fds[&to].preopen_path.is_some() {
|
if wasi_ctx.fds[&from].preopen_path.is_some() || wasi_ctx.fds[&to].preopen_path.is_some() {
|
||||||
return Err(host::__WASI_ENOTSUP);
|
return Err(Error::ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if stdio fds
|
// check if stdio fds
|
||||||
@@ -196,7 +196,7 @@ pub(crate) fn fd_renumber(
|
|||||||
if !wasi_ctx.fds[&from].fd_object.descriptor.is_file()
|
if !wasi_ctx.fds[&from].fd_object.descriptor.is_file()
|
||||||
|| !wasi_ctx.fds[&to].fd_object.descriptor.is_file()
|
|| !wasi_ctx.fds[&to].fd_object.descriptor.is_file()
|
||||||
{
|
{
|
||||||
return Err(host::__WASI_EBADF);
|
return Err(Error::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fe_from_dup = wasi_ctx.fds[&from]
|
let fe_from_dup = wasi_ctx.fds[&from]
|
||||||
@@ -244,9 +244,9 @@ pub(crate) fn fd_seek(
|
|||||||
host::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
host::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
||||||
host::__WASI_WHENCE_END => SeekFrom::End(offset),
|
host::__WASI_WHENCE_END => SeekFrom::End(offset),
|
||||||
host::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
host::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
};
|
};
|
||||||
let host_newoffset = fd.seek(pos).map_err(errno_from_ioerror)?;
|
let host_newoffset = fd.seek(pos)?;
|
||||||
|
|
||||||
trace!(" | *newoffset={:?}", host_newoffset);
|
trace!(" | *newoffset={:?}", host_newoffset);
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ pub(crate) fn fd_tell(
|
|||||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_TELL, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_FD_TELL, 0)
|
||||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||||
|
|
||||||
let host_offset = fd.seek(SeekFrom::Current(0)).map_err(errno_from_ioerror)?;
|
let host_offset = fd.seek(SeekFrom::Current(0))?;
|
||||||
|
|
||||||
trace!(" | *newoffset={:?}", host_offset);
|
trace!(" | *newoffset={:?}", host_offset);
|
||||||
|
|
||||||
@@ -328,12 +328,12 @@ pub(crate) fn fd_fdstat_set_rights(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let fd = dec_fd(fd);
|
let fd = dec_fd(fd);
|
||||||
let fe = wasi_ctx.fds.get_mut(&fd).ok_or(host::__WASI_EBADF)?;
|
let fe = wasi_ctx.fds.get_mut(&fd).ok_or(Error::EBADF)?;
|
||||||
|
|
||||||
if fe.rights_base & fs_rights_base != fs_rights_base
|
if fe.rights_base & fs_rights_base != fs_rights_base
|
||||||
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
|
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
|
||||||
{
|
{
|
||||||
return Err(host::__WASI_ENOTCAPABLE);
|
return Err(Error::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
fe.rights_base = fs_rights_base;
|
fe.rights_base = fs_rights_base;
|
||||||
fe.rights_inheriting = fs_rights_inheriting;
|
fe.rights_inheriting = fs_rights_inheriting;
|
||||||
@@ -348,7 +348,7 @@ pub(crate) fn fd_sync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result<()>
|
|||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_SYNC, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_FD_SYNC, 0)
|
||||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||||
fd.sync_all().map_err(errno_from_ioerror)
|
fd.sync_all().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_write(
|
pub(crate) fn fd_write(
|
||||||
@@ -377,20 +377,17 @@ pub(crate) fn fd_write(
|
|||||||
|
|
||||||
// perform unbuffered writes
|
// perform unbuffered writes
|
||||||
let host_nwritten = match &mut *fe.fd_object.descriptor {
|
let host_nwritten = match &mut *fe.fd_object.descriptor {
|
||||||
Descriptor::File(f) => f.write_vectored(&iovs).map_err(errno_from_ioerror)?,
|
Descriptor::File(f) => f.write_vectored(&iovs)?,
|
||||||
Descriptor::Stdin => return Err(host::__WASI_EBADF),
|
Descriptor::Stdin => return Err(Error::EBADF),
|
||||||
Descriptor::Stdout => {
|
Descriptor::Stdout => {
|
||||||
// lock for the duration of the scope
|
// lock for the duration of the scope
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
let nwritten = stdout.write_vectored(&iovs).map_err(errno_from_ioerror)?;
|
let nwritten = stdout.write_vectored(&iovs)?;
|
||||||
stdout.flush().map_err(errno_from_ioerror)?;
|
stdout.flush()?;
|
||||||
nwritten
|
nwritten
|
||||||
}
|
}
|
||||||
Descriptor::Stderr => io::stderr()
|
Descriptor::Stderr => io::stderr().lock().write_vectored(&iovs)?,
|
||||||
.lock()
|
|
||||||
.write_vectored(&iovs)
|
|
||||||
.map_err(errno_from_ioerror)?,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!(" | *nwritten={:?}", host_nwritten);
|
trace!(" | *nwritten={:?}", host_nwritten);
|
||||||
@@ -439,17 +436,17 @@ pub(crate) fn fd_allocate(
|
|||||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_ALLOCATE, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_FD_ALLOCATE, 0)
|
||||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||||
|
|
||||||
let metadata = fd.metadata().map_err(errno_from_ioerror)?;
|
let metadata = fd.metadata()?;
|
||||||
|
|
||||||
let current_size = metadata.len();
|
let current_size = metadata.len();
|
||||||
let wanted_size = offset.checked_add(len).ok_or(host::__WASI_E2BIG)?;
|
let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?;
|
||||||
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if wanted_size > i64::max_value() as u64 {
|
if wanted_size > i64::max_value() as u64 {
|
||||||
return Err(host::__WASI_E2BIG);
|
return Err(Error::E2BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if wanted_size > current_size {
|
if wanted_size > current_size {
|
||||||
fd.set_len(wanted_size).map_err(errno_from_ioerror)
|
fd.set_len(wanted_size).map_err(Into::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -782,7 +779,7 @@ pub(crate) fn fd_filestat_set_times_impl(
|
|||||||
let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0;
|
let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
let atim = if set_atim {
|
let atim = if set_atim {
|
||||||
let time = UNIX_EPOCH + Duration::from_nanos(st_atim);
|
let time = UNIX_EPOCH + Duration::from_nanos(st_atim);
|
||||||
@@ -803,7 +800,7 @@ pub(crate) fn fd_filestat_set_times_impl(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
set_file_handle_times(fd, atim, mtim).map_err(errno_from_ioerror)
|
set_file_handle_times(fd, atim, mtim).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_filestat_set_size(
|
pub(crate) fn fd_filestat_set_size(
|
||||||
@@ -821,9 +818,9 @@ pub(crate) fn fd_filestat_set_size(
|
|||||||
let st_size = dec_filesize(st_size);
|
let st_size = dec_filesize(st_size);
|
||||||
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if st_size > i64::max_value() as u64 {
|
if st_size > i64::max_value() as u64 {
|
||||||
return Err(host::__WASI_E2BIG);
|
return Err(Error::E2BIG);
|
||||||
}
|
}
|
||||||
fd.set_len(st_size).map_err(errno_from_ioerror)
|
fd.set_len(st_size).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_filestat_get(
|
pub(crate) fn path_filestat_get(
|
||||||
@@ -1006,9 +1003,9 @@ pub(crate) fn fd_prestat_get(
|
|||||||
wasi_ctx
|
wasi_ctx
|
||||||
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
||||||
.and_then(|fe| {
|
.and_then(|fe| {
|
||||||
let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?;
|
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
|
||||||
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(Error::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||||
@@ -1047,15 +1044,15 @@ pub(crate) fn fd_prestat_dir_name(
|
|||||||
wasi_ctx
|
wasi_ctx
|
||||||
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
||||||
.and_then(|fe| {
|
.and_then(|fe| {
|
||||||
let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?;
|
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
|
||||||
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(Error::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||||
|
|
||||||
if path.len() > dec_usize(path_len) {
|
if path.len() > dec_usize(path_len) {
|
||||||
return Err(host::__WASI_ENAMETOOLONG);
|
return Err(Error::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(" | (path_ptr,path_len)='{}'", path);
|
trace!(" | (path_ptr,path_len)='{}'", path);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
use crate::sys::host_impl;
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::*;
|
use crate::sys::hostcalls_impl::fs_helpers::*;
|
||||||
use crate::sys::{errno_from_host, host_impl};
|
use crate::{host, Error, Result};
|
||||||
use crate::{host, Result};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::{Component, Path};
|
use std::path::{Component, Path};
|
||||||
|
|
||||||
@@ -33,13 +33,10 @@ pub(crate) fn path_get(
|
|||||||
|
|
||||||
if path.contains('\0') {
|
if path.contains('\0') {
|
||||||
// if contains NUL, return EILSEQ
|
// if contains NUL, return EILSEQ
|
||||||
return Err(host::__WASI_EILSEQ);
|
return Err(Error::EILSEQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dirfd = dirfd.try_clone().map_err(|err| {
|
let dirfd = dirfd.try_clone()?;
|
||||||
err.raw_os_error()
|
|
||||||
.map_or(host::__WASI_EBADF, errno_from_host)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Stack of directory file descriptors. Index 0 always corresponds with the directory provided
|
// Stack of directory file descriptors. Index 0 always corresponds with the directory provided
|
||||||
// to this function. Entering a directory causes a file descriptor to be pushed, while handling
|
// to this function. Entering a directory causes a file descriptor to be pushed, while handling
|
||||||
@@ -64,7 +61,7 @@ pub(crate) fn path_get(
|
|||||||
let ends_with_slash = cur_path.ends_with('/');
|
let ends_with_slash = cur_path.ends_with('/');
|
||||||
let mut components = Path::new(&cur_path).components();
|
let mut components = Path::new(&cur_path).components();
|
||||||
let head = match components.next() {
|
let head = match components.next() {
|
||||||
None => return Err(host::__WASI_ENOENT),
|
None => return Err(Error::ENOENT),
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
};
|
};
|
||||||
let tail = components.as_path();
|
let tail = components.as_path();
|
||||||
@@ -80,18 +77,18 @@ pub(crate) fn path_get(
|
|||||||
match head {
|
match head {
|
||||||
Component::Prefix(_) | Component::RootDir => {
|
Component::Prefix(_) | Component::RootDir => {
|
||||||
// path is absolute!
|
// path is absolute!
|
||||||
return Err(host::__WASI_ENOTCAPABLE);
|
return Err(Error::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
Component::CurDir => {
|
Component::CurDir => {
|
||||||
// "." so skip
|
// "." so skip
|
||||||
}
|
}
|
||||||
Component::ParentDir => {
|
Component::ParentDir => {
|
||||||
// ".." so pop a dir
|
// ".." so pop a dir
|
||||||
let _ = dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?;
|
let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?;
|
||||||
|
|
||||||
// we're not allowed to pop past the original directory
|
// we're not allowed to pop past the original directory
|
||||||
if dir_stack.is_empty() {
|
if dir_stack.is_empty() {
|
||||||
return Err(host::__WASI_ENOTCAPABLE);
|
return Err(Error::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component::Normal(head) => {
|
Component::Normal(head) => {
|
||||||
@@ -102,41 +99,44 @@ pub(crate) fn path_get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
|
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
|
||||||
match openat(dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?, &head) {
|
match openat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
|
||||||
Ok(new_dir) => {
|
Ok(new_dir) => {
|
||||||
dir_stack.push(new_dir);
|
dir_stack.push(new_dir);
|
||||||
}
|
}
|
||||||
Err(e)
|
|
||||||
if e == host::__WASI_ELOOP
|
|
||||||
|| e == host::__WASI_EMLINK
|
|
||||||
|| e == host::__WASI_ENOTDIR =>
|
|
||||||
// Check to see if it was a symlink. Linux indicates
|
|
||||||
// this with ENOTDIR because of the O_DIRECTORY flag.
|
|
||||||
{
|
|
||||||
// attempt symlink expansion
|
|
||||||
let mut link_path = readlinkat(
|
|
||||||
dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?,
|
|
||||||
&head,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
symlink_expansions += 1;
|
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
|
||||||
return Err(host::__WASI_ELOOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if head.ends_with('/') {
|
|
||||||
link_path.push('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!(
|
|
||||||
"attempted symlink expansion link_path={:?}",
|
|
||||||
link_path
|
|
||||||
);
|
|
||||||
|
|
||||||
path_stack.push(link_path);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(e);
|
match e.as_wasi_errno() {
|
||||||
|
host::__WASI_ELOOP
|
||||||
|
| host::__WASI_EMLINK
|
||||||
|
| host::__WASI_ENOTDIR =>
|
||||||
|
// Check to see if it was a symlink. Linux indicates
|
||||||
|
// this with ENOTDIR because of the O_DIRECTORY flag.
|
||||||
|
{
|
||||||
|
// attempt symlink expansion
|
||||||
|
let mut link_path = readlinkat(
|
||||||
|
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
|
||||||
|
&head,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
symlink_expansions += 1;
|
||||||
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
|
return Err(Error::ELOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if head.ends_with('/') {
|
||||||
|
link_path.push('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"attempted symlink expansion link_path={:?}",
|
||||||
|
link_path
|
||||||
|
);
|
||||||
|
|
||||||
|
path_stack.push(link_path);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,14 +146,11 @@ pub(crate) fn path_get(
|
|||||||
{
|
{
|
||||||
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
||||||
// symlink expansion
|
// symlink expansion
|
||||||
match readlinkat(
|
match readlinkat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
|
||||||
dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?,
|
|
||||||
&head,
|
|
||||||
) {
|
|
||||||
Ok(mut link_path) => {
|
Ok(mut link_path) => {
|
||||||
symlink_expansions += 1;
|
symlink_expansions += 1;
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
return Err(host::__WASI_ELOOP);
|
return Err(Error::ELOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.ends_with('/') {
|
if head.ends_with('/') {
|
||||||
@@ -169,7 +166,9 @@ pub(crate) fn path_get(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e != host::__WASI_EINVAL && e != host::__WASI_ENOENT {
|
if e.as_wasi_errno() != host::__WASI_EINVAL
|
||||||
|
&& e.as_wasi_errno() != host::__WASI_ENOENT
|
||||||
|
{
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +177,7 @@ pub(crate) fn path_get(
|
|||||||
|
|
||||||
// not a symlink, so we're done;
|
// not a symlink, so we're done;
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
||||||
path: head,
|
path: head,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -188,7 +187,7 @@ pub(crate) fn path_get(
|
|||||||
// no further components to process. means we've hit a case like "." or "a/..", or if the
|
// no further components to process. means we've hit a case like "." or "a/..", or if the
|
||||||
// input path has trailing slashes and `needs_final_component` is not set
|
// input path has trailing slashes and `needs_final_component` is not set
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
||||||
path: String::from("."),
|
path: String::from("."),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
use crate::ctx::WasiCtx;
|
use crate::ctx::WasiCtx;
|
||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sys::hostcalls_impl;
|
use crate::sys::hostcalls_impl;
|
||||||
use crate::{host, wasm32, Result};
|
use crate::{wasm32, Error, Result};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@@ -29,11 +29,8 @@ pub(crate) fn args_get(
|
|||||||
|
|
||||||
argv.push(arg_ptr);
|
argv.push(arg_ptr);
|
||||||
|
|
||||||
let len =
|
let len = wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| Error::EOVERFLOW)?;
|
||||||
wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?;
|
argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?;
|
||||||
argv_buf_offset = argv_buf_offset
|
|
||||||
.checked_add(len)
|
|
||||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_slice_of(memory, argv.as_slice(), argv_ptr)
|
enc_slice_of(memory, argv.as_slice(), argv_ptr)
|
||||||
@@ -90,11 +87,10 @@ pub(crate) fn environ_get(
|
|||||||
|
|
||||||
environ.push(env_ptr);
|
environ.push(env_ptr);
|
||||||
|
|
||||||
let len =
|
let len = wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| Error::EOVERFLOW)?;
|
||||||
wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?;
|
|
||||||
environ_buf_offset = environ_buf_offset
|
environ_buf_offset = environ_buf_offset
|
||||||
.checked_add(len)
|
.checked_add(len)
|
||||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
.ok_or(Error::EOVERFLOW)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_slice_of(memory, environ.as_slice(), environ_ptr)
|
enc_slice_of(memory, environ.as_slice(), environ_ptr)
|
||||||
@@ -119,7 +115,7 @@ pub(crate) fn environ_sizes_get(
|
|||||||
.try_fold(0, |acc: u32, pair| {
|
.try_fold(0, |acc: u32, pair| {
|
||||||
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
|
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
|
||||||
})
|
})
|
||||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
.ok_or(Error::EOVERFLOW)?;
|
||||||
|
|
||||||
trace!(" | *environ_count_ptr={:?}", environ_count);
|
trace!(" | *environ_count_ptr={:?}", environ_count);
|
||||||
|
|
||||||
@@ -202,7 +198,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if nsubscriptions as u64 > wasm32::__wasi_filesize_t::max_value() {
|
if nsubscriptions as u64 > wasm32::__wasi_filesize_t::max_value() {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_pointee(memory, nevents, 0)?;
|
enc_pointee(memory, nevents, 0)?;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
mod ctx;
|
mod ctx;
|
||||||
|
mod error;
|
||||||
mod fdentry;
|
mod fdentry;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
mod hostcalls_impl;
|
mod hostcalls_impl;
|
||||||
@@ -36,4 +37,5 @@ pub mod wasm32;
|
|||||||
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
||||||
pub use sys::preopen_dir;
|
pub use sys::preopen_dir;
|
||||||
|
|
||||||
pub(crate) type Result<T> = std::result::Result<T, self::host::__wasi_errno_t>;
|
pub type Error = error::Error;
|
||||||
|
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ macro_rules! hostcalls {
|
|||||||
pub fn $name($($arg: $ty,)*) -> $ret {
|
pub fn $name($($arg: $ty,)*) -> $ret {
|
||||||
let ret = match crate::hostcalls_impl::$name($($arg,)*) {
|
let ret = match crate::hostcalls_impl::$name($($arg,)*) {
|
||||||
Ok(()) => crate::host::__WASI_ESUCCESS,
|
Ok(()) => crate::host::__WASI_ESUCCESS,
|
||||||
Err(e) => e,
|
Err(e) => e.as_wasi_errno(),
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::hostcalls::return_enc_errno(ret)
|
crate::hostcalls::return_enc_errno(ret)
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
//! Functions to go back and forth between WASI types in host and wasm32 representations.
|
//! Functions to go back and forth between WASI types in host and wasm32 representations.
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use crate::{host, wasm32, Result};
|
use crate::{host, wasm32, Error, Result};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::{align_of, size_of};
|
||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
|
|
||||||
fn dec_ptr(memory: &[u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*const u8> {
|
fn dec_ptr(memory: &[u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*const u8> {
|
||||||
// check for overflow
|
// check for overflow
|
||||||
let checked_len = (ptr as usize).checked_add(len).ok_or(host::__WASI_EFAULT)?;
|
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
|
||||||
|
|
||||||
// translate the pointer
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get(ptr as usize..checked_len)
|
.get(ptr as usize..checked_len)
|
||||||
.ok_or(host::__WASI_EFAULT)
|
.ok_or(Error::EFAULT)
|
||||||
.map(|mem| mem.as_ptr())
|
.map(|mem| mem.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dec_ptr_mut(memory: &mut [u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*mut u8> {
|
fn dec_ptr_mut(memory: &mut [u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*mut u8> {
|
||||||
// check for overflow
|
// check for overflow
|
||||||
let checked_len = (ptr as usize).checked_add(len).ok_or(host::__WASI_EFAULT)?;
|
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
|
||||||
|
|
||||||
// translate the pointer
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get_mut(ptr as usize..checked_len)
|
.get_mut(ptr as usize..checked_len)
|
||||||
.ok_or(host::__WASI_EFAULT)
|
.ok_or(Error::EFAULT)
|
||||||
.map(|mem| mem.as_mut_ptr())
|
.map(|mem| mem.as_mut_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasm32::uintptr_t) -> Result<&'memory T> {
|
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasm32::uintptr_t) -> Result<&'memory T> {
|
||||||
// check that the ptr is aligned
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dec_ptr(memory, ptr, size_of::<T>()).map(|p| unsafe { &*(p as *const T) })
|
dec_ptr(memory, ptr, size_of::<T>()).map(|p| unsafe { &*(p as *const T) })
|
||||||
@@ -42,7 +42,7 @@ fn dec_ptr_to_mut<'memory, T>(
|
|||||||
) -> Result<&'memory mut T> {
|
) -> Result<&'memory mut T> {
|
||||||
// check that the ptr is aligned
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
|
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
|
||||||
@@ -59,13 +59,13 @@ pub fn enc_pointee<T>(memory: &mut [u8], ptr: wasm32::uintptr_t, t: T) -> Result
|
|||||||
fn check_slice_of<T>(ptr: wasm32::uintptr_t, len: wasm32::size_t) -> Result<(usize, usize)> {
|
fn check_slice_of<T>(ptr: wasm32::uintptr_t, len: wasm32::size_t) -> Result<(usize, usize)> {
|
||||||
// check alignment, and that length doesn't overflow
|
// check alignment, and that length doesn't overflow
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
let len = dec_usize(len);
|
let len = dec_usize(len);
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EOVERFLOW);
|
return Err(Error::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((len, len_bytes))
|
Ok((len, len_bytes))
|
||||||
@@ -94,13 +94,13 @@ pub fn dec_slice_of_mut<'memory, T>(
|
|||||||
pub fn enc_slice_of<T>(memory: &mut [u8], slice: &[T], ptr: wasm32::uintptr_t) -> Result<()> {
|
pub fn enc_slice_of<T>(memory: &mut [u8], slice: &[T], ptr: wasm32::uintptr_t) -> Result<()> {
|
||||||
// check alignment
|
// check alignment
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
// check that length doesn't overflow
|
// check that length doesn't overflow
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EOVERFLOW);
|
return Err(Error::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the pointer into guest memory, and copy the bytes
|
// get the pointer into guest memory, and copy the bytes
|
||||||
@@ -357,7 +357,7 @@ pub fn dec_prestat(prestat: wasm32::__wasi_prestat_t) -> Result<host::__wasi_pre
|
|||||||
u,
|
u,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(host::__WASI_EINVAL),
|
_ => Err(Error::EINVAL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ pub fn enc_prestat(prestat: host::__wasi_prestat_t) -> Result<wasm32::__wasi_pre
|
|||||||
u,
|
u,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(host::__WASI_EINVAL),
|
_ => Err(Error::EINVAL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +497,7 @@ pub fn dec_subscription(
|
|||||||
fd: dec_fd(unsafe{u_orig.fd_readwrite.fd})
|
fd: dec_fd(unsafe{u_orig.fd_readwrite.fd})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(wasm32::__WASI_EINVAL)
|
_ => return Err(Error::EINVAL)
|
||||||
};
|
};
|
||||||
Ok(host::__wasi_subscription_t { userdata, type_, u })
|
Ok(host::__wasi_subscription_t { userdata, type_, u })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ cfg_if! {
|
|||||||
pub use self::unix::preopen_dir;
|
pub use self::unix::preopen_dir;
|
||||||
|
|
||||||
pub(crate) fn errno_from_host(err: i32) -> host::__wasi_errno_t {
|
pub(crate) fn errno_from_host(err: i32) -> host::__wasi_errno_t {
|
||||||
host_impl::errno_from_nix(nix::errno::from_i32(err))
|
host_impl::errno_from_nix(nix::errno::from_i32(err)).as_wasi_errno()
|
||||||
}
|
}
|
||||||
} else if #[cfg(windows)] {
|
} else if #[cfg(windows)] {
|
||||||
mod windows;
|
mod windows;
|
||||||
@@ -23,7 +23,7 @@ cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn errno_from_ioerror(e: std::io::Error) -> host::__wasi_errno_t {
|
pub(crate) fn errno_from_ioerror(e: &std::io::Error) -> host::__wasi_errno_t {
|
||||||
match e.raw_os_error() {
|
match e.raw_os_error() {
|
||||||
Some(code) => errno_from_host(code),
|
Some(code) => errno_from_host(code),
|
||||||
None => {
|
None => {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::sys::{errno_from_host, errno_from_ioerror};
|
use crate::{host, Error, Result};
|
||||||
use crate::{host, Result};
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
||||||
|
|
||||||
@@ -25,10 +24,7 @@ pub(crate) fn determine_type_and_access_rights<Fd: AsRawFd>(
|
|||||||
let (file_type, mut rights_base, rights_inheriting) = determine_type_rights(fd)?;
|
let (file_type, mut rights_base, rights_inheriting) = determine_type_rights(fd)?;
|
||||||
|
|
||||||
use nix::fcntl::{fcntl, OFlag, F_GETFL};
|
use nix::fcntl::{fcntl, OFlag, F_GETFL};
|
||||||
let flags_bits = fcntl(fd.as_raw_fd(), F_GETFL).map_err(|err| {
|
let flags_bits = fcntl(fd.as_raw_fd(), F_GETFL)?;
|
||||||
err.as_errno()
|
|
||||||
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
||||||
})?;
|
|
||||||
let flags = OFlag::from_bits_truncate(flags_bits);
|
let flags = OFlag::from_bits_truncate(flags_bits);
|
||||||
let accmode = flags & OFlag::O_ACCMODE;
|
let accmode = flags & OFlag::O_ACCMODE;
|
||||||
if accmode == OFlag::O_RDONLY {
|
if accmode == OFlag::O_RDONLY {
|
||||||
@@ -51,7 +47,7 @@ pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|||||||
// we just make a `File` here for convenience; we don't want it to close when it drops
|
// we just make a `File` here for convenience; we don't want it to close when it drops
|
||||||
let file =
|
let file =
|
||||||
std::mem::ManuallyDrop::new(unsafe { std::fs::File::from_raw_fd(fd.as_raw_fd()) });
|
std::mem::ManuallyDrop::new(unsafe { std::fs::File::from_raw_fd(fd.as_raw_fd()) });
|
||||||
let ft = file.metadata().map_err(errno_from_ioerror)?.file_type();
|
let ft = file.metadata()?.file_type();
|
||||||
if ft.is_block_device() {
|
if ft.is_block_device() {
|
||||||
(
|
(
|
||||||
host::__WASI_FILETYPE_BLOCK_DEVICE,
|
host::__WASI_FILETYPE_BLOCK_DEVICE,
|
||||||
@@ -59,10 +55,7 @@ pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|||||||
host::RIGHTS_BLOCK_DEVICE_INHERITING,
|
host::RIGHTS_BLOCK_DEVICE_INHERITING,
|
||||||
)
|
)
|
||||||
} else if ft.is_char_device() {
|
} else if ft.is_char_device() {
|
||||||
if nix::unistd::isatty(fd.as_raw_fd()).map_err(|err| {
|
if nix::unistd::isatty(fd.as_raw_fd())? {
|
||||||
err.as_errno()
|
|
||||||
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
||||||
})? {
|
|
||||||
(
|
(
|
||||||
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
||||||
host::RIGHTS_TTY_BASE,
|
host::RIGHTS_TTY_BASE,
|
||||||
@@ -89,10 +82,7 @@ pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|||||||
)
|
)
|
||||||
} else if ft.is_socket() {
|
} else if ft.is_socket() {
|
||||||
use nix::sys::socket;
|
use nix::sys::socket;
|
||||||
match socket::getsockopt(fd.as_raw_fd(), socket::sockopt::SockType).map_err(|err| {
|
match socket::getsockopt(fd.as_raw_fd(), socket::sockopt::SockType)? {
|
||||||
err.as_errno()
|
|
||||||
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
||||||
})? {
|
|
||||||
socket::SockType::Datagram => (
|
socket::SockType::Datagram => (
|
||||||
host::__WASI_FILETYPE_SOCKET_DGRAM,
|
host::__WASI_FILETYPE_SOCKET_DGRAM,
|
||||||
host::RIGHTS_SOCKET_BASE,
|
host::RIGHTS_SOCKET_BASE,
|
||||||
@@ -103,7 +93,7 @@ pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|||||||
host::RIGHTS_SOCKET_BASE,
|
host::RIGHTS_SOCKET_BASE,
|
||||||
host::RIGHTS_SOCKET_INHERITING,
|
host::RIGHTS_SOCKET_INHERITING,
|
||||||
),
|
),
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
}
|
}
|
||||||
} else if ft.is_fifo() {
|
} else if ft.is_fifo() {
|
||||||
(
|
(
|
||||||
@@ -112,7 +102,7 @@ pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|||||||
host::RIGHTS_REGULAR_FILE_INHERITING,
|
host::RIGHTS_REGULAR_FILE_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,87 +2,91 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::{host, memory, Result};
|
use crate::{host, memory, Error, Result};
|
||||||
|
use log::warn;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::os::unix::prelude::OsStrExt;
|
use std::os::unix::prelude::OsStrExt;
|
||||||
|
|
||||||
pub(crate) fn errno_from_nix(errno: nix::errno::Errno) -> host::__wasi_errno_t {
|
pub(crate) fn errno_from_nix(errno: nix::errno::Errno) -> Error {
|
||||||
match errno {
|
match errno {
|
||||||
nix::errno::Errno::EPERM => host::__WASI_EPERM,
|
nix::errno::Errno::EPERM => Error::EPERM,
|
||||||
nix::errno::Errno::ENOENT => host::__WASI_ENOENT,
|
nix::errno::Errno::ENOENT => Error::ENOENT,
|
||||||
nix::errno::Errno::ESRCH => host::__WASI_ESRCH,
|
nix::errno::Errno::ESRCH => Error::ESRCH,
|
||||||
nix::errno::Errno::EINTR => host::__WASI_EINTR,
|
nix::errno::Errno::EINTR => Error::EINTR,
|
||||||
nix::errno::Errno::EIO => host::__WASI_EIO,
|
nix::errno::Errno::EIO => Error::EIO,
|
||||||
nix::errno::Errno::ENXIO => host::__WASI_ENXIO,
|
nix::errno::Errno::ENXIO => Error::ENXIO,
|
||||||
nix::errno::Errno::E2BIG => host::__WASI_E2BIG,
|
nix::errno::Errno::E2BIG => Error::E2BIG,
|
||||||
nix::errno::Errno::ENOEXEC => host::__WASI_ENOEXEC,
|
nix::errno::Errno::ENOEXEC => Error::ENOEXEC,
|
||||||
nix::errno::Errno::EBADF => host::__WASI_EBADF,
|
nix::errno::Errno::EBADF => Error::EBADF,
|
||||||
nix::errno::Errno::ECHILD => host::__WASI_ECHILD,
|
nix::errno::Errno::ECHILD => Error::ECHILD,
|
||||||
nix::errno::Errno::EAGAIN => host::__WASI_EAGAIN,
|
nix::errno::Errno::EAGAIN => Error::EAGAIN,
|
||||||
nix::errno::Errno::ENOMEM => host::__WASI_ENOMEM,
|
nix::errno::Errno::ENOMEM => Error::ENOMEM,
|
||||||
nix::errno::Errno::EACCES => host::__WASI_EACCES,
|
nix::errno::Errno::EACCES => Error::EACCES,
|
||||||
nix::errno::Errno::EFAULT => host::__WASI_EFAULT,
|
nix::errno::Errno::EFAULT => Error::EFAULT,
|
||||||
nix::errno::Errno::EBUSY => host::__WASI_EBUSY,
|
nix::errno::Errno::EBUSY => Error::EBUSY,
|
||||||
nix::errno::Errno::EEXIST => host::__WASI_EEXIST,
|
nix::errno::Errno::EEXIST => Error::EEXIST,
|
||||||
nix::errno::Errno::EXDEV => host::__WASI_EXDEV,
|
nix::errno::Errno::EXDEV => Error::EXDEV,
|
||||||
nix::errno::Errno::ENODEV => host::__WASI_ENODEV,
|
nix::errno::Errno::ENODEV => Error::ENODEV,
|
||||||
nix::errno::Errno::ENOTDIR => host::__WASI_ENOTDIR,
|
nix::errno::Errno::ENOTDIR => Error::ENOTDIR,
|
||||||
nix::errno::Errno::EISDIR => host::__WASI_EISDIR,
|
nix::errno::Errno::EISDIR => Error::EISDIR,
|
||||||
nix::errno::Errno::EINVAL => host::__WASI_EINVAL,
|
nix::errno::Errno::EINVAL => Error::EINVAL,
|
||||||
nix::errno::Errno::ENFILE => host::__WASI_ENFILE,
|
nix::errno::Errno::ENFILE => Error::ENFILE,
|
||||||
nix::errno::Errno::EMFILE => host::__WASI_EMFILE,
|
nix::errno::Errno::EMFILE => Error::EMFILE,
|
||||||
nix::errno::Errno::ENOTTY => host::__WASI_ENOTTY,
|
nix::errno::Errno::ENOTTY => Error::ENOTTY,
|
||||||
nix::errno::Errno::ETXTBSY => host::__WASI_ETXTBSY,
|
nix::errno::Errno::ETXTBSY => Error::ETXTBSY,
|
||||||
nix::errno::Errno::EFBIG => host::__WASI_EFBIG,
|
nix::errno::Errno::EFBIG => Error::EFBIG,
|
||||||
nix::errno::Errno::ENOSPC => host::__WASI_ENOSPC,
|
nix::errno::Errno::ENOSPC => Error::ENOSPC,
|
||||||
nix::errno::Errno::ESPIPE => host::__WASI_ESPIPE,
|
nix::errno::Errno::ESPIPE => Error::ESPIPE,
|
||||||
nix::errno::Errno::EROFS => host::__WASI_EROFS,
|
nix::errno::Errno::EROFS => Error::EROFS,
|
||||||
nix::errno::Errno::EMLINK => host::__WASI_EMLINK,
|
nix::errno::Errno::EMLINK => Error::EMLINK,
|
||||||
nix::errno::Errno::EPIPE => host::__WASI_EPIPE,
|
nix::errno::Errno::EPIPE => Error::EPIPE,
|
||||||
nix::errno::Errno::EDOM => host::__WASI_EDOM,
|
nix::errno::Errno::EDOM => Error::EDOM,
|
||||||
nix::errno::Errno::ERANGE => host::__WASI_ERANGE,
|
nix::errno::Errno::ERANGE => Error::ERANGE,
|
||||||
nix::errno::Errno::EDEADLK => host::__WASI_EDEADLK,
|
nix::errno::Errno::EDEADLK => Error::EDEADLK,
|
||||||
nix::errno::Errno::ENAMETOOLONG => host::__WASI_ENAMETOOLONG,
|
nix::errno::Errno::ENAMETOOLONG => Error::ENAMETOOLONG,
|
||||||
nix::errno::Errno::ENOLCK => host::__WASI_ENOLCK,
|
nix::errno::Errno::ENOLCK => Error::ENOLCK,
|
||||||
nix::errno::Errno::ENOSYS => host::__WASI_ENOSYS,
|
nix::errno::Errno::ENOSYS => Error::ENOSYS,
|
||||||
nix::errno::Errno::ENOTEMPTY => host::__WASI_ENOTEMPTY,
|
nix::errno::Errno::ENOTEMPTY => Error::ENOTEMPTY,
|
||||||
nix::errno::Errno::ELOOP => host::__WASI_ELOOP,
|
nix::errno::Errno::ELOOP => Error::ELOOP,
|
||||||
nix::errno::Errno::ENOMSG => host::__WASI_ENOMSG,
|
nix::errno::Errno::ENOMSG => Error::ENOMSG,
|
||||||
nix::errno::Errno::EIDRM => host::__WASI_EIDRM,
|
nix::errno::Errno::EIDRM => Error::EIDRM,
|
||||||
nix::errno::Errno::ENOLINK => host::__WASI_ENOLINK,
|
nix::errno::Errno::ENOLINK => Error::ENOLINK,
|
||||||
nix::errno::Errno::EPROTO => host::__WASI_EPROTO,
|
nix::errno::Errno::EPROTO => Error::EPROTO,
|
||||||
nix::errno::Errno::EMULTIHOP => host::__WASI_EMULTIHOP,
|
nix::errno::Errno::EMULTIHOP => Error::EMULTIHOP,
|
||||||
nix::errno::Errno::EBADMSG => host::__WASI_EBADMSG,
|
nix::errno::Errno::EBADMSG => Error::EBADMSG,
|
||||||
nix::errno::Errno::EOVERFLOW => host::__WASI_EOVERFLOW,
|
nix::errno::Errno::EOVERFLOW => Error::EOVERFLOW,
|
||||||
nix::errno::Errno::EILSEQ => host::__WASI_EILSEQ,
|
nix::errno::Errno::EILSEQ => Error::EILSEQ,
|
||||||
nix::errno::Errno::ENOTSOCK => host::__WASI_ENOTSOCK,
|
nix::errno::Errno::ENOTSOCK => Error::ENOTSOCK,
|
||||||
nix::errno::Errno::EDESTADDRREQ => host::__WASI_EDESTADDRREQ,
|
nix::errno::Errno::EDESTADDRREQ => Error::EDESTADDRREQ,
|
||||||
nix::errno::Errno::EMSGSIZE => host::__WASI_EMSGSIZE,
|
nix::errno::Errno::EMSGSIZE => Error::EMSGSIZE,
|
||||||
nix::errno::Errno::EPROTOTYPE => host::__WASI_EPROTOTYPE,
|
nix::errno::Errno::EPROTOTYPE => Error::EPROTOTYPE,
|
||||||
nix::errno::Errno::ENOPROTOOPT => host::__WASI_ENOPROTOOPT,
|
nix::errno::Errno::ENOPROTOOPT => Error::ENOPROTOOPT,
|
||||||
nix::errno::Errno::EPROTONOSUPPORT => host::__WASI_EPROTONOSUPPORT,
|
nix::errno::Errno::EPROTONOSUPPORT => Error::EPROTONOSUPPORT,
|
||||||
nix::errno::Errno::EAFNOSUPPORT => host::__WASI_EAFNOSUPPORT,
|
nix::errno::Errno::EAFNOSUPPORT => Error::EAFNOSUPPORT,
|
||||||
nix::errno::Errno::EADDRINUSE => host::__WASI_EADDRINUSE,
|
nix::errno::Errno::EADDRINUSE => Error::EADDRINUSE,
|
||||||
nix::errno::Errno::EADDRNOTAVAIL => host::__WASI_EADDRNOTAVAIL,
|
nix::errno::Errno::EADDRNOTAVAIL => Error::EADDRNOTAVAIL,
|
||||||
nix::errno::Errno::ENETDOWN => host::__WASI_ENETDOWN,
|
nix::errno::Errno::ENETDOWN => Error::ENETDOWN,
|
||||||
nix::errno::Errno::ENETUNREACH => host::__WASI_ENETUNREACH,
|
nix::errno::Errno::ENETUNREACH => Error::ENETUNREACH,
|
||||||
nix::errno::Errno::ENETRESET => host::__WASI_ENETRESET,
|
nix::errno::Errno::ENETRESET => Error::ENETRESET,
|
||||||
nix::errno::Errno::ECONNABORTED => host::__WASI_ECONNABORTED,
|
nix::errno::Errno::ECONNABORTED => Error::ECONNABORTED,
|
||||||
nix::errno::Errno::ECONNRESET => host::__WASI_ECONNRESET,
|
nix::errno::Errno::ECONNRESET => Error::ECONNRESET,
|
||||||
nix::errno::Errno::ENOBUFS => host::__WASI_ENOBUFS,
|
nix::errno::Errno::ENOBUFS => Error::ENOBUFS,
|
||||||
nix::errno::Errno::EISCONN => host::__WASI_EISCONN,
|
nix::errno::Errno::EISCONN => Error::EISCONN,
|
||||||
nix::errno::Errno::ENOTCONN => host::__WASI_ENOTCONN,
|
nix::errno::Errno::ENOTCONN => Error::ENOTCONN,
|
||||||
nix::errno::Errno::ETIMEDOUT => host::__WASI_ETIMEDOUT,
|
nix::errno::Errno::ETIMEDOUT => Error::ETIMEDOUT,
|
||||||
nix::errno::Errno::ECONNREFUSED => host::__WASI_ECONNREFUSED,
|
nix::errno::Errno::ECONNREFUSED => Error::ECONNREFUSED,
|
||||||
nix::errno::Errno::EHOSTUNREACH => host::__WASI_EHOSTUNREACH,
|
nix::errno::Errno::EHOSTUNREACH => Error::EHOSTUNREACH,
|
||||||
nix::errno::Errno::EALREADY => host::__WASI_EALREADY,
|
nix::errno::Errno::EALREADY => Error::EALREADY,
|
||||||
nix::errno::Errno::EINPROGRESS => host::__WASI_EINPROGRESS,
|
nix::errno::Errno::EINPROGRESS => Error::EINPROGRESS,
|
||||||
nix::errno::Errno::ESTALE => host::__WASI_ESTALE,
|
nix::errno::Errno::ESTALE => Error::ESTALE,
|
||||||
nix::errno::Errno::EDQUOT => host::__WASI_EDQUOT,
|
nix::errno::Errno::EDQUOT => Error::EDQUOT,
|
||||||
nix::errno::Errno::ECANCELED => host::__WASI_ECANCELED,
|
nix::errno::Errno::ECANCELED => Error::ECANCELED,
|
||||||
nix::errno::Errno::EOWNERDEAD => host::__WASI_EOWNERDEAD,
|
nix::errno::Errno::EOWNERDEAD => Error::EOWNERDEAD,
|
||||||
nix::errno::Errno::ENOTRECOVERABLE => host::__WASI_ENOTRECOVERABLE,
|
nix::errno::Errno::ENOTRECOVERABLE => Error::ENOTRECOVERABLE,
|
||||||
_ => host::__WASI_ENOSYS,
|
other => {
|
||||||
|
warn!("Unknown error from nix: {}", other);
|
||||||
|
Error::ENOSYS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,14 +183,12 @@ pub(crate) fn filestat_from_nix(
|
|||||||
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<host::__wasi_timestamp_t> {
|
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<host::__wasi_timestamp_t> {
|
||||||
secs.checked_mul(1_000_000_000)
|
secs.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
|
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
|
||||||
.ok_or(host::__WASI_EOVERFLOW)
|
.ok_or(Error::EOVERFLOW)
|
||||||
}
|
}
|
||||||
|
|
||||||
let filetype = nix::sys::stat::SFlag::from_bits_truncate(filestat.st_mode);
|
let filetype = nix::sys::stat::SFlag::from_bits_truncate(filestat.st_mode);
|
||||||
let dev =
|
let dev = host::__wasi_device_t::try_from(filestat.st_dev).map_err(|_| Error::EOVERFLOW)?;
|
||||||
host::__wasi_device_t::try_from(filestat.st_dev).map_err(|_| host::__WASI_EOVERFLOW)?;
|
let ino = host::__wasi_inode_t::try_from(filestat.st_ino).map_err(|_| Error::EOVERFLOW)?;
|
||||||
let ino =
|
|
||||||
host::__wasi_inode_t::try_from(filestat.st_ino).map_err(|_| host::__WASI_EOVERFLOW)?;
|
|
||||||
let st_atim = filestat_to_timestamp(filestat.st_atime as u64, filestat.st_atime_nsec as u64)?;
|
let st_atim = filestat_to_timestamp(filestat.st_atime as u64, filestat.st_atime_nsec as u64)?;
|
||||||
let st_ctim = filestat_to_timestamp(filestat.st_ctime as u64, filestat.st_ctime_nsec as u64)?;
|
let st_ctim = filestat_to_timestamp(filestat.st_ctime as u64, filestat.st_ctime_nsec as u64)?;
|
||||||
let st_mtim = filestat_to_timestamp(filestat.st_mtime as u64, filestat.st_mtime_nsec as u64)?;
|
let st_mtim = filestat_to_timestamp(filestat.st_mtime as u64, filestat.st_mtime_nsec as u64)?;
|
||||||
@@ -222,7 +224,7 @@ pub(crate) fn dirent_filetype_from_host(
|
|||||||
Ok(host::__WASI_FILETYPE_UNKNOWN)
|
Ok(host::__WASI_FILETYPE_UNKNOWN)
|
||||||
}
|
}
|
||||||
libc::DT_UNKNOWN => Ok(host::__WASI_FILETYPE_UNKNOWN),
|
libc::DT_UNKNOWN => Ok(host::__WASI_FILETYPE_UNKNOWN),
|
||||||
_ => Err(host::__WASI_EINVAL),
|
_ => Err(Error::EINVAL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +235,7 @@ pub(crate) fn dirent_from_host(host_entry: &nix::libc::dirent) -> Result<host::_
|
|||||||
.to_bytes()
|
.to_bytes()
|
||||||
.len();
|
.len();
|
||||||
if d_namlen > u32::max_value() as usize {
|
if d_namlen > u32::max_value() as usize {
|
||||||
return Err(host::__WASI_EIO);
|
return Err(Error::EIO);
|
||||||
}
|
}
|
||||||
let d_type = dirent_filetype_from_host(host_entry)?;
|
let d_type = dirent_filetype_from_host(host_entry)?;
|
||||||
entry.d_ino = memory::enc_inode(host_entry.d_ino);
|
entry.d_ino = memory::enc_inode(host_entry.d_ino);
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
use super::fs_helpers::*;
|
use super::fs_helpers::*;
|
||||||
use crate::helpers::systemtime_to_timestamp;
|
use crate::helpers::systemtime_to_timestamp;
|
||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::sys::errno_from_ioerror;
|
|
||||||
use crate::sys::host_impl::{self, errno_from_nix};
|
use crate::sys::host_impl::{self, errno_from_nix};
|
||||||
use crate::{host, Result};
|
use crate::{host, Result, Error};
|
||||||
use nix::libc::{self, c_long, c_void};
|
use nix::libc::{self, c_long, c_void};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
@@ -18,11 +17,11 @@ pub(crate) fn fd_pread(
|
|||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: host::__wasi_filesize_t,
|
offset: host::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
file.read_at(buf, offset).map_err(errno_from_ioerror)
|
file.read_at(buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result<usize> {
|
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result<usize> {
|
||||||
file.write_at(buf, offset).map_err(errno_from_ioerror)
|
file.write_at(buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<host::__wasi_fdflags_t> {
|
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<host::__wasi_fdflags_t> {
|
||||||
@@ -52,8 +51,8 @@ pub(crate) fn fd_advise(
|
|||||||
{
|
{
|
||||||
use nix::fcntl::{posix_fadvise, PosixFadviseAdvice};
|
use nix::fcntl::{posix_fadvise, PosixFadviseAdvice};
|
||||||
|
|
||||||
let offset = offset.try_into().map_err(|_| host::__WASI_EOVERFLOW)?;
|
let offset = offset.try_into().map_err(|_| Error::EOVERFLOW)?;
|
||||||
let len = len.try_into().map_err(|_| host::__WASI_EOVERFLOW)?;
|
let len = len.try_into().map_err(|_| Error::EOVERFLOW)?;
|
||||||
let host_advice = match advice {
|
let host_advice = match advice {
|
||||||
host::__WASI_ADVICE_DONTNEED => PosixFadviseAdvice::POSIX_FADV_DONTNEED,
|
host::__WASI_ADVICE_DONTNEED => PosixFadviseAdvice::POSIX_FADV_DONTNEED,
|
||||||
host::__WASI_ADVICE_SEQUENTIAL => PosixFadviseAdvice::POSIX_FADV_SEQUENTIAL,
|
host::__WASI_ADVICE_SEQUENTIAL => PosixFadviseAdvice::POSIX_FADV_SEQUENTIAL,
|
||||||
@@ -61,7 +60,7 @@ pub(crate) fn fd_advise(
|
|||||||
host::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::POSIX_FADV_NOREUSE,
|
host::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::POSIX_FADV_NOREUSE,
|
||||||
host::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::POSIX_FADV_RANDOM,
|
host::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::POSIX_FADV_RANDOM,
|
||||||
host::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::POSIX_FADV_NORMAL,
|
host::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::POSIX_FADV_NORMAL,
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
};
|
};
|
||||||
|
|
||||||
posix_fadvise(file.as_raw_fd(), offset, len, host_advice)
|
posix_fadvise(file.as_raw_fd(), offset, len, host_advice)
|
||||||
@@ -85,7 +84,7 @@ pub(crate) fn fd_advise(
|
|||||||
| host::__WASI_ADVICE_NOREUSE
|
| host::__WASI_ADVICE_NOREUSE
|
||||||
| host::__WASI_ADVICE_RANDOM
|
| host::__WASI_ADVICE_RANDOM
|
||||||
| host::__WASI_ADVICE_NORMAL => {}
|
| host::__WASI_ADVICE_NORMAL => {}
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -93,7 +92,7 @@ pub(crate) fn fd_advise(
|
|||||||
|
|
||||||
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
||||||
use nix::libc::mkdirat;
|
use nix::libc::mkdirat;
|
||||||
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
// nix doesn't expose mkdirat() yet
|
// nix doesn't expose mkdirat() yet
|
||||||
match unsafe { mkdirat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0o777) } {
|
match unsafe { mkdirat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0o777) } {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
@@ -104,9 +103,9 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
|||||||
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
||||||
use nix::libc::linkat;
|
use nix::libc::linkat;
|
||||||
let old_path_cstr =
|
let old_path_cstr =
|
||||||
CString::new(resolved_old.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
let new_path_cstr =
|
let new_path_cstr =
|
||||||
CString::new(resolved_new.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
// Not setting AT_SYMLINK_FOLLOW fails on most filesystems
|
// Not setting AT_SYMLINK_FOLLOW fails on most filesystems
|
||||||
let atflags = libc::AT_SYMLINK_FOLLOW;
|
let atflags = libc::AT_SYMLINK_FOLLOW;
|
||||||
@@ -174,12 +173,12 @@ pub(crate) fn path_open(
|
|||||||
AtFlags::AT_SYMLINK_NOFOLLOW,
|
AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||||
) {
|
) {
|
||||||
if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFSOCK) {
|
if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFSOCK) {
|
||||||
return Err(host::__WASI_ENOTSUP);
|
return Err(Error::ENOTSUP);
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_ENXIO);
|
return Err(Error::ENXIO);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_ENXIO);
|
return Err(Error::ENXIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY
|
// Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY
|
||||||
@@ -193,18 +192,18 @@ pub(crate) fn path_open(
|
|||||||
AtFlags::AT_SYMLINK_NOFOLLOW,
|
AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||||
) {
|
) {
|
||||||
if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFLNK) {
|
if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFLNK) {
|
||||||
return Err(host::__WASI_ELOOP);
|
return Err(Error::ELOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(Error::ENOTDIR);
|
||||||
}
|
}
|
||||||
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
||||||
// a symlink.
|
// a symlink.
|
||||||
Some(Errno::EMLINK) if !(nix_all_oflags & OFlag::O_NOFOLLOW).is_empty() => {
|
Some(Errno::EMLINK) if !(nix_all_oflags & OFlag::O_NOFOLLOW).is_empty() => {
|
||||||
return Err(host::__WASI_ELOOP);
|
return Err(Error::ELOOP);
|
||||||
}
|
}
|
||||||
Some(e) => return Err(host_impl::errno_from_nix(e)),
|
Some(e) => return Err(host_impl::errno_from_nix(e)),
|
||||||
None => return Err(host::__WASI_ENOSYS),
|
None => return Err(Error::ENOSYS),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -275,7 +274,7 @@ pub(crate) fn fd_readdir(
|
|||||||
|
|
||||||
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
|
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
// Linux requires that the buffer size is positive, whereas POSIX does not.
|
// Linux requires that the buffer size is positive, whereas POSIX does not.
|
||||||
// Use a fake buffer to store the results if the size is zero.
|
// Use a fake buffer to store the results if the size is zero.
|
||||||
@@ -307,9 +306,9 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
|
|||||||
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
||||||
use nix::libc::renameat;
|
use nix::libc::renameat;
|
||||||
let old_path_cstr =
|
let old_path_cstr =
|
||||||
CString::new(resolved_old.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
let new_path_cstr =
|
let new_path_cstr =
|
||||||
CString::new(resolved_new.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
renameat(
|
renameat(
|
||||||
@@ -329,27 +328,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_filestat_t> {
|
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_filestat_t> {
|
||||||
use std::os::unix::fs::MetadataExt;
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
|
||||||
let metadata = file.metadata().map_err(errno_from_ioerror)?;
|
let metadata = file.metadata()?;
|
||||||
Ok(host::__wasi_filestat_t {
|
Ok(host::__wasi_filestat_t {
|
||||||
st_dev: metadata.dev(),
|
st_dev: metadata.dev(),
|
||||||
st_ino: metadata.ino(),
|
st_ino: metadata.ino(),
|
||||||
st_nlink: metadata
|
st_nlink: metadata
|
||||||
.nlink()
|
.nlink()
|
||||||
.try_into()
|
.try_into()?, // u64 doesn't fit into u32
|
||||||
.map_err(|_| host::__WASI_EOVERFLOW)?, // u64 doesn't fit into u32
|
|
||||||
st_size: metadata.len(),
|
st_size: metadata.len(),
|
||||||
st_atim: metadata
|
st_atim: systemtime_to_timestamp(metadata.accessed()?)?,
|
||||||
.accessed()
|
|
||||||
.map_err(errno_from_ioerror)
|
|
||||||
.and_then(systemtime_to_timestamp)?,
|
|
||||||
st_ctim: metadata
|
st_ctim: metadata
|
||||||
.ctime()
|
.ctime()
|
||||||
.try_into()
|
.try_into()?, // i64 doesn't fit into u64
|
||||||
.map_err(|_| host::__WASI_EOVERFLOW)?, // i64 doesn't fit into u64
|
st_mtim: systemtime_to_timestamp(metadata.modified()?)?,
|
||||||
st_mtim: metadata
|
|
||||||
.modified()
|
|
||||||
.map_err(errno_from_ioerror)
|
|
||||||
.and_then(systemtime_to_timestamp)?,
|
|
||||||
st_filetype: filetype(file, &metadata)?,
|
st_filetype: filetype(file, &metadata)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -432,7 +423,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0;
|
let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
let atflags = match dirflags {
|
let atflags = match dirflags {
|
||||||
@@ -441,7 +432,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let atim = if set_atim_now {
|
let atim = if set_atim_now {
|
||||||
let st_atim = st_atim.try_into().map_err(|_| host::__WASI_EOVERFLOW)?;
|
let st_atim = st_atim.try_into().map_err(|_| Error::EOVERFLOW)?;
|
||||||
TimeSpec::nanoseconds(st_atim)
|
TimeSpec::nanoseconds(st_atim)
|
||||||
} else if set_atim_now {
|
} else if set_atim_now {
|
||||||
timespec_now()
|
timespec_now()
|
||||||
@@ -450,7 +441,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mtim = if set_mtim {
|
let mtim = if set_mtim {
|
||||||
let st_mtim = st_mtim.try_into().map_err(|_| host::__WASI_EOVERFLOW)?;
|
let st_mtim = st_mtim.try_into().map_err(|_| Error::EOVERFLOW)?;
|
||||||
TimeSpec::nanoseconds(st_mtim)
|
TimeSpec::nanoseconds(st_mtim)
|
||||||
} else if set_atim_now {
|
} else if set_atim_now {
|
||||||
timespec_now()
|
timespec_now()
|
||||||
@@ -466,9 +457,9 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
||||||
use nix::libc::symlinkat;
|
use nix::libc::symlinkat;
|
||||||
|
|
||||||
let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
let new_path_cstr =
|
let new_path_cstr =
|
||||||
CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
symlinkat(
|
symlinkat(
|
||||||
@@ -488,7 +479,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
use nix::errno;
|
use nix::errno;
|
||||||
use nix::libc::unlinkat;
|
use nix::libc::unlinkat;
|
||||||
|
|
||||||
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
// nix doesn't expose unlinkat() yet
|
// nix doesn't expose unlinkat() yet
|
||||||
match unsafe { unlinkat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0) } {
|
match unsafe { unlinkat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0) } {
|
||||||
@@ -532,7 +523,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
|||||||
use nix::errno;
|
use nix::errno;
|
||||||
use nix::libc::{unlinkat, AT_REMOVEDIR};
|
use nix::libc::{unlinkat, AT_REMOVEDIR};
|
||||||
|
|
||||||
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?;
|
||||||
|
|
||||||
// nix doesn't expose unlinkat() yet
|
// nix doesn't expose unlinkat() yet
|
||||||
match unsafe {
|
match unsafe {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::{host, wasm32, Result};
|
use crate::{host, wasm32, Result, Error};
|
||||||
use nix::libc::{self, c_int};
|
use nix::libc::{self, c_int};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
@@ -14,7 +14,7 @@ pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result<host::__
|
|||||||
host::__WASI_CLOCK_MONOTONIC => libc::CLOCK_MONOTONIC,
|
host::__WASI_CLOCK_MONOTONIC => libc::CLOCK_MONOTONIC,
|
||||||
host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID,
|
host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID,
|
||||||
host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID,
|
host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID,
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
};
|
};
|
||||||
|
|
||||||
// no `nix` wrapper for clock_getres, so we do it ourselves
|
// no `nix` wrapper for clock_getres, so we do it ourselves
|
||||||
@@ -30,11 +30,11 @@ pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result<host::__
|
|||||||
(timespec.tv_sec as host::__wasi_timestamp_t)
|
(timespec.tv_sec as host::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t))
|
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t))
|
||||||
.map_or(Err(host::__WASI_EOVERFLOW), |resolution| {
|
.map_or(Err(Error::EOVERFLOW), |resolution| {
|
||||||
// a supported clock can never return zero; this case will probably never get hit, but
|
// a supported clock can never return zero; this case will probably never get hit, but
|
||||||
// make sure we follow the spec
|
// make sure we follow the spec
|
||||||
if resolution == 0 {
|
if resolution == 0 {
|
||||||
Err(host::__WASI_EINVAL)
|
Err(Error::EINVAL)
|
||||||
} else {
|
} else {
|
||||||
Ok(resolution)
|
Ok(resolution)
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ pub(crate) fn clock_time_get(clock_id: host::__wasi_clockid_t) -> Result<host::_
|
|||||||
host::__WASI_CLOCK_MONOTONIC => libc::CLOCK_MONOTONIC,
|
host::__WASI_CLOCK_MONOTONIC => libc::CLOCK_MONOTONIC,
|
||||||
host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID,
|
host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID,
|
||||||
host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID,
|
host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID,
|
||||||
_ => return Err(host::__WASI_EINVAL),
|
_ => return Err(Error::EINVAL),
|
||||||
};
|
};
|
||||||
|
|
||||||
// no `nix` wrapper for clock_getres, so we do it ourselves
|
// no `nix` wrapper for clock_getres, so we do it ourselves
|
||||||
@@ -63,7 +63,7 @@ pub(crate) fn clock_time_get(clock_id: host::__wasi_clockid_t) -> Result<host::_
|
|||||||
(timespec.tv_sec as host::__wasi_timestamp_t)
|
(timespec.tv_sec as host::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t))
|
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as host::__wasi_timestamp_t))
|
||||||
.map_or(Err(host::__WASI_EOVERFLOW), |time| Ok(time))
|
.map_or(Err(Error::EOVERFLOW), |time| Ok(time))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn poll_oneoff(
|
pub(crate) fn poll_oneoff(
|
||||||
@@ -152,7 +152,7 @@ fn wasi_clock_to_relative_ns_delay(
|
|||||||
}
|
}
|
||||||
let now: u128 = SystemTime::now()
|
let now: u128 = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.map_err(|_| host::__WASI_ENOTCAPABLE)?
|
.map_err(|_| Error::ENOTCAPABLE)?
|
||||||
.as_nanos();
|
.as_nanos();
|
||||||
let deadline = wasi_clock.timeout as u128;
|
let deadline = wasi_clock.timeout as u128;
|
||||||
Ok(deadline.saturating_sub(now))
|
Ok(deadline.saturating_sub(now))
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ pub(crate) mod fdentry_impl;
|
|||||||
pub(crate) mod host_impl;
|
pub(crate) mod host_impl;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
|
|
||||||
use crate::sys::errno_from_ioerror;
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
File::open("/dev/null").map_err(errno_from_ioerror)
|
File::open("/dev/null").map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
||||||
File::open(path).map_err(errno_from_ioerror)
|
File::open(path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::host_impl;
|
|
||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::{host, Result};
|
use crate::{host, Error, Result};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
||||||
@@ -29,8 +28,7 @@ pub(crate) fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
|||||||
|
|
||||||
match file_type {
|
match file_type {
|
||||||
host::__WASI_FILETYPE_DIRECTORY | host::__WASI_FILETYPE_REGULAR_FILE => {
|
host::__WASI_FILETYPE_DIRECTORY | host::__WASI_FILETYPE_REGULAR_FILE => {
|
||||||
let mode =
|
let mode = get_file_access_mode(handle.as_raw_handle())?;
|
||||||
get_file_access_mode(handle.as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
|
||||||
if mode.contains(AccessMode::FILE_GENERIC_READ) {
|
if mode.contains(AccessMode::FILE_GENERIC_READ) {
|
||||||
rights_base |= host::__WASI_RIGHT_FD_READ;
|
rights_base |= host::__WASI_RIGHT_FD_READ;
|
||||||
}
|
}
|
||||||
@@ -55,8 +53,7 @@ pub(crate) fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
host::__wasi_rights_t,
|
host::__wasi_rights_t,
|
||||||
)> {
|
)> {
|
||||||
let (file_type, rights_base, rights_inheriting) = {
|
let (file_type, rights_base, rights_inheriting) = {
|
||||||
let file_type =
|
let file_type = winx::file::get_file_type(handle.as_raw_handle())?;
|
||||||
winx::file::get_file_type(handle.as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
|
||||||
if file_type.is_char() {
|
if file_type.is_char() {
|
||||||
// character file: LPT device or console
|
// character file: LPT device or console
|
||||||
// TODO: rule out LPT device
|
// TODO: rule out LPT device
|
||||||
@@ -70,7 +67,7 @@ pub(crate) fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
let file = std::mem::ManuallyDrop::new(unsafe {
|
let file = std::mem::ManuallyDrop::new(unsafe {
|
||||||
File::from_raw_handle(handle.as_raw_handle())
|
File::from_raw_handle(handle.as_raw_handle())
|
||||||
});
|
});
|
||||||
let meta = file.metadata().map_err(|_| host::__WASI_EINVAL)?;
|
let meta = file.metadata().map_err(|_| Error::EINVAL)?;
|
||||||
if meta.is_dir() {
|
if meta.is_dir() {
|
||||||
(
|
(
|
||||||
host::__WASI_FILETYPE_DIRECTORY,
|
host::__WASI_FILETYPE_DIRECTORY,
|
||||||
@@ -84,7 +81,7 @@ pub(crate) fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
host::RIGHTS_REGULAR_FILE_INHERITING,
|
host::RIGHTS_REGULAR_FILE_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
} else if file_type.is_pipe() {
|
} else if file_type.is_pipe() {
|
||||||
// pipe object: socket, named pipe or anonymous pipe
|
// pipe object: socket, named pipe or anonymous pipe
|
||||||
@@ -95,7 +92,7 @@ pub(crate) fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
host::RIGHTS_SOCKET_INHERITING,
|
host::RIGHTS_SOCKET_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(host::__WASI_EINVAL);
|
return Err(Error::EINVAL);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok((file_type, rights_base, rights_inheriting))
|
Ok((file_type, rights_base, rights_inheriting))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use crate::{host, Result};
|
use crate::{host, Result, Error};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
@@ -102,5 +102,5 @@ pub(crate) fn win_from_oflags(oflags: host::__wasi_oflags_t) -> CreationDisposit
|
|||||||
/// `__WASI_EILSEQ` error is returned.
|
/// `__WASI_EILSEQ` error is returned.
|
||||||
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
|
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
|
||||||
let vec: Vec<u16> = s.as_ref().encode_wide().collect();
|
let vec: Vec<u16> = s.as_ref().encode_wide().collect();
|
||||||
String::from_utf16(&vec).map_err(|_| host::__WASI_EILSEQ)
|
String::from_utf16(&vec).map_err(|_| Error::EILSEQ)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
|
|||||||
use crate::sys::fdentry_impl::determine_type_rights;
|
use crate::sys::fdentry_impl::determine_type_rights;
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||||
use crate::sys::{errno_from_host, errno_from_ioerror};
|
use crate::{host, Error, Result};
|
||||||
use crate::{host, Result};
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::{File, Metadata, OpenOptions};
|
use std::fs::{File, Metadata, OpenOptions};
|
||||||
use std::io::{self, Seek, SeekFrom};
|
use std::io::{self, Seek, SeekFrom};
|
||||||
@@ -37,23 +36,25 @@ fn write_at(mut file: &File, buf: &[u8], offset: u64) -> io::Result<usize> {
|
|||||||
Ok(nwritten)
|
Ok(nwritten)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO refactor common code with unix
|
||||||
pub(crate) fn fd_pread(
|
pub(crate) fn fd_pread(
|
||||||
file: &File,
|
file: &File,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: host::__wasi_filesize_t,
|
offset: host::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
read_at(file, buf, offset).map_err(errno_from_ioerror)
|
read_at(file, buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO refactor common code with unix
|
||||||
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result<usize> {
|
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result<usize> {
|
||||||
write_at(file, buf, offset).map_err(errno_from_ioerror)
|
write_at(file, buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<host::__wasi_fdflags_t> {
|
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<host::__wasi_fdflags_t> {
|
||||||
use winx::file::AccessMode;
|
use winx::file::AccessMode;
|
||||||
winx::file::get_file_access_mode(fd.as_raw_handle())
|
winx::file::get_file_access_mode(fd.as_raw_handle())
|
||||||
.map(host_impl::fdflags_from_win)
|
.map(host_impl::fdflags_from_win)
|
||||||
.map_err(host_impl::errno_from_win)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: host::__wasi_fdflags_t) -> Result<()> {
|
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: host::__wasi_fdflags_t) -> Result<()> {
|
||||||
@@ -81,7 +82,7 @@ pub(crate) fn fd_advise(
|
|||||||
|
|
||||||
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
std::fs::create_dir(&path).map_err(errno_from_ioerror)
|
std::fs::create_dir(&path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
||||||
@@ -133,11 +134,11 @@ pub(crate) fn path_open(
|
|||||||
Ok(file_type) => {
|
Ok(file_type) => {
|
||||||
// check if we are trying to open a symlink
|
// check if we are trying to open a symlink
|
||||||
if file_type.is_symlink() {
|
if file_type.is_symlink() {
|
||||||
return Err(host::__WASI_ELOOP);
|
return Err(Error::ELOOP);
|
||||||
}
|
}
|
||||||
// check if we are trying to open a file as a dir
|
// check if we are trying to open a file as a dir
|
||||||
if file_type.is_file() && oflags & host::__WASI_O_DIRECTORY != 0 {
|
if file_type.is_file() && oflags & host::__WASI_O_DIRECTORY != 0 {
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(Error::ENOTDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => match e.raw_os_error() {
|
Err(e) => match e.raw_os_error() {
|
||||||
@@ -147,14 +148,14 @@ pub(crate) fn path_open(
|
|||||||
let e = WinError::from_u32(e as u32);
|
let e = WinError::from_u32(e as u32);
|
||||||
|
|
||||||
if e != WinError::ERROR_FILE_NOT_FOUND {
|
if e != WinError::ERROR_FILE_NOT_FOUND {
|
||||||
return Err(host_impl::errno_from_win(e));
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
// file not found, let it proceed to actually
|
// file not found, let it proceed to actually
|
||||||
// trying to open it
|
// trying to open it
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
return Err(host::__WASI_EIO);
|
return Err(Error::EIO);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,7 @@ pub(crate) fn path_open(
|
|||||||
opts.access_mode(access_mode.bits())
|
opts.access_mode(access_mode.bits())
|
||||||
.custom_flags(flags.bits())
|
.custom_flags(flags.bits())
|
||||||
.open(&path)
|
.open(&path)
|
||||||
.map_err(errno_from_ioerror)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
@@ -177,19 +178,18 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
|
|||||||
use winx::file::get_path_by_handle;
|
use winx::file::get_path_by_handle;
|
||||||
|
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let target_path = path.read_link().map_err(errno_from_ioerror)?;
|
let target_path = path.read_link()?;
|
||||||
|
|
||||||
// since on Windows we are effectively emulating 'at' syscalls
|
// since on Windows we are effectively emulating 'at' syscalls
|
||||||
// we need to strip the prefix from the absolute path
|
// we need to strip the prefix from the absolute path
|
||||||
// as otherwise we will error out since WASI is not capable
|
// as otherwise we will error out since WASI is not capable
|
||||||
// of dealing with absolute paths
|
// of dealing with absolute paths
|
||||||
let dir_path =
|
let dir_path = get_path_by_handle(resolved.dirfd().as_raw_handle())?;
|
||||||
get_path_by_handle(resolved.dirfd().as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
|
||||||
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
let target_path = target_path
|
let target_path = target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| host::__WASI_ENOTCAPABLE)
|
.map_err(|_| Error::ENOTCAPABLE)
|
||||||
.and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ))?;
|
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
|
||||||
|
|
||||||
if buf.len() > 0 {
|
if buf.len() > 0 {
|
||||||
let mut chars = target_path.chars();
|
let mut chars = target_path.chars();
|
||||||
@@ -222,7 +222,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
//
|
//
|
||||||
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
|
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
|
||||||
if old_path.is_dir() && new_path.is_file() {
|
if old_path.is_dir() && new_path.is_file() {
|
||||||
return Err(host::__WASI_ENOTDIR);
|
return Err(Error::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle symlinks
|
// TODO handle symlinks
|
||||||
@@ -237,21 +237,21 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
// So most likely dealing with new_path == dir.
|
// So most likely dealing with new_path == dir.
|
||||||
// Eliminate case old_path == file first.
|
// Eliminate case old_path == file first.
|
||||||
if old_path.is_file() {
|
if old_path.is_file() {
|
||||||
Err(host::__WASI_EISDIR)
|
Err(Error::EISDIR)
|
||||||
} else {
|
} else {
|
||||||
// Ok, let's try removing an empty dir at new_path if it exists
|
// Ok, let's try removing an empty dir at new_path if it exists
|
||||||
// and is a nonempty dir.
|
// and is a nonempty dir.
|
||||||
fs::remove_dir(&new_path)
|
fs::remove_dir(&new_path)
|
||||||
.and_then(|()| fs::rename(old_path, new_path))
|
.and_then(|()| fs::rename(old_path, new_path))
|
||||||
.map_err(errno_from_ioerror)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e => Err(host_impl::errno_from_win(e)),
|
e => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
Err(host::__WASI_EIO)
|
Err(Error::EIO)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -277,27 +277,15 @@ pub(crate) fn change_time(file: &File, _metadata: &Metadata) -> io::Result<i64>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_filestat_t> {
|
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_filestat_t> {
|
||||||
let metadata = file.metadata().map_err(errno_from_ioerror)?;
|
let metadata = file.metadata()?;
|
||||||
Ok(host::__wasi_filestat_t {
|
Ok(host::__wasi_filestat_t {
|
||||||
st_dev: device_id(file, &metadata).map_err(errno_from_ioerror)?,
|
st_dev: device_id(file, &metadata)?,
|
||||||
st_ino: file_serial_no(file, &metadata).map_err(errno_from_ioerror)?,
|
st_ino: file_serial_no(file, &metadata)?,
|
||||||
st_nlink: num_hardlinks(file, &metadata)
|
st_nlink: num_hardlinks(file, &metadata)?.try_into()?, // u64 doesn't fit into u32
|
||||||
.map_err(errno_from_ioerror)?
|
|
||||||
.try_into()
|
|
||||||
.map_err(|_| host::__WASI_EOVERFLOW)?, // u64 doesn't fit into u32
|
|
||||||
st_size: metadata.len(),
|
st_size: metadata.len(),
|
||||||
st_atim: metadata
|
st_atim: systemtime_to_timestamp(metadata.accessed()?)?,
|
||||||
.accessed()
|
st_ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64
|
||||||
.map_err(errno_from_ioerror)
|
st_mtim: systemtime_to_timestamp(metadata.modified()?)?,
|
||||||
.and_then(systemtime_to_timestamp)?,
|
|
||||||
st_ctim: change_time(file, &metadata)
|
|
||||||
.map_err(errno_from_ioerror)?
|
|
||||||
.try_into()
|
|
||||||
.map_err(|_| host::__WASI_EOVERFLOW)?, // i64 doesn't fit into u64
|
|
||||||
st_mtim: metadata
|
|
||||||
.modified()
|
|
||||||
.map_err(errno_from_ioerror)
|
|
||||||
.and_then(systemtime_to_timestamp)?,
|
|
||||||
st_filetype: filetype(file, &metadata)?,
|
st_filetype: filetype(file, &metadata)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -322,7 +310,7 @@ pub(crate) fn path_filestat_get(
|
|||||||
dirflags: host::__wasi_lookupflags_t,
|
dirflags: host::__wasi_lookupflags_t,
|
||||||
) -> Result<host::__wasi_filestat_t> {
|
) -> Result<host::__wasi_filestat_t> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = File::open(path).map_err(errno_from_ioerror)?;
|
let file = File::open(path)?;
|
||||||
fd_filestat_get_impl(&file)
|
fd_filestat_get_impl(&file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,8 +325,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
.access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits())
|
.access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits())
|
||||||
.open(path)
|
.open(path)?;
|
||||||
.map_err(errno_from_ioerror)?;
|
|
||||||
fd_filestat_set_times_impl(&file, st_atim, st_mtim, fst_flags)
|
fd_filestat_set_times_impl(&file, st_atim, st_mtim, fst_flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,14 +344,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
|||||||
match WinError::from_u32(e as u32) {
|
match WinError::from_u32(e as u32) {
|
||||||
WinError::ERROR_NOT_A_REPARSE_POINT => {
|
WinError::ERROR_NOT_A_REPARSE_POINT => {
|
||||||
// try creating a dir symlink instead
|
// try creating a dir symlink instead
|
||||||
symlink_dir(old_path, new_path).map_err(errno_from_ioerror)
|
symlink_dir(old_path, new_path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
e => Err(host_impl::errno_from_win(e)),
|
e => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
Err(host::__WASI_EIO)
|
Err(Error::EIO)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -377,8 +364,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file_type = path
|
let file_type = path
|
||||||
.symlink_metadata()
|
.symlink_metadata()
|
||||||
.map(|metadata| metadata.file_type())
|
.map(|metadata| metadata.file_type())?;
|
||||||
.map_err(errno_from_ioerror)?;
|
|
||||||
|
|
||||||
// check if we're unlinking a symlink
|
// check if we're unlinking a symlink
|
||||||
// NB this will get cleaned up a lot when [std::os::windows::fs::FileTypeExt]
|
// NB this will get cleaned up a lot when [std::os::windows::fs::FileTypeExt]
|
||||||
@@ -393,27 +379,27 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
match WinError::from_u32(e as u32) {
|
match WinError::from_u32(e as u32) {
|
||||||
WinError::ERROR_ACCESS_DENIED => {
|
WinError::ERROR_ACCESS_DENIED => {
|
||||||
// try unlinking a dir symlink instead
|
// try unlinking a dir symlink instead
|
||||||
fs::remove_dir(path).map_err(errno_from_ioerror)
|
fs::remove_dir(path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
e => Err(host_impl::errno_from_win(e)),
|
e => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
Err(host::__WASI_EIO)
|
Err(Error::EIO)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else if file_type.is_dir() {
|
} else if file_type.is_dir() {
|
||||||
Err(host::__WASI_EISDIR)
|
Err(Error::EISDIR)
|
||||||
} else if file_type.is_file() {
|
} else if file_type.is_file() {
|
||||||
fs::remove_file(path).map_err(errno_from_ioerror)
|
fs::remove_file(path).map_err(Into::into)
|
||||||
} else {
|
} else {
|
||||||
Err(host::__WASI_EINVAL)
|
Err(Error::EINVAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
std::fs::remove_dir(&path).map_err(errno_from_ioerror)
|
std::fs::remove_dir(&path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use crate::sys::host_impl;
|
|
||||||
use crate::{host, Result};
|
|
||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
|
use crate::{host, Error, Result};
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
@@ -62,13 +61,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
|
|||||||
Some(e) => {
|
Some(e) => {
|
||||||
log::debug!("openat error={:?}", e);
|
log::debug!("openat error={:?}", e);
|
||||||
match WinError::from_u32(e as u32) {
|
match WinError::from_u32(e as u32) {
|
||||||
WinError::ERROR_INVALID_NAME => host::__WASI_ENOTDIR,
|
WinError::ERROR_INVALID_NAME => Error::ENOTDIR,
|
||||||
e => host_impl::errno_from_win(e),
|
e => e.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
host::__WASI_EIO
|
Error::EIO
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -84,13 +83,12 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
|
|||||||
// we need to strip the prefix from the absolute path
|
// we need to strip the prefix from the absolute path
|
||||||
// as otherwise we will error out since WASI is not capable
|
// as otherwise we will error out since WASI is not capable
|
||||||
// of dealing with absolute paths
|
// of dealing with absolute paths
|
||||||
let dir_path =
|
let dir_path = get_path_by_handle(dirfd.as_raw_handle())?;
|
||||||
get_path_by_handle(dirfd.as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
|
||||||
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
target_path
|
target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| host::__WASI_ENOTCAPABLE)
|
.map_err(|_| Error::ENOTCAPABLE)
|
||||||
.and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ))
|
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))
|
||||||
}
|
}
|
||||||
Err(e) => match e.raw_os_error() {
|
Err(e) => match e.raw_os_error() {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
@@ -101,20 +99,20 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
|
|||||||
// strip "/" and check if exists
|
// strip "/" and check if exists
|
||||||
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
||||||
if path.exists() && !path.is_dir() {
|
if path.exists() && !path.is_dir() {
|
||||||
Err(host::__WASI_ENOTDIR)
|
Err(Error::ENOTDIR)
|
||||||
} else {
|
} else {
|
||||||
Err(host::__WASI_ENOENT)
|
Err(Error::ENOENT)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(host::__WASI_ENOENT)
|
Err(Error::ENOENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e => Err(host_impl::errno_from_win(e)),
|
e => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", e);
|
log::debug!("Inconvertible OS error: {}", e);
|
||||||
Err(host::__WASI_EIO)
|
Err(Error::EIO)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -135,10 +133,10 @@ pub(crate) fn concatenate<P: AsRef<Path>>(dirfd: &File, path: P) -> Result<PathB
|
|||||||
// WASI is not able to deal with absolute paths
|
// WASI is not able to deal with absolute paths
|
||||||
// so error out if absolute
|
// so error out if absolute
|
||||||
if path.as_ref().is_absolute() {
|
if path.as_ref().is_absolute() {
|
||||||
return Err(host::__WASI_ENOTCAPABLE);
|
return Err(Error::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir_path = get_path_by_handle(dirfd.as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
let dir_path = get_path_by_handle(dirfd.as_raw_handle())?;
|
||||||
// concatenate paths
|
// concatenate paths
|
||||||
let mut out_path = PathBuf::from(dir_path);
|
let mut out_path = PathBuf::from(dir_path);
|
||||||
out_path.push(path.as_ref());
|
out_path.push(path.as_ref());
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ pub(crate) mod fdentry_impl;
|
|||||||
pub(crate) mod host_impl;
|
pub(crate) mod host_impl;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
|
|
||||||
use crate::sys::errno_from_ioerror;
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
File::open("NUL").map_err(errno_from_ioerror)
|
File::open("NUL").map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
||||||
@@ -25,5 +24,5 @@ pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
|||||||
.read(true)
|
.read(true)
|
||||||
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
|
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
.open(path)
|
.open(path)
|
||||||
.map_err(errno_from_ioerror)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user