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:
Dan Gohman
2019-11-28 05:36:18 -08:00
committed by Jakub Konka
parent b69758f672
commit 1f9d764d5d
22 changed files with 278 additions and 191 deletions

View File

@@ -1,26 +1,27 @@
use crate::fdentry::Descriptor;
use crate::fdentry::{Descriptor, OsHandleRef};
use crate::{wasi, Error, Result};
use std::fs::File;
use std::io;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
#[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 {
Self(file)
}
}
impl AsRawHandle for OsFile {
impl AsRawHandle for OsHandle {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}
impl Deref for OsFile {
impl Deref for OsHandle {
type Target = File;
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 {
&mut self.0
}
@@ -37,7 +38,7 @@ impl DerefMut for OsFile {
impl AsRawHandle for Descriptor {
fn as_raw_handle(&self) -> RawHandle {
match self {
Self::OsFile(file) => file.as_raw_handle(),
Self::OsHandle(file) => file.as_raw_handle(),
Self::Stdin => io::stdin().as_raw_handle(),
Self::Stdout => io::stdout().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.
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
handle: &Handle,

View File

@@ -5,7 +5,7 @@ use crate::ctx::WasiCtx;
use crate::fdentry::FdEntry;
use crate::helpers::systemtime_to_timestamp;
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::hostcalls_impl::fs_helpers::PathGetExt;
use crate::{wasi, Error, Result};