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:
@@ -1,5 +1,5 @@
|
||||
use super::super::dir::{Dir, Entry, SeekLoc};
|
||||
use super::osfile::OsFile;
|
||||
use super::oshandle::OsHandle;
|
||||
use crate::hostcalls_impl::{Dirent, PathGet};
|
||||
use crate::sys::host_impl;
|
||||
use crate::sys::unix::str_to_cstring;
|
||||
@@ -205,12 +205,12 @@ pub(crate) fn fd_advise(
|
||||
}
|
||||
|
||||
pub(crate) fn fd_readdir<'a>(
|
||||
os_file: &'a mut OsFile,
|
||||
os_handle: &'a mut OsHandle,
|
||||
cookie: wasi::__wasi_dircookie_t,
|
||||
) -> Result<impl Iterator<Item = Result<Dirent>> + 'a> {
|
||||
use std::sync::Mutex;
|
||||
|
||||
let dir = match os_file.dir {
|
||||
let dir = match os_handle.dir {
|
||||
Some(ref mut dir) => dir,
|
||||
None => {
|
||||
// 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
|
||||
// than by means of closedir(), readdir(), readdir_r(), or rewinddir(),
|
||||
// the behaviour is undefined.
|
||||
let fd = (*os_file).try_clone()?;
|
||||
let fd = (*os_handle).try_clone()?;
|
||||
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();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pub(crate) mod filetime;
|
||||
pub(crate) mod hostcalls_impl;
|
||||
pub(crate) mod osfile;
|
||||
pub(crate) mod oshandle;
|
||||
|
||||
pub(crate) mod fdentry_impl {
|
||||
use crate::{sys::host_impl, Result};
|
||||
|
||||
@@ -5,9 +5,9 @@ use std::os::unix::prelude::{AsRawFd, RawFd};
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct OsFile {
|
||||
pub(crate) struct OsHandle {
|
||||
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,
|
||||
// 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
|
||||
@@ -21,19 +21,19 @@ pub(crate) struct OsFile {
|
||||
pub(crate) dir: Option<Mutex<Dir>>,
|
||||
}
|
||||
|
||||
impl From<fs::File> for OsFile {
|
||||
impl From<fs::File> for OsHandle {
|
||||
fn from(file: fs::File) -> Self {
|
||||
Self { file, dir: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for OsFile {
|
||||
impl AsRawFd for OsHandle {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.file.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OsFile {
|
||||
impl Deref for OsHandle {
|
||||
type Target = fs::File;
|
||||
|
||||
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 {
|
||||
&mut self.file
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
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::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
pub(crate) use super::linux::osfile::*;
|
||||
pub(crate) use super::linux::oshandle::*;
|
||||
pub(crate) use super::linux::fdentry_impl::*;
|
||||
} else if #[cfg(any(
|
||||
target_os = "macos",
|
||||
@@ -15,7 +17,7 @@ cfg_if::cfg_if! {
|
||||
target_os = "ios",
|
||||
target_os = "dragonfly"
|
||||
))] {
|
||||
pub(crate) use super::bsd::osfile::*;
|
||||
pub(crate) use super::bsd::oshandle::*;
|
||||
pub(crate) use super::bsd::fdentry_impl::*;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +25,7 @@ cfg_if::cfg_if! {
|
||||
impl AsRawFd for Descriptor {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
match self {
|
||||
Self::OsFile(file) => file.as_raw_fd(),
|
||||
Self::OsHandle(file) => file.as_raw_fd(),
|
||||
Self::Stdin => io::stdin().as_raw_fd(),
|
||||
Self::Stdout => io::stdout().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.
|
||||
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
||||
fd: &Fd,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pub(crate) mod filetime;
|
||||
pub(crate) mod hostcalls_impl;
|
||||
pub(crate) mod osfile;
|
||||
pub(crate) mod oshandle;
|
||||
|
||||
pub(crate) mod fdentry_impl {
|
||||
use crate::{sys::host_impl, Result};
|
||||
|
||||
@@ -3,21 +3,21 @@ use std::ops::{Deref, DerefMut};
|
||||
use std::os::unix::prelude::{AsRawFd, RawFd};
|
||||
|
||||
#[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 {
|
||||
Self(file)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for OsFile {
|
||||
impl AsRawFd for OsHandle {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OsFile {
|
||||
impl Deref for OsHandle {
|
||||
type Target = fs::File;
|
||||
|
||||
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 {
|
||||
&mut self.0
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user