Refactor hostcalls_impl in sys module
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use super::fs_helpers::*;
|
use super::fs_helpers::*;
|
||||||
use crate::ctx::WasiCtx;
|
use crate::ctx::WasiCtx;
|
||||||
use crate::fdentry::{Descriptor, FdEntry};
|
use crate::fdentry::FdEntry;
|
||||||
use crate::sys::errno_from_host;
|
use crate::sys::errno_from_host;
|
||||||
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;
|
||||||
@@ -36,8 +36,9 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<host::__wasi_fdflags_t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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<()> {
|
||||||
|
use nix::fcntl::{fcntl, F_SETFL};
|
||||||
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
||||||
match nix::fcntl::fcntl(fd.as_raw_fd(), nix::fcntl::F_SETFL(nix_flags)) {
|
match fcntl(fd.as_raw_fd(), F_SETFL(nix_flags)) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(host_impl::errno_from_nix(e.as_errno().unwrap())),
|
Err(e) => Err(host_impl::errno_from_nix(e.as_errno().unwrap())),
|
||||||
}
|
}
|
||||||
@@ -88,10 +89,7 @@ pub(crate) fn fd_advise(
|
|||||||
pub(crate) fn path_create_directory(dirfd: &File, path: &str) -> Result<()> {
|
pub(crate) fn path_create_directory(dirfd: &File, path: &str) -> Result<()> {
|
||||||
use nix::libc::mkdirat;
|
use nix::libc::mkdirat;
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, 0, path, false) {
|
let (dir, path) = path_get(dirfd, 0, path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
// nix doesn't expose mkdirat() yet
|
// nix doesn't expose mkdirat() yet
|
||||||
@@ -108,14 +106,8 @@ pub(crate) fn path_link(
|
|||||||
new_path: &str,
|
new_path: &str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use nix::libc::linkat;
|
use nix::libc::linkat;
|
||||||
let (old_dir, old_path) = match path_get(old_dirfd, 0, old_path, false) {
|
let (old_dir, old_path) = path_get(old_dirfd, 0, old_path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
let (new_dir, new_path) = path_get(new_dirfd, 0, new_path, false)?;
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let (new_dir, new_path) = match path_get(new_dirfd, 0, new_path, false) {
|
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
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(|_| host::__WASI_EILSEQ)?;
|
||||||
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
@@ -184,15 +176,8 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let dirfe = ctx.get_fd_entry(dirfd, needed_base, needed_inheriting)?;
|
let dirfe = ctx.get_fd_entry(dirfd, needed_base, needed_inheriting)?;
|
||||||
let dirfd = match &*dirfe.fd_object.descriptor {
|
let dirfd = dirfe.fd_object.descriptor.as_file()?;
|
||||||
Descriptor::File(f) => f,
|
let (dir, path) = path_get(dirfd, dirflags, path, nix_oflags.contains(OFlag::O_CREAT))?;
|
||||||
_ => return Err(host::__WASI_EBADF),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, dirflags, path, nix_oflags.contains(OFlag::O_CREAT)) {
|
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call openat. Use mode 0o666 so that we follow whatever the user's
|
// Call openat. Use mode 0o666 so that we follow whatever the user's
|
||||||
// umask is, but don't set the executable flag, because it isn't yet
|
// umask is, but don't set the executable flag, because it isn't yet
|
||||||
@@ -247,15 +232,13 @@ pub(crate) fn path_open(
|
|||||||
|
|
||||||
// Determine the type of the new file descriptor and which rights contradict with this type
|
// Determine the type of the new file descriptor and which rights contradict with this type
|
||||||
let file = unsafe { File::from_raw_fd(new_fd) };
|
let file = unsafe { File::from_raw_fd(new_fd) };
|
||||||
match determine_type_rights(&file) {
|
determine_type_rights(&file).and_then(|(_ty, max_base, max_inheriting)| {
|
||||||
Err(e) => Err(e),
|
FdEntry::from(file).map(|mut fe| {
|
||||||
Ok((_ty, max_base, max_inheriting)) => {
|
|
||||||
let mut fe = FdEntry::from(file)?;
|
|
||||||
fe.rights_base &= max_base;
|
fe.rights_base &= max_base;
|
||||||
fe.rights_inheriting &= max_inheriting;
|
fe.rights_inheriting &= max_inheriting;
|
||||||
Ok(fe)
|
fe
|
||||||
}
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
@@ -286,11 +269,7 @@ pub(crate) fn fd_readdir(
|
|||||||
if host_entry.is_null() {
|
if host_entry.is_null() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let entry: wasm32::__wasi_dirent_t =
|
let entry: wasm32::__wasi_dirent_t = host_impl::dirent_from_host(&unsafe { *host_entry })?;
|
||||||
match host_impl::dirent_from_host(&unsafe { *host_entry }) {
|
|
||||||
Ok(entry) => entry,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let name_len = entry.d_namlen as usize;
|
let name_len = entry.d_namlen as usize;
|
||||||
let required_space = std::mem::size_of_val(&entry) + name_len;
|
let required_space = std::mem::size_of_val(&entry) + name_len;
|
||||||
if required_space > left {
|
if required_space > left {
|
||||||
@@ -319,10 +298,7 @@ pub(crate) fn fd_readdir(
|
|||||||
pub(crate) fn path_readlink(dirfd: &File, path: &str, buf: &mut [u8]) -> Result<usize> {
|
pub(crate) fn path_readlink(dirfd: &File, path: &str, buf: &mut [u8]) -> Result<usize> {
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, 0, path, false) {
|
let (dir, path) = path_get(dirfd, 0, path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_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.
|
||||||
@@ -360,14 +336,8 @@ pub(crate) fn path_rename(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use nix::libc::renameat;
|
use nix::libc::renameat;
|
||||||
|
|
||||||
let (old_dir, old_path) = match path_get(old_dirfd, 0, old_path, false) {
|
let (old_dir, old_path) = path_get(old_dirfd, 0, old_path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
let (new_dir, new_path) = path_get(new_dirfd, 0, new_path, false)?;
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let (new_dir, new_path) = match path_get(new_dirfd, 0, new_path, false) {
|
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
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(|_| host::__WASI_EILSEQ)?;
|
||||||
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
@@ -388,10 +358,9 @@ pub(crate) fn path_rename(
|
|||||||
|
|
||||||
pub(crate) fn fd_filestat_get(fd: &File) -> Result<host::__wasi_filestat_t> {
|
pub(crate) fn fd_filestat_get(fd: &File) -> Result<host::__wasi_filestat_t> {
|
||||||
use nix::sys::stat::fstat;
|
use nix::sys::stat::fstat;
|
||||||
match fstat(fd.as_raw_fd()) {
|
let filestat =
|
||||||
Err(e) => Err(host_impl::errno_from_nix(e.as_errno().unwrap())),
|
fstat(fd.as_raw_fd()).map_err(|err| host_impl::errno_from_nix(err.as_errno().unwrap()))?;
|
||||||
Ok(filestat) => Ok(host_impl::filestat_from_nix(filestat)?),
|
host_impl::filestat_from_nix(filestat)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_filestat_set_times(
|
pub(crate) fn fd_filestat_set_times(
|
||||||
@@ -409,14 +378,10 @@ pub(crate) fn fd_filestat_set_times(
|
|||||||
if res != 0 {
|
if res != 0 {
|
||||||
return Err(host_impl::errno_from_nix(nix::errno::Errno::last()));
|
return Err(host_impl::errno_from_nix(nix::errno::Errno::last()));
|
||||||
}
|
}
|
||||||
let time_ns = match (timespec.tv_sec as host::__wasi_timestamp_t)
|
st_mtim = (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))
|
||||||
{
|
.ok_or(host::__WASI_EOVERFLOW)?;
|
||||||
Some(time_ns) => time_ns,
|
|
||||||
None => return Err(host::__WASI_EOVERFLOW),
|
|
||||||
};
|
|
||||||
st_mtim = time_ns;
|
|
||||||
}
|
}
|
||||||
let ts_atime = match fst_flags {
|
let ts_atime = match fst_flags {
|
||||||
f if f & host::__WASI_FILESTAT_SET_ATIM_NOW != 0 => libc::timespec {
|
f if f & host::__WASI_FILESTAT_SET_ATIM_NOW != 0 => libc::timespec {
|
||||||
@@ -455,19 +420,15 @@ pub(crate) fn path_filestat_get(
|
|||||||
use nix::fcntl::AtFlags;
|
use nix::fcntl::AtFlags;
|
||||||
use nix::sys::stat::fstatat;
|
use nix::sys::stat::fstatat;
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, dirflags, path, false) {
|
let (dir, path) = path_get(dirfd, dirflags, path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let atflags = match dirflags {
|
let atflags = match dirflags {
|
||||||
0 => AtFlags::empty(),
|
0 => AtFlags::empty(),
|
||||||
_ => AtFlags::AT_SYMLINK_NOFOLLOW,
|
_ => AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||||
};
|
};
|
||||||
|
|
||||||
match fstatat(dir.as_raw_fd(), path.as_str(), atflags) {
|
let filestat = fstatat(dir.as_raw_fd(), path.as_str(), atflags)
|
||||||
Err(e) => Err(host_impl::errno_from_nix(e.as_errno().unwrap())),
|
.map_err(|err| host_impl::errno_from_nix(err.as_errno().unwrap()))?;
|
||||||
Ok(filestat) => Ok(host_impl::filestat_from_nix(filestat)?),
|
host_impl::filestat_from_nix(filestat)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_filestat_set_times(
|
pub(crate) fn path_filestat_set_times(
|
||||||
@@ -480,10 +441,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use nix::sys::time::{TimeSpec, TimeValLike};
|
use nix::sys::time::{TimeSpec, TimeValLike};
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, dirflags, &path, false) {
|
let (dir, path) = path_get(dirfd, dirflags, &path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let atflags = match dirflags {
|
let atflags = match dirflags {
|
||||||
wasm32::__WASI_LOOKUP_SYMLINK_FOLLOW => 0,
|
wasm32::__WASI_LOOKUP_SYMLINK_FOLLOW => 0,
|
||||||
_ => libc::AT_SYMLINK_NOFOLLOW,
|
_ => libc::AT_SYMLINK_NOFOLLOW,
|
||||||
@@ -495,14 +453,10 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
if res != 0 {
|
if res != 0 {
|
||||||
return Err(host_impl::errno_from_nix(nix::errno::Errno::last()));
|
return Err(host_impl::errno_from_nix(nix::errno::Errno::last()));
|
||||||
}
|
}
|
||||||
let time_ns = match (timespec.tv_sec as host::__wasi_timestamp_t)
|
st_mtim = (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))
|
||||||
{
|
.ok_or(host::__WASI_EOVERFLOW)?;
|
||||||
Some(time_ns) => time_ns,
|
|
||||||
None => return Err(host::__WASI_EOVERFLOW),
|
|
||||||
};
|
|
||||||
st_mtim = time_ns;
|
|
||||||
}
|
}
|
||||||
let ts_atime = match fst_flags {
|
let ts_atime = match fst_flags {
|
||||||
f if f & host::__WASI_FILESTAT_SET_ATIM_NOW != 0 => libc::timespec {
|
f if f & host::__WASI_FILESTAT_SET_ATIM_NOW != 0 => libc::timespec {
|
||||||
@@ -534,10 +488,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
pub(crate) fn path_symlink(dirfd: &File, old_path: &str, new_path: &str) -> Result<()> {
|
pub(crate) fn path_symlink(dirfd: &File, old_path: &str, new_path: &str) -> Result<()> {
|
||||||
use nix::libc::symlinkat;
|
use nix::libc::symlinkat;
|
||||||
|
|
||||||
let (dir, new_path) = match path_get(dirfd, 0, new_path, false) {
|
let (dir, new_path) = path_get(dirfd, 0, new_path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
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(|_| host::__WASI_EILSEQ)?;
|
||||||
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let new_path_cstr = CString::new(new_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
@@ -559,10 +510,7 @@ pub(crate) fn path_unlink_file(dirfd: &File, path: &str) -> Result<()> {
|
|||||||
use nix::errno;
|
use nix::errno;
|
||||||
use nix::libc::unlinkat;
|
use nix::libc::unlinkat;
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, 0, path, false) {
|
let (dir, path) = path_get(dirfd, 0, path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
// nix doesn't expose unlinkat() yet
|
// nix doesn't expose unlinkat() yet
|
||||||
@@ -605,10 +553,7 @@ pub(crate) fn path_remove_directory(dirfd: &File, path: &str) -> Result<()> {
|
|||||||
use nix::errno;
|
use nix::errno;
|
||||||
use nix::libc::{unlinkat, AT_REMOVEDIR};
|
use nix::libc::{unlinkat, AT_REMOVEDIR};
|
||||||
|
|
||||||
let (dir, path) = match path_get(dirfd, 0, path, false) {
|
let (dir, path) = path_get(dirfd, 0, path, false)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
let path_cstr = CString::new(path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?;
|
||||||
|
|
||||||
// nix doesn't expose unlinkat() yet
|
// nix doesn't expose unlinkat() yet
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use super::fs_helpers::*;
|
use super::fs_helpers::*;
|
||||||
use crate::ctx::WasiCtx;
|
use crate::ctx::WasiCtx;
|
||||||
use crate::fdentry::{Descriptor, FdEntry};
|
use crate::fdentry::FdEntry;
|
||||||
use crate::sys::errno_from_host;
|
use crate::sys::errno_from_host;
|
||||||
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;
|
||||||
@@ -124,43 +124,32 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let dirfe = ctx.get_fd_entry(dirfd, needed_base, needed_inheriting)?;
|
let dirfe = ctx.get_fd_entry(dirfd, needed_base, needed_inheriting)?;
|
||||||
let dirfd = match &*dirfe.fd_object.descriptor {
|
let dirfd = dirfe.fd_object.descriptor.as_file()?;
|
||||||
Descriptor::File(f) => f,
|
let (dir, path) = path_get(
|
||||||
_ => return Err(host::__WASI_EBADF),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (dir, path) = match path_get(
|
|
||||||
dirfd,
|
dirfd,
|
||||||
dirflags,
|
dirflags,
|
||||||
path,
|
path,
|
||||||
!win_flags_attrs.contains(FlagsAndAttributes::FILE_FLAG_BACKUP_SEMANTICS),
|
!win_flags_attrs.contains(FlagsAndAttributes::FILE_FLAG_BACKUP_SEMANTICS),
|
||||||
) {
|
)?;
|
||||||
Ok((dir, path)) => (dir, path),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_handle = match winx::file::openat(
|
let new_handle = winx::file::openat(
|
||||||
dir.as_raw_handle(),
|
dir.as_raw_handle(),
|
||||||
path.as_str(),
|
path.as_str(),
|
||||||
win_rights,
|
win_rights,
|
||||||
win_create_disp,
|
win_create_disp,
|
||||||
win_flags_attrs,
|
win_flags_attrs,
|
||||||
) {
|
)
|
||||||
Ok(handle) => handle,
|
.map_err(host_impl::errno_from_win)?;
|
||||||
Err(e) => return Err(host_impl::errno_from_win(e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine the type of the new file descriptor and which rights contradict with this type
|
// Determine the type of the new file descriptor and which rights contradict with this type
|
||||||
let file = unsafe { File::from_raw_handle(new_handle) };
|
let file = unsafe { File::from_raw_handle(new_handle) };
|
||||||
match determine_type_rights(&file) {
|
determine_type_rights(&file).and_then(|(_ty, max_base, max_inheriting)| {
|
||||||
Err(e) => Err(e),
|
FdEntry::from(file).map(|mut fe| {
|
||||||
Ok((_ty, max_base, max_inheriting)) => {
|
|
||||||
let mut fe = FdEntry::from(file)?;
|
|
||||||
fe.rights_base &= max_base;
|
fe.rights_base &= max_base;
|
||||||
fe.rights_inheriting &= max_inheriting;
|
fe.rights_inheriting &= max_inheriting;
|
||||||
Ok(fe)
|
fe
|
||||||
}
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
|
|||||||
Reference in New Issue
Block a user