Support fd_fdstat_get and fd_renumber on stdin/stdout/stderr (#631)
* Support fd_fdstat_get on stdin/stdout/stderr. Add a routine for obtaining an `OsFile` containing a file descriptor for stdin/stdout/stderr so that we can do fd_fdstat_get on them. * Add a testcase for fd_fdstat_get etc. on stdin etc. * Don't dup file descriptors in fd_renumber. * Fix compilation on macOS * Rename OsFile to OsHandle This commits renames `OsFile` to `OsHandle` which seems to make more sense semantically as it is permitted to hold a valid OS handle to OS entities other than simply file/dir (e.g., socket, stream, etc.). As such, this commit also renames methods on `Descriptor` struct from `as_actual_file` to `as_file` as this in reality does pertain ops on FS entities such as files/dirs, and `as_file` to `as_os_handle` as in this case it can be anything, from file, through a socket, to a stream. * Fix compilation on Linux * Introduce `OsHandleRef` for borrowing OS resources. To prevent a `ManuallyDrop<OsHandleRef>` from outliving the resource it holds on to, create an `OsHandleRef` class parameterized on the lifetime of the `Descriptor`. * Fix scoping to pub-priv and backport to snapshot_0
This commit is contained in:
31
crates/test-programs/wasi-tests/src/bin/stdio.rs
Normal file
31
crates/test-programs/wasi-tests/src/bin/stdio.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use libc;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
use std::{env, process};
|
||||||
|
use wasi::wasi_unstable;
|
||||||
|
use wasi_tests::wasi_wrappers::wasi_fd_fdstat_get;
|
||||||
|
|
||||||
|
unsafe fn test_stdio() {
|
||||||
|
for fd in &[
|
||||||
|
wasi_unstable::STDIN_FD,
|
||||||
|
wasi_unstable::STDOUT_FD,
|
||||||
|
wasi_unstable::STDERR_FD,
|
||||||
|
] {
|
||||||
|
let mut fdstat: wasi_unstable::FdStat = MaybeUninit::zeroed().assume_init();
|
||||||
|
let status = wasi_fd_fdstat_get(*fd, &mut fdstat);
|
||||||
|
assert_eq!(
|
||||||
|
status,
|
||||||
|
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||||
|
"fd_fdstat_get on stdio"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
wasi_unstable::fd_renumber(*fd, *fd + 100).is_ok(),
|
||||||
|
"renumbering stdio",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Run the tests.
|
||||||
|
unsafe { test_stdio() }
|
||||||
|
}
|
||||||
@@ -1,61 +1,44 @@
|
|||||||
use crate::sys::dev_null;
|
use crate::sys::dev_null;
|
||||||
use crate::sys::fdentry_impl::{determine_type_and_access_rights, OsFile};
|
use crate::sys::fdentry_impl::{
|
||||||
|
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
|
||||||
|
};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Descriptor {
|
pub(crate) enum Descriptor {
|
||||||
OsFile(OsFile),
|
OsHandle(OsHandle),
|
||||||
Stdin,
|
Stdin,
|
||||||
Stdout,
|
Stdout,
|
||||||
Stderr,
|
Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Descriptor {
|
impl Descriptor {
|
||||||
pub(crate) fn as_file(&self) -> Result<&OsFile> {
|
/// Return a reference to the `OsHandle` treating it as an actual file/dir, and
|
||||||
|
/// allowing operations which require an actual file and not just a stream or
|
||||||
|
/// socket file descriptor.
|
||||||
|
pub(crate) fn as_file(&self) -> Result<&OsHandle> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => Ok(file),
|
Self::OsHandle(file) => Ok(file),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(Error::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsFile> {
|
/// Like `as_file`, but return a mutable reference.
|
||||||
|
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsHandle> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => Ok(file),
|
Self::OsHandle(file) => Ok(file),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(Error::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_file(&self) -> bool {
|
/// Return an `OsHandle`, which may be a stream or socket file descriptor.
|
||||||
match self {
|
pub(crate) fn as_os_handle<'descriptor>(&'descriptor self) -> OsHandleRef<'descriptor> {
|
||||||
Self::OsFile(_) => true,
|
descriptor_as_oshandle(self)
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stdin(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stdin => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stdout(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stdout => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stderr(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stderr => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +65,7 @@ impl FdEntry {
|
|||||||
unsafe { determine_type_and_access_rights(&file) }.map(
|
unsafe { determine_type_and_access_rights(&file) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
file_type,
|
||||||
descriptor: Descriptor::OsFile(OsFile::from(file)),
|
descriptor: Descriptor::OsHandle(OsHandle::from(file)),
|
||||||
rights_base,
|
rights_base,
|
||||||
rights_inheriting,
|
rights_inheriting,
|
||||||
preopen_path: None,
|
preopen_path: None,
|
||||||
@@ -90,10 +73,6 @@ impl FdEntry {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn duplicate(file: &fs::File) -> Result<Self> {
|
|
||||||
Self::from(file.try_clone()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn duplicate_stdin() -> Result<Self> {
|
pub(crate) fn duplicate_stdin() -> Result<Self> {
|
||||||
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
@@ -184,3 +163,35 @@ impl FdEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This allows an `OsHandle` to be temporarily borrowed from a
|
||||||
|
/// `Descriptor`. The `Descriptor` continues to own the resource,
|
||||||
|
/// and `OsHandleRef`'s lifetime parameter ensures that it doesn't
|
||||||
|
/// outlive the `Descriptor`.
|
||||||
|
pub(crate) struct OsHandleRef<'descriptor> {
|
||||||
|
handle: ManuallyDrop<OsHandle>,
|
||||||
|
_ref: PhantomData<&'descriptor Descriptor>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> OsHandleRef<'descriptor> {
|
||||||
|
pub(crate) fn new(handle: ManuallyDrop<OsHandle>) -> Self {
|
||||||
|
OsHandleRef {
|
||||||
|
handle,
|
||||||
|
_ref: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> Deref for OsHandleRef<'descriptor> {
|
||||||
|
type Target = fs::File;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> DerefMut for OsHandleRef<'descriptor> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ pub(crate) unsafe fn fd_read(
|
|||||||
.get_fd_entry_mut(fd)?
|
.get_fd_entry_mut(fd)?
|
||||||
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
|
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
|
||||||
{
|
{
|
||||||
Descriptor::OsFile(file) => file.read_vectored(&mut iovs),
|
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
|
||||||
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
||||||
_ => return Err(Error::EBADF),
|
_ => return Err(Error::EBADF),
|
||||||
};
|
};
|
||||||
@@ -180,33 +180,25 @@ pub(crate) unsafe fn fd_renumber(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
||||||
|
|
||||||
if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) {
|
if !wasi_ctx.contains_fd_entry(from) {
|
||||||
return Err(Error::EBADF);
|
return Err(Error::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
|
||||||
let to_fe = wasi_ctx.get_fd_entry(to)?;
|
|
||||||
|
|
||||||
// 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 from_fe.preopen_path.is_some() || to_fe.preopen_path.is_some() {
|
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
||||||
|
if from_fe.preopen_path.is_some() {
|
||||||
|
return Err(Error::ENOTSUP);
|
||||||
|
}
|
||||||
|
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
|
||||||
|
if to_fe.preopen_path.is_some() {
|
||||||
return Err(Error::ENOTSUP);
|
return Err(Error::ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if stdio fds
|
|
||||||
// TODO should we renumber stdio fds?
|
|
||||||
if !from_fe.as_descriptor(0, 0)?.is_file() || !to_fe.as_descriptor(0, 0)?.is_file() {
|
|
||||||
return Err(Error::EBADF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let fe_from_dup = from_fe
|
let fe = wasi_ctx.remove_fd_entry(from)?;
|
||||||
.as_descriptor(0, 0)?
|
wasi_ctx.insert_fd_entry_at(to, fe);
|
||||||
.as_file()
|
|
||||||
.and_then(|file| FdEntry::duplicate(file))?;
|
|
||||||
|
|
||||||
wasi_ctx.insert_fd_entry_at(to, fe_from_dup);
|
|
||||||
wasi_ctx.remove_fd_entry(from)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -279,9 +271,12 @@ pub(crate) unsafe fn fd_fdstat_get(
|
|||||||
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
||||||
|
|
||||||
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
|
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
|
||||||
let wasi_fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
|
let host_fd = wasi_ctx
|
||||||
|
.get_fd_entry(fd)?
|
||||||
|
.as_descriptor(0, 0)?
|
||||||
|
.as_os_handle();
|
||||||
|
|
||||||
let fs_flags = hostcalls_impl::fd_fdstat_get(wasi_fd)?;
|
let fs_flags = hostcalls_impl::fd_fdstat_get(&host_fd)?;
|
||||||
|
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
let fe = wasi_ctx.get_fd_entry(fd)?;
|
||||||
fdstat.fs_filetype = fe.file_type;
|
fdstat.fs_filetype = fe.file_type;
|
||||||
@@ -301,9 +296,12 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
||||||
|
|
||||||
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
|
let fd = wasi_ctx
|
||||||
|
.get_fd_entry(fd)?
|
||||||
|
.as_descriptor(0, 0)?
|
||||||
|
.as_os_handle();
|
||||||
|
|
||||||
hostcalls_impl::fd_fdstat_set_flags(fd, fdflags)
|
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn fd_fdstat_set_rights(
|
pub(crate) unsafe fn fd_fdstat_set_rights(
|
||||||
@@ -365,7 +363,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
.get_fd_entry_mut(fd)?
|
.get_fd_entry_mut(fd)?
|
||||||
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?
|
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?
|
||||||
{
|
{
|
||||||
Descriptor::OsFile(file) => file.write_vectored(&iovs)?,
|
Descriptor::OsHandle(file) => file.write_vectored(&iovs)?,
|
||||||
Descriptor::Stdin => return Err(Error::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
|
||||||
|
|||||||
@@ -1,61 +1,44 @@
|
|||||||
use crate::old::snapshot_0::sys::dev_null;
|
use crate::old::snapshot_0::sys::dev_null;
|
||||||
use crate::old::snapshot_0::sys::fdentry_impl::{determine_type_and_access_rights, OsFile};
|
use crate::old::snapshot_0::sys::fdentry_impl::{
|
||||||
|
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
|
||||||
|
};
|
||||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Descriptor {
|
pub(crate) enum Descriptor {
|
||||||
OsFile(OsFile),
|
OsHandle(OsHandle),
|
||||||
Stdin,
|
Stdin,
|
||||||
Stdout,
|
Stdout,
|
||||||
Stderr,
|
Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Descriptor {
|
impl Descriptor {
|
||||||
pub(crate) fn as_file(&self) -> Result<&OsFile> {
|
/// Return a reference to the `OsHandle` treating it as an actual file/dir, and
|
||||||
|
/// allowing operations which require an actual file and not just a stream or
|
||||||
|
/// socket file descriptor.
|
||||||
|
pub(crate) fn as_file(&self) -> Result<&OsHandle> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => Ok(file),
|
Self::OsHandle(file) => Ok(file),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(Error::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsFile> {
|
/// Like `as_file`, but return a mutable reference.
|
||||||
|
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsHandle> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => Ok(file),
|
Self::OsHandle(file) => Ok(file),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(Error::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_file(&self) -> bool {
|
/// Return an `OsHandle`, which may be a stream or socket file descriptor.
|
||||||
match self {
|
pub(crate) fn as_os_handle<'descriptor>(&'descriptor self) -> OsHandleRef<'descriptor> {
|
||||||
Self::OsFile(_) => true,
|
descriptor_as_oshandle(self)
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stdin(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stdin => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stdout(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stdout => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn is_stderr(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Stderr => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +65,7 @@ impl FdEntry {
|
|||||||
unsafe { determine_type_and_access_rights(&file) }.map(
|
unsafe { determine_type_and_access_rights(&file) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
file_type,
|
||||||
descriptor: Descriptor::OsFile(OsFile::from(file)),
|
descriptor: Descriptor::OsHandle(OsHandle::from(file)),
|
||||||
rights_base,
|
rights_base,
|
||||||
rights_inheriting,
|
rights_inheriting,
|
||||||
preopen_path: None,
|
preopen_path: None,
|
||||||
@@ -90,10 +73,6 @@ impl FdEntry {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn duplicate(file: &fs::File) -> Result<Self> {
|
|
||||||
Self::from(file.try_clone()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn duplicate_stdin() -> Result<Self> {
|
pub(crate) fn duplicate_stdin() -> Result<Self> {
|
||||||
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
@@ -184,3 +163,35 @@ impl FdEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This allows an `OsHandle` to be temporarily borrowed from a
|
||||||
|
/// `Descriptor`. The `Descriptor` continues to own the resource,
|
||||||
|
/// and `OsHandleRef`'s lifetime parameter ensures that it doesn't
|
||||||
|
/// outlive the `Descriptor`.
|
||||||
|
pub(crate) struct OsHandleRef<'descriptor> {
|
||||||
|
handle: ManuallyDrop<OsHandle>,
|
||||||
|
_ref: PhantomData<&'descriptor Descriptor>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> OsHandleRef<'descriptor> {
|
||||||
|
pub(crate) fn new(handle: ManuallyDrop<OsHandle>) -> Self {
|
||||||
|
OsHandleRef {
|
||||||
|
handle,
|
||||||
|
_ref: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> Deref for OsHandleRef<'descriptor> {
|
||||||
|
type Target = fs::File;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'descriptor> DerefMut for OsHandleRef<'descriptor> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ pub(crate) unsafe fn fd_read(
|
|||||||
.get_fd_entry_mut(fd)?
|
.get_fd_entry_mut(fd)?
|
||||||
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
|
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
|
||||||
{
|
{
|
||||||
Descriptor::OsFile(file) => file.read_vectored(&mut iovs),
|
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
|
||||||
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
||||||
_ => return Err(Error::EBADF),
|
_ => return Err(Error::EBADF),
|
||||||
};
|
};
|
||||||
@@ -180,33 +180,25 @@ pub(crate) unsafe fn fd_renumber(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
||||||
|
|
||||||
if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) {
|
if !wasi_ctx.contains_fd_entry(from) {
|
||||||
return Err(Error::EBADF);
|
return Err(Error::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
|
||||||
let to_fe = wasi_ctx.get_fd_entry(to)?;
|
|
||||||
|
|
||||||
// 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 from_fe.preopen_path.is_some() || to_fe.preopen_path.is_some() {
|
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
||||||
|
if from_fe.preopen_path.is_some() {
|
||||||
|
return Err(Error::ENOTSUP);
|
||||||
|
}
|
||||||
|
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
|
||||||
|
if to_fe.preopen_path.is_some() {
|
||||||
return Err(Error::ENOTSUP);
|
return Err(Error::ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if stdio fds
|
|
||||||
// TODO should we renumber stdio fds?
|
|
||||||
if !from_fe.as_descriptor(0, 0)?.is_file() || !to_fe.as_descriptor(0, 0)?.is_file() {
|
|
||||||
return Err(Error::EBADF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let fe_from_dup = from_fe
|
let fe = wasi_ctx.remove_fd_entry(from)?;
|
||||||
.as_descriptor(0, 0)?
|
wasi_ctx.insert_fd_entry_at(to, fe);
|
||||||
.as_file()
|
|
||||||
.and_then(|file| FdEntry::duplicate(file))?;
|
|
||||||
|
|
||||||
wasi_ctx.insert_fd_entry_at(to, fe_from_dup);
|
|
||||||
wasi_ctx.remove_fd_entry(from)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -279,9 +271,12 @@ pub(crate) unsafe fn fd_fdstat_get(
|
|||||||
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
||||||
|
|
||||||
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
|
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
|
||||||
let wasi_fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
|
let host_fd = wasi_ctx
|
||||||
|
.get_fd_entry(fd)?
|
||||||
|
.as_descriptor(0, 0)?
|
||||||
|
.as_os_handle();
|
||||||
|
|
||||||
let fs_flags = hostcalls_impl::fd_fdstat_get(wasi_fd)?;
|
let fs_flags = hostcalls_impl::fd_fdstat_get(&host_fd)?;
|
||||||
|
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
let fe = wasi_ctx.get_fd_entry(fd)?;
|
||||||
fdstat.fs_filetype = fe.file_type;
|
fdstat.fs_filetype = fe.file_type;
|
||||||
@@ -301,9 +296,12 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
||||||
|
|
||||||
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
|
let fd = wasi_ctx
|
||||||
|
.get_fd_entry(fd)?
|
||||||
|
.as_descriptor(0, 0)?
|
||||||
|
.as_os_handle();
|
||||||
|
|
||||||
hostcalls_impl::fd_fdstat_set_flags(fd, fdflags)
|
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn fd_fdstat_set_rights(
|
pub(crate) unsafe fn fd_fdstat_set_rights(
|
||||||
@@ -365,7 +363,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
.get_fd_entry_mut(fd)?
|
.get_fd_entry_mut(fd)?
|
||||||
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?
|
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?
|
||||||
{
|
{
|
||||||
Descriptor::OsFile(file) => file.write_vectored(&iovs)?,
|
Descriptor::OsHandle(file) => file.write_vectored(&iovs)?,
|
||||||
Descriptor::Stdin => return Err(Error::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
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::osfile::OsFile;
|
use super::oshandle::OsHandle;
|
||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
||||||
use crate::old::snapshot_0::sys::host_impl;
|
use crate::old::snapshot_0::sys::host_impl;
|
||||||
use crate::old::snapshot_0::sys::unix::str_to_cstring;
|
use crate::old::snapshot_0::sys::unix::str_to_cstring;
|
||||||
@@ -140,23 +140,23 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
os_file: &mut OsFile,
|
os_handle: &mut OsHandle,
|
||||||
host_buf: &mut [u8],
|
host_buf: &mut [u8],
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
use crate::old::snapshot_0::sys::unix::bsd::osfile::DirStream;
|
use crate::old::snapshot_0::sys::unix::bsd::oshandle::DirStream;
|
||||||
use libc::{fdopendir, readdir, rewinddir, seekdir, telldir};
|
use libc::{fdopendir, readdir, rewinddir, seekdir, telldir};
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
let dir_stream = match os_file.dir_stream {
|
let dir_stream = match os_handle.dir_stream {
|
||||||
Some(ref mut dir_stream) => dir_stream,
|
Some(ref mut dir_stream) => dir_stream,
|
||||||
None => {
|
None => {
|
||||||
let file = os_file.file.try_clone()?;
|
let file = os_handle.file.try_clone()?;
|
||||||
let dir_ptr = unsafe { fdopendir(file.as_raw_fd()) };
|
let dir_ptr = unsafe { fdopendir(file.as_raw_fd()) };
|
||||||
os_file.dir_stream.get_or_insert(Mutex::new(DirStream {
|
os_handle.dir_stream.get_or_insert(Mutex::new(DirStream {
|
||||||
file: ManuallyDrop::new(file),
|
file: ManuallyDrop::new(file),
|
||||||
dir_ptr,
|
dir_ptr,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pub(crate) mod filetime;
|
pub(crate) mod filetime;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
pub(crate) mod osfile;
|
pub(crate) mod oshandle;
|
||||||
|
|
||||||
pub(crate) mod fdentry_impl {
|
pub(crate) mod fdentry_impl {
|
||||||
use crate::old::snapshot_0::{sys::host_impl, Result};
|
use crate::old::snapshot_0::{sys::host_impl, Result};
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ impl Drop for DirStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile {
|
pub(crate) struct OsHandle {
|
||||||
pub(crate) file: fs::File,
|
pub(crate) file: fs::File,
|
||||||
pub(crate) dir_stream: Option<Mutex<DirStream>>,
|
pub(crate) dir_stream: Option<Mutex<DirStream>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<fs::File> for OsFile {
|
impl From<fs::File> for OsHandle {
|
||||||
fn from(file: fs::File) -> Self {
|
fn from(file: fs::File) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file,
|
file,
|
||||||
@@ -31,13 +31,13 @@ impl From<fs::File> for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for OsFile {
|
impl AsRawFd for OsHandle {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.file.as_raw_fd()
|
self.file.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = fs::File;
|
type Target = fs::File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -45,7 +45,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.file
|
&mut self.file
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::old::snapshot_0::fdentry::Descriptor;
|
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
|
||||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||||
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_os = "linux")] {
|
if #[cfg(target_os = "linux")] {
|
||||||
pub(crate) use super::linux::osfile::*;
|
pub(crate) use super::linux::oshandle::*;
|
||||||
pub(crate) use super::linux::fdentry_impl::*;
|
pub(crate) use super::linux::fdentry_impl::*;
|
||||||
} else if #[cfg(any(
|
} else if #[cfg(any(
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
@@ -15,7 +17,7 @@ cfg_if::cfg_if! {
|
|||||||
target_os = "ios",
|
target_os = "ios",
|
||||||
target_os = "dragonfly"
|
target_os = "dragonfly"
|
||||||
))] {
|
))] {
|
||||||
pub(crate) use super::bsd::osfile::*;
|
pub(crate) use super::bsd::oshandle::*;
|
||||||
pub(crate) use super::bsd::fdentry_impl::*;
|
pub(crate) use super::bsd::fdentry_impl::*;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +25,7 @@ cfg_if::cfg_if! {
|
|||||||
impl AsRawFd for Descriptor {
|
impl AsRawFd for Descriptor {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => file.as_raw_fd(),
|
Self::OsHandle(file) => file.as_raw_fd(),
|
||||||
Self::Stdin => io::stdin().as_raw_fd(),
|
Self::Stdin => io::stdin().as_raw_fd(),
|
||||||
Self::Stdout => io::stdout().as_raw_fd(),
|
Self::Stdout => io::stdout().as_raw_fd(),
|
||||||
Self::Stderr => io::stderr().as_raw_fd(),
|
Self::Stderr => io::stderr().as_raw_fd(),
|
||||||
@@ -31,6 +33,14 @@ impl AsRawFd for Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn descriptor_as_oshandle<'lifetime>(
|
||||||
|
desc: &'lifetime Descriptor,
|
||||||
|
) -> OsHandleRef<'lifetime> {
|
||||||
|
OsHandleRef::new(ManuallyDrop::new(OsHandle::from(unsafe {
|
||||||
|
File::from_raw_fd(desc.as_raw_fd())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is unsafe because it operates on a raw file descriptor.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::super::dir::{Dir, Entry, SeekLoc};
|
use super::super::dir::{Dir, Entry, SeekLoc};
|
||||||
use super::osfile::OsFile;
|
use super::oshandle::OsHandle;
|
||||||
use crate::old::snapshot_0::hostcalls_impl::{Dirent, PathGet};
|
use crate::old::snapshot_0::hostcalls_impl::{Dirent, PathGet};
|
||||||
use crate::old::snapshot_0::sys::host_impl;
|
use crate::old::snapshot_0::sys::host_impl;
|
||||||
use crate::old::snapshot_0::sys::unix::str_to_cstring;
|
use crate::old::snapshot_0::sys::unix::str_to_cstring;
|
||||||
@@ -115,11 +115,11 @@ pub(crate) fn fd_readdir_impl(
|
|||||||
// This should actually be common code with Windows,
|
// This should actually be common code with Windows,
|
||||||
// but there's BSD stuff remaining
|
// but there's BSD stuff remaining
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
os_file: &mut OsFile,
|
os_handle: &mut OsHandle,
|
||||||
mut host_buf: &mut [u8],
|
mut host_buf: &mut [u8],
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
let iter = fd_readdir_impl(os_file, cookie)?;
|
let iter = fd_readdir_impl(os_handle, cookie)?;
|
||||||
let mut used = 0;
|
let mut used = 0;
|
||||||
for dirent in iter {
|
for dirent in iter {
|
||||||
let dirent_raw = dirent?.to_wasi_raw()?;
|
let dirent_raw = dirent?.to_wasi_raw()?;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pub(crate) mod filetime;
|
pub(crate) mod filetime;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
pub(crate) mod osfile;
|
pub(crate) mod oshandle;
|
||||||
|
|
||||||
pub(crate) mod fdentry_impl {
|
pub(crate) mod fdentry_impl {
|
||||||
use crate::old::snapshot_0::{sys::host_impl, Result};
|
use crate::old::snapshot_0::{sys::host_impl, Result};
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ use std::ops::{Deref, DerefMut};
|
|||||||
use std::os::unix::prelude::{AsRawFd, RawFd};
|
use std::os::unix::prelude::{AsRawFd, RawFd};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile(fs::File);
|
pub(crate) struct OsHandle(fs::File);
|
||||||
|
|
||||||
impl From<fs::File> for OsFile {
|
impl From<fs::File> for OsHandle {
|
||||||
fn from(file: fs::File) -> Self {
|
fn from(file: fs::File) -> Self {
|
||||||
Self(file)
|
Self(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for OsFile {
|
impl AsRawFd for OsHandle {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.0.as_raw_fd()
|
self.0.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = fs::File;
|
type Target = fs::File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -25,7 +25,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
use crate::old::snapshot_0::fdentry::Descriptor;
|
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
|
||||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile(File);
|
pub(crate) struct OsHandle(File);
|
||||||
|
|
||||||
impl From<File> for OsFile {
|
impl From<File> for OsHandle {
|
||||||
fn from(file: File) -> Self {
|
fn from(file: File) -> Self {
|
||||||
Self(file)
|
Self(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawHandle for OsFile {
|
impl AsRawHandle for OsHandle {
|
||||||
fn as_raw_handle(&self) -> RawHandle {
|
fn as_raw_handle(&self) -> RawHandle {
|
||||||
self.0.as_raw_handle()
|
self.0.as_raw_handle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = File;
|
type Target = File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -28,7 +29,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ impl DerefMut for OsFile {
|
|||||||
impl AsRawHandle for Descriptor {
|
impl AsRawHandle for Descriptor {
|
||||||
fn as_raw_handle(&self) -> RawHandle {
|
fn as_raw_handle(&self) -> RawHandle {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => file.as_raw_handle(),
|
Self::OsHandle(file) => file.as_raw_handle(),
|
||||||
Self::Stdin => io::stdin().as_raw_handle(),
|
Self::Stdin => io::stdin().as_raw_handle(),
|
||||||
Self::Stdout => io::stdout().as_raw_handle(),
|
Self::Stdout => io::stdout().as_raw_handle(),
|
||||||
Self::Stderr => io::stderr().as_raw_handle(),
|
Self::Stderr => io::stderr().as_raw_handle(),
|
||||||
@@ -45,6 +46,14 @@ impl AsRawHandle for Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn descriptor_as_oshandle<'lifetime>(
|
||||||
|
desc: &'lifetime Descriptor,
|
||||||
|
) -> OsHandleRef<'lifetime> {
|
||||||
|
OsHandleRef::new(ManuallyDrop::new(OsHandle::from(unsafe {
|
||||||
|
File::from_raw_handle(desc.as_raw_handle())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is unsafe because it operates on a raw file handle.
|
/// This function is unsafe because it operates on a raw file handle.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::old::snapshot_0::helpers::systemtime_to_timestamp;
|
|||||||
use crate::old::snapshot_0::hostcalls_impl::{
|
use crate::old::snapshot_0::hostcalls_impl::{
|
||||||
fd_filestat_set_times_impl, Dirent, FileType, PathGet,
|
fd_filestat_set_times_impl, Dirent, FileType, PathGet,
|
||||||
};
|
};
|
||||||
use crate::old::snapshot_0::sys::fdentry_impl::{determine_type_rights, OsFile};
|
use crate::old::snapshot_0::sys::fdentry_impl::{determine_type_rights, OsHandle};
|
||||||
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
|
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
|
||||||
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||||
@@ -261,11 +261,11 @@ pub(crate) fn fd_readdir_impl(
|
|||||||
|
|
||||||
// This should actually be common code with Linux
|
// This should actually be common code with Linux
|
||||||
pub(crate) fn fd_readdir(
|
pub(crate) fn fd_readdir(
|
||||||
os_file: &mut OsFile,
|
os_handle: &mut OsHandle,
|
||||||
mut host_buf: &mut [u8],
|
mut host_buf: &mut [u8],
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
let iter = fd_readdir_impl(os_file, cookie)?;
|
let iter = fd_readdir_impl(os_handle, cookie)?;
|
||||||
let mut used = 0;
|
let mut used = 0;
|
||||||
for dirent in iter {
|
for dirent in iter {
|
||||||
let dirent_raw = dirent?.to_wasi_raw()?;
|
let dirent_raw = dirent?.to_wasi_raw()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::super::dir::{Dir, Entry, SeekLoc};
|
use super::super::dir::{Dir, Entry, SeekLoc};
|
||||||
use super::osfile::OsFile;
|
use super::oshandle::OsHandle;
|
||||||
use crate::hostcalls_impl::{Dirent, PathGet};
|
use crate::hostcalls_impl::{Dirent, PathGet};
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::sys::unix::str_to_cstring;
|
use crate::sys::unix::str_to_cstring;
|
||||||
@@ -205,12 +205,12 @@ pub(crate) fn fd_advise(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fd_readdir<'a>(
|
pub(crate) fn fd_readdir<'a>(
|
||||||
os_file: &'a mut OsFile,
|
os_handle: &'a mut OsHandle,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<impl Iterator<Item = Result<Dirent>> + 'a> {
|
) -> Result<impl Iterator<Item = Result<Dirent>> + 'a> {
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
let dir = match os_file.dir {
|
let dir = match os_handle.dir {
|
||||||
Some(ref mut dir) => dir,
|
Some(ref mut dir) => dir,
|
||||||
None => {
|
None => {
|
||||||
// We need to duplicate the fd, because `opendir(3)`:
|
// We need to duplicate the fd, because `opendir(3)`:
|
||||||
@@ -219,9 +219,9 @@ pub(crate) fn fd_readdir<'a>(
|
|||||||
// descriptor, or to modify the state of the associated description other
|
// descriptor, or to modify the state of the associated description other
|
||||||
// than by means of closedir(), readdir(), readdir_r(), or rewinddir(),
|
// than by means of closedir(), readdir(), readdir_r(), or rewinddir(),
|
||||||
// the behaviour is undefined.
|
// the behaviour is undefined.
|
||||||
let fd = (*os_file).try_clone()?;
|
let fd = (*os_handle).try_clone()?;
|
||||||
let dir = Dir::from(fd)?;
|
let dir = Dir::from(fd)?;
|
||||||
os_file.dir.get_or_insert(Mutex::new(dir))
|
os_handle.dir.get_or_insert(Mutex::new(dir))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut dir = dir.lock().unwrap();
|
let mut dir = dir.lock().unwrap();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pub(crate) mod filetime;
|
pub(crate) mod filetime;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
pub(crate) mod osfile;
|
pub(crate) mod oshandle;
|
||||||
|
|
||||||
pub(crate) mod fdentry_impl {
|
pub(crate) mod fdentry_impl {
|
||||||
use crate::{sys::host_impl, Result};
|
use crate::{sys::host_impl, Result};
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use std::os::unix::prelude::{AsRawFd, RawFd};
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile {
|
pub(crate) struct OsHandle {
|
||||||
pub(crate) file: fs::File,
|
pub(crate) file: fs::File,
|
||||||
// In case that this `OsFile` actually refers to a directory,
|
// In case that this `OsHandle` actually refers to a directory,
|
||||||
// when the client makes a `fd_readdir` syscall on this descriptor,
|
// when the client makes a `fd_readdir` syscall on this descriptor,
|
||||||
// we will need to cache the `libc::DIR` pointer manually in order
|
// we will need to cache the `libc::DIR` pointer manually in order
|
||||||
// to be able to seek on it later. While on Linux, this is handled
|
// to be able to seek on it later. While on Linux, this is handled
|
||||||
@@ -21,19 +21,19 @@ pub(crate) struct OsFile {
|
|||||||
pub(crate) dir: Option<Mutex<Dir>>,
|
pub(crate) dir: Option<Mutex<Dir>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<fs::File> for OsFile {
|
impl From<fs::File> for OsHandle {
|
||||||
fn from(file: fs::File) -> Self {
|
fn from(file: fs::File) -> Self {
|
||||||
Self { file, dir: None }
|
Self { file, dir: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for OsFile {
|
impl AsRawFd for OsHandle {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.file.as_raw_fd()
|
self.file.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = fs::File;
|
type Target = fs::File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -41,7 +41,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.file
|
&mut self.file
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::{Descriptor, OsHandleRef};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_os = "linux")] {
|
if #[cfg(target_os = "linux")] {
|
||||||
pub(crate) use super::linux::osfile::*;
|
pub(crate) use super::linux::oshandle::*;
|
||||||
pub(crate) use super::linux::fdentry_impl::*;
|
pub(crate) use super::linux::fdentry_impl::*;
|
||||||
} else if #[cfg(any(
|
} else if #[cfg(any(
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
@@ -15,7 +17,7 @@ cfg_if::cfg_if! {
|
|||||||
target_os = "ios",
|
target_os = "ios",
|
||||||
target_os = "dragonfly"
|
target_os = "dragonfly"
|
||||||
))] {
|
))] {
|
||||||
pub(crate) use super::bsd::osfile::*;
|
pub(crate) use super::bsd::oshandle::*;
|
||||||
pub(crate) use super::bsd::fdentry_impl::*;
|
pub(crate) use super::bsd::fdentry_impl::*;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +25,7 @@ cfg_if::cfg_if! {
|
|||||||
impl AsRawFd for Descriptor {
|
impl AsRawFd for Descriptor {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => file.as_raw_fd(),
|
Self::OsHandle(file) => file.as_raw_fd(),
|
||||||
Self::Stdin => io::stdin().as_raw_fd(),
|
Self::Stdin => io::stdin().as_raw_fd(),
|
||||||
Self::Stdout => io::stdout().as_raw_fd(),
|
Self::Stdout => io::stdout().as_raw_fd(),
|
||||||
Self::Stderr => io::stderr().as_raw_fd(),
|
Self::Stderr => io::stderr().as_raw_fd(),
|
||||||
@@ -31,6 +33,14 @@ impl AsRawFd for Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn descriptor_as_oshandle<'lifetime>(
|
||||||
|
desc: &'lifetime Descriptor,
|
||||||
|
) -> OsHandleRef<'lifetime> {
|
||||||
|
OsHandleRef::new(ManuallyDrop::new(OsHandle::from(unsafe {
|
||||||
|
File::from_raw_fd(desc.as_raw_fd())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is unsafe because it operates on a raw file descriptor.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pub(crate) mod filetime;
|
pub(crate) mod filetime;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
pub(crate) mod osfile;
|
pub(crate) mod oshandle;
|
||||||
|
|
||||||
pub(crate) mod fdentry_impl {
|
pub(crate) mod fdentry_impl {
|
||||||
use crate::{sys::host_impl, Result};
|
use crate::{sys::host_impl, Result};
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ use std::ops::{Deref, DerefMut};
|
|||||||
use std::os::unix::prelude::{AsRawFd, RawFd};
|
use std::os::unix::prelude::{AsRawFd, RawFd};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile(fs::File);
|
pub(crate) struct OsHandle(fs::File);
|
||||||
|
|
||||||
impl From<fs::File> for OsFile {
|
impl From<fs::File> for OsHandle {
|
||||||
fn from(file: fs::File) -> Self {
|
fn from(file: fs::File) -> Self {
|
||||||
Self(file)
|
Self(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for OsFile {
|
impl AsRawFd for OsHandle {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.0.as_raw_fd()
|
self.0.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = fs::File;
|
type Target = fs::File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -25,7 +25,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::{Descriptor, OsHandleRef};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OsFile(File);
|
pub(crate) struct OsHandle(File);
|
||||||
|
|
||||||
impl From<File> for OsFile {
|
impl From<File> for OsHandle {
|
||||||
fn from(file: File) -> Self {
|
fn from(file: File) -> Self {
|
||||||
Self(file)
|
Self(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawHandle for OsFile {
|
impl AsRawHandle for OsHandle {
|
||||||
fn as_raw_handle(&self) -> RawHandle {
|
fn as_raw_handle(&self) -> RawHandle {
|
||||||
self.0.as_raw_handle()
|
self.0.as_raw_handle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for OsFile {
|
impl Deref for OsHandle {
|
||||||
type Target = File;
|
type Target = File;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@@ -28,7 +29,7 @@ impl Deref for OsFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for OsFile {
|
impl DerefMut for OsHandle {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ impl DerefMut for OsFile {
|
|||||||
impl AsRawHandle for Descriptor {
|
impl AsRawHandle for Descriptor {
|
||||||
fn as_raw_handle(&self) -> RawHandle {
|
fn as_raw_handle(&self) -> RawHandle {
|
||||||
match self {
|
match self {
|
||||||
Self::OsFile(file) => file.as_raw_handle(),
|
Self::OsHandle(file) => file.as_raw_handle(),
|
||||||
Self::Stdin => io::stdin().as_raw_handle(),
|
Self::Stdin => io::stdin().as_raw_handle(),
|
||||||
Self::Stdout => io::stdout().as_raw_handle(),
|
Self::Stdout => io::stdout().as_raw_handle(),
|
||||||
Self::Stderr => io::stderr().as_raw_handle(),
|
Self::Stderr => io::stderr().as_raw_handle(),
|
||||||
@@ -45,6 +46,14 @@ impl AsRawHandle for Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn descriptor_as_oshandle<'lifetime>(
|
||||||
|
desc: &'lifetime Descriptor,
|
||||||
|
) -> OsHandleRef<'lifetime> {
|
||||||
|
OsHandleRef::new(ManuallyDrop::new(OsHandle::from(unsafe {
|
||||||
|
File::from_raw_handle(desc.as_raw_handle())
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is unsafe because it operates on a raw file handle.
|
/// This function is unsafe because it operates on a raw file handle.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::ctx::WasiCtx;
|
|||||||
use crate::fdentry::FdEntry;
|
use crate::fdentry::FdEntry;
|
||||||
use crate::helpers::systemtime_to_timestamp;
|
use crate::helpers::systemtime_to_timestamp;
|
||||||
use crate::hostcalls_impl::{fd_filestat_set_times_impl, Dirent, FileType, PathGet};
|
use crate::hostcalls_impl::{fd_filestat_set_times_impl, Dirent, FileType, PathGet};
|
||||||
use crate::sys::fdentry_impl::{determine_type_rights, OsFile};
|
use crate::sys::fdentry_impl::determine_type_rights;
|
||||||
use crate::sys::host_impl::{self, path_from_host};
|
use crate::sys::host_impl::{self, path_from_host};
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
|
|||||||
Reference in New Issue
Block a user