Initial error refactor
This commit is contained in:
committed by
Jakub Konka
parent
85a41d449c
commit
14aaffd46f
@@ -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::host_impl;
|
||||
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||
use crate::sys::{errno_from_host, errno_from_ioerror};
|
||||
use crate::{host, Result};
|
||||
use crate::{host, Error, Result};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, Metadata, OpenOptions};
|
||||
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)
|
||||
}
|
||||
|
||||
// TODO refactor common code with unix
|
||||
pub(crate) fn fd_pread(
|
||||
file: &File,
|
||||
buf: &mut [u8],
|
||||
offset: host::__wasi_filesize_t,
|
||||
) -> 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> {
|
||||
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> {
|
||||
use winx::file::AccessMode;
|
||||
winx::file::get_file_access_mode(fd.as_raw_handle())
|
||||
.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<()> {
|
||||
@@ -81,7 +82,7 @@ pub(crate) fn fd_advise(
|
||||
|
||||
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
||||
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<()> {
|
||||
@@ -133,11 +134,11 @@ pub(crate) fn path_open(
|
||||
Ok(file_type) => {
|
||||
// check if we are trying to open a 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
|
||||
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() {
|
||||
@@ -147,14 +148,14 @@ pub(crate) fn path_open(
|
||||
let e = WinError::from_u32(e as u32);
|
||||
|
||||
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
|
||||
// trying to open it
|
||||
}
|
||||
None => {
|
||||
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())
|
||||
.custom_flags(flags.bits())
|
||||
.open(&path)
|
||||
.map_err(errno_from_ioerror)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
// we need to strip the prefix from the absolute path
|
||||
// as otherwise we will error out since WASI is not capable
|
||||
// of dealing with absolute paths
|
||||
let dir_path =
|
||||
get_path_by_handle(resolved.dirfd().as_raw_handle()).map_err(host_impl::errno_from_win)?;
|
||||
let dir_path = get_path_by_handle(resolved.dirfd().as_raw_handle())?;
|
||||
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||
let target_path = target_path
|
||||
.strip_prefix(dir_path)
|
||||
.map_err(|_| host::__WASI_ENOTCAPABLE)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ))?;
|
||||
.map_err(|_| Error::ENOTCAPABLE)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
|
||||
|
||||
if buf.len() > 0 {
|
||||
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
|
||||
if old_path.is_dir() && new_path.is_file() {
|
||||
return Err(host::__WASI_ENOTDIR);
|
||||
return Err(Error::ENOTDIR);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Eliminate case old_path == file first.
|
||||
if old_path.is_file() {
|
||||
Err(host::__WASI_EISDIR)
|
||||
Err(Error::EISDIR)
|
||||
} else {
|
||||
// Ok, let's try removing an empty dir at new_path if it exists
|
||||
// and is a nonempty dir.
|
||||
fs::remove_dir(&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 => {
|
||||
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> {
|
||||
let metadata = file.metadata().map_err(errno_from_ioerror)?;
|
||||
let metadata = file.metadata()?;
|
||||
Ok(host::__wasi_filestat_t {
|
||||
st_dev: device_id(file, &metadata).map_err(errno_from_ioerror)?,
|
||||
st_ino: file_serial_no(file, &metadata).map_err(errno_from_ioerror)?,
|
||||
st_nlink: num_hardlinks(file, &metadata)
|
||||
.map_err(errno_from_ioerror)?
|
||||
.try_into()
|
||||
.map_err(|_| host::__WASI_EOVERFLOW)?, // u64 doesn't fit into u32
|
||||
st_dev: device_id(file, &metadata)?,
|
||||
st_ino: file_serial_no(file, &metadata)?,
|
||||
st_nlink: num_hardlinks(file, &metadata)?.try_into()?, // u64 doesn't fit into u32
|
||||
st_size: metadata.len(),
|
||||
st_atim: metadata
|
||||
.accessed()
|
||||
.map_err(errno_from_ioerror)
|
||||
.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_atim: systemtime_to_timestamp(metadata.accessed()?)?,
|
||||
st_ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64
|
||||
st_mtim: systemtime_to_timestamp(metadata.modified()?)?,
|
||||
st_filetype: filetype(file, &metadata)?,
|
||||
})
|
||||
}
|
||||
@@ -322,7 +310,7 @@ pub(crate) fn path_filestat_get(
|
||||
dirflags: host::__wasi_lookupflags_t,
|
||||
) -> Result<host::__wasi_filestat_t> {
|
||||
let path = resolved.concatenate()?;
|
||||
let file = File::open(path).map_err(errno_from_ioerror)?;
|
||||
let file = File::open(path)?;
|
||||
fd_filestat_get_impl(&file)
|
||||
}
|
||||
|
||||
@@ -337,8 +325,7 @@ pub(crate) fn path_filestat_set_times(
|
||||
let path = resolved.concatenate()?;
|
||||
let file = OpenOptions::new()
|
||||
.access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits())
|
||||
.open(path)
|
||||
.map_err(errno_from_ioerror)?;
|
||||
.open(path)?;
|
||||
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) {
|
||||
WinError::ERROR_NOT_A_REPARSE_POINT => {
|
||||
// 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 => {
|
||||
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 file_type = path
|
||||
.symlink_metadata()
|
||||
.map(|metadata| metadata.file_type())
|
||||
.map_err(errno_from_ioerror)?;
|
||||
.map(|metadata| metadata.file_type())?;
|
||||
|
||||
// check if we're unlinking a symlink
|
||||
// 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) {
|
||||
WinError::ERROR_ACCESS_DENIED => {
|
||||
// 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 => {
|
||||
log::debug!("Inconvertible OS error: {}", e);
|
||||
Err(host::__WASI_EIO)
|
||||
Err(Error::EIO)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if file_type.is_dir() {
|
||||
Err(host::__WASI_EISDIR)
|
||||
Err(Error::EISDIR)
|
||||
} else if file_type.is_file() {
|
||||
fs::remove_file(path).map_err(errno_from_ioerror)
|
||||
fs::remove_file(path).map_err(Into::into)
|
||||
} else {
|
||||
Err(host::__WASI_EINVAL)
|
||||
Err(Error::EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
||||
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)]
|
||||
use crate::sys::host_impl;
|
||||
use crate::{host, Result};
|
||||
use crate::hostcalls_impl::PathGet;
|
||||
use crate::{host, Error, Result};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
@@ -62,13 +61,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
|
||||
Some(e) => {
|
||||
log::debug!("openat error={:?}", e);
|
||||
match WinError::from_u32(e as u32) {
|
||||
WinError::ERROR_INVALID_NAME => host::__WASI_ENOTDIR,
|
||||
e => host_impl::errno_from_win(e),
|
||||
WinError::ERROR_INVALID_NAME => Error::ENOTDIR,
|
||||
e => e.into(),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
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
|
||||
// as otherwise we will error out since WASI is not capable
|
||||
// of dealing with absolute paths
|
||||
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())?;
|
||||
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||
target_path
|
||||
.strip_prefix(dir_path)
|
||||
.map_err(|_| host::__WASI_ENOTCAPABLE)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ))
|
||||
.map_err(|_| Error::ENOTCAPABLE)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))
|
||||
}
|
||||
Err(e) => match e.raw_os_error() {
|
||||
Some(e) => {
|
||||
@@ -101,20 +99,20 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
|
||||
// strip "/" and check if exists
|
||||
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
||||
if path.exists() && !path.is_dir() {
|
||||
Err(host::__WASI_ENOTDIR)
|
||||
Err(Error::ENOTDIR)
|
||||
} else {
|
||||
Err(host::__WASI_ENOENT)
|
||||
Err(Error::ENOENT)
|
||||
}
|
||||
} else {
|
||||
Err(host::__WASI_ENOENT)
|
||||
Err(Error::ENOENT)
|
||||
}
|
||||
}
|
||||
e => Err(host_impl::errno_from_win(e)),
|
||||
e => Err(e.into()),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
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
|
||||
// so error out if 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
|
||||
let mut out_path = PathBuf::from(dir_path);
|
||||
out_path.push(path.as_ref());
|
||||
|
||||
Reference in New Issue
Block a user