From 132ec261b0d215f77b71eeee3d814cd304fc1a29 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 22 Feb 2021 14:21:43 -0800 Subject: [PATCH 1/6] Enable API documentation for `std::os::wasi`. This adds API documentation support for `std::os::wasi` modeled after how `std::os::unix` works, so that WASI can be documented [here] along with the other platforms. [here]: https://doc.rust-lang.org/stable/std/os/index.html Two changes of particular interest: - This changes the `AsRawFd` for `io::Stdin` for WASI to return `libc::STDIN_FILENO` instead of `sys::stdio::Stdin.as_raw_fd()` (and similar for `Stdout` and `Stderr`), which matches how the `unix` version works. `STDIN_FILENO` etc. may not always be explicitly reserved at the WASI level, but as long as we have Rust's `std` and `libc`, I think it's reasonable to guarantee that we'll always use `libc::STDIN_FILENO` for stdin. - This duplicates the `osstr2str` utility function, rather than trying to share it across all the configurations that need it. --- library/std/src/os/mod.rs | 3 +++ library/std/src/sys/mod.rs | 30 +++++++++++++++++++++++++---- library/std/src/sys/wasi/ext/fs.rs | 25 +++++++++++++++--------- library/std/src/sys/wasi/ext/io.rs | 12 ++++++------ library/std/src/sys/wasi/ext/mod.rs | 28 +++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index f61e402e37027..fad5886def700 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -22,6 +22,9 @@ pub use crate::sys::windows_ext as windows; #[doc(cfg(target_os = "linux"))] pub mod linux; +#[cfg(doc)] +pub use crate::sys::wasi_ext as wasi; + // If we're not documenting libstd then we just expose the main modules as we otherwise would. #[cfg(not(doc))] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index d48d9cb0efce0..d3f53801d2d0f 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -61,9 +61,9 @@ cfg_if::cfg_if! { #[stable(feature = "rust1", since = "1.0.0")] pub use self::ext as unix_ext; } else if #[cfg(any(target_os = "hermit", - target_arch = "wasm32", + all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx")))] { - // On wasm right now the module below doesn't compile + // On non-WASI wasm right now the module below doesn't compile // (missing things in `libc` which is empty) so just omit everything // with an empty module #[unstable(issue = "none", feature = "std_internals")] @@ -85,9 +85,9 @@ cfg_if::cfg_if! { #[stable(feature = "rust1", since = "1.0.0")] pub use self::ext as windows_ext; } else if #[cfg(any(target_os = "hermit", - target_arch = "wasm32", + all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx")))] { - // On wasm right now the shim below doesn't compile, so + // On non-WASI wasm right now the shim below doesn't compile, so // just omit it #[unstable(issue = "none", feature = "std_internals")] #[allow(missing_docs)] @@ -106,3 +106,25 @@ cfg_if::cfg_if! { pub mod windows_ext; } } + +#[cfg(doc)] +cfg_if::cfg_if! { + if #[cfg(target_os = "wasi")] { + // On WASI we'll document what's already available + #[stable(feature = "rust1", since = "1.0.0")] + pub use self::ext as wasi_ext; + } else if #[cfg(any(target_os = "hermit", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] { + // On non-WASI wasm right now the module below doesn't compile + // (missing things in `libc` which is empty) so just omit everything + // with an empty module + #[unstable(issue = "none", feature = "std_internals")] + #[allow(missing_docs)] + pub mod wasi_ext {} + } else { + // On other platforms like Windows document the bare bones of WASI + #[path = "wasi/ext/mod.rs"] + pub mod wasi_ext; + } +} diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs index a8da003d550ac..66b6caf25127d 100644 --- a/library/std/src/sys/wasi/ext/fs.rs +++ b/library/std/src/sys/wasi/ext/fs.rs @@ -3,11 +3,14 @@ #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "none")] +use crate::ffi::OsStr; use crate::fs::{self, File, Metadata, OpenOptions}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::path::{Path, PathBuf}; -use crate::sys::fs::osstr2str; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; +// Used for `File::read` on intra-doc links +#[allow(unused_imports)] +use io::{Read, Write}; /// WASI-specific extensions to [`File`]. pub trait FileExt { @@ -54,11 +57,11 @@ pub trait FileExt { /// # Errors /// /// If this function encounters an error of the kind - /// [`ErrorKind::Interrupted`] then the error is ignored and the operation + /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If this function encounters an "end of file" before completely filling - /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`]. /// The contents of `buf` are unspecified in this case. /// /// If any other read error is encountered then this function immediately @@ -131,16 +134,16 @@ pub trait FileExt { /// The current file cursor is not affected by this function. /// /// This method will continuously call [`write_at`] until there is no more data - /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is /// returned. This method will not return until the entire buffer has been /// successfully written or such an error occurs. The first error that is - /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be /// returned. /// /// # Errors /// /// This function will return the first error of - /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns. + /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns. /// /// [`write_at`]: FileExt::write_at #[stable(feature = "rw_exact_all_at", since = "1.33.0")] @@ -426,7 +429,7 @@ impl MetadataExt for fs::Metadata { } } -/// WASI-specific extensions for [`FileType`]. +/// WASI-specific extensions for [`fs::FileType`]. /// /// Adds support for special WASI file types such as block/character devices, /// pipes, and sockets. @@ -517,8 +520,12 @@ pub fn symlink, U: AsRef>( /// Create a symbolic link. /// -/// This is a convenience API similar to [`std::os::unix::fs::symlink`] and -/// [`std::os::windows::fs::symlink_file`] and [`symlink_dir`](std::os::windows::fs::symlink_dir). +/// This is a convenience API similar to `std::os::unix::fs::symlink` and +/// `std::os::windows::fs::symlink_file` and `std::os::windows::fs::symlink_dir`. pub fn symlink_path, U: AsRef>(old_path: P, new_path: U) -> io::Result<()> { crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref()) } + +fn osstr2str(f: &OsStr) -> io::Result<&str> { + f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) +} diff --git a/library/std/src/sys/wasi/ext/io.rs b/library/std/src/sys/wasi/ext/io.rs index 81413f39dc1cd..d0edfa9f35f90 100644 --- a/library/std/src/sys/wasi/ext/io.rs +++ b/library/std/src/sys/wasi/ext/io.rs @@ -145,36 +145,36 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stdin.as_raw_fd() + libc::STDIN_FILENO } } impl AsRawFd for io::Stdout { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stdout.as_raw_fd() + libc::STDOUT_FILENO } } impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stderr.as_raw_fd() + libc::STDERR_FILENO } } impl<'a> AsRawFd for io::StdinLock<'a> { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stdin.as_raw_fd() + libc::STDIN_FILENO } } impl<'a> AsRawFd for io::StdoutLock<'a> { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stdout.as_raw_fd() + libc::STDOUT_FILENO } } impl<'a> AsRawFd for io::StderrLock<'a> { fn as_raw_fd(&self) -> RawFd { - sys::stdio::Stderr.as_raw_fd() + libc::STDERR_FILENO } } diff --git a/library/std/src/sys/wasi/ext/mod.rs b/library/std/src/sys/wasi/ext/mod.rs index 1cda30edcad0a..8a83b24700391 100644 --- a/library/std/src/sys/wasi/ext/mod.rs +++ b/library/std/src/sys/wasi/ext/mod.rs @@ -1,4 +1,32 @@ +//! Platform-specific extensions to `std` for WASI. +//! +//! Provides access to platform-level information on WASI, and exposes +//! WASI-specific functions that would otherwise be inappropriate as +//! part of the core `std` library. +//! +//! It exposes more ways to deal with platform-specific strings (`OsStr`, +//! `OsString`), allows to set permissions more granularly, extract low-level +//! file descriptors from files and sockets, and has platform-specific helpers +//! for spawning processes. +//! +//! # Examples +//! +//! ```no_run +//! use std::fs::File; +//! use std::os::wasi::prelude::*; +//! +//! fn main() -> std::io::Result<()> { +//! let f = File::create("foo.txt")?; +//! let fd = f.as_raw_fd(); +//! +//! // use fd with native WASI bindings +//! +//! Ok(()) +//! } +//! ``` + #![deny(unsafe_op_in_unsafe_fn)] +#![doc(cfg(target_os = "wasi"))] pub mod ffi; pub mod fs; From 9ce567efc20e3bfc8409ae92af74ebfc53b83aa8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Feb 2021 10:35:40 -0800 Subject: [PATCH 2/6] Cast `libc::STDIN_FILENO` to `RawFd`. WASI's `RawFd` is a `u32`, while `libc` uses `c_int`. --- library/std/src/sys/wasi/ext/io.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/wasi/ext/io.rs b/library/std/src/sys/wasi/ext/io.rs index d0edfa9f35f90..3c480aa8e19bf 100644 --- a/library/std/src/sys/wasi/ext/io.rs +++ b/library/std/src/sys/wasi/ext/io.rs @@ -145,36 +145,36 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO + libc::STDIN_FILENO as RawFd } } impl AsRawFd for io::Stdout { fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO + libc::STDOUT_FILENO as RawFd } } impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO + libc::STDERR_FILENO as RawFd } } impl<'a> AsRawFd for io::StdinLock<'a> { fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO + libc::STDIN_FILENO as RawFd } } impl<'a> AsRawFd for io::StdoutLock<'a> { fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO + libc::STDOUT_FILENO as RawFd } } impl<'a> AsRawFd for io::StderrLock<'a> { fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO + libc::STDERR_FILENO as RawFd } } From 0208fca342977838be7c718fb0335931fbb56cff Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Feb 2021 10:37:05 -0800 Subject: [PATCH 3/6] Use `super::` to refer to WASI-specific names. This ensures that these names resolve to the right place even when building the WASI support on other platforms for generating the documentation. --- library/std/src/sys/wasi/ext/mod.rs | 8 ++++---- library/std/src/sys/wasi/fs.rs | 2 +- library/std/src/sys/wasi/net.rs | 2 +- library/std/src/sys/wasi/stdio.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/wasi/ext/mod.rs b/library/std/src/sys/wasi/ext/mod.rs index 8a83b24700391..b08402f077652 100644 --- a/library/std/src/sys/wasi/ext/mod.rs +++ b/library/std/src/sys/wasi/ext/mod.rs @@ -39,14 +39,14 @@ pub mod io; pub mod prelude { #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext::ffi::{OsStrExt, OsStringExt}; + pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext::fs::FileTypeExt; + pub use super::fs::FileTypeExt; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt}; + pub use super::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 83debdfc86043..41203aa218dc5 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -9,7 +9,7 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Arc; -use crate::sys::fd::WasiFd; +use super::fd::WasiFd; use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 8fd4bb76d854f..7fa4f2923b8a5 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -4,7 +4,7 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use crate::sys::fd::WasiFd; +use super::fd::WasiFd; use crate::sys::{unsupported, Void}; use crate::sys_common::FromInner; use crate::time::Duration; diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index d82f6f411863d..c665ee2399660 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -2,7 +2,7 @@ use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; -use crate::sys::fd::WasiFd; +use super::fd::WasiFd; pub struct Stdin; pub struct Stdout; From e66e2635442b47808a5e23db83b461c11d2943fc Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Feb 2021 10:43:50 -0800 Subject: [PATCH 4/6] Make the main `wasi` module `cfg(not(doc))`. --- library/std/src/os/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index fad5886def700..ca8c4c9c420a3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -41,6 +41,10 @@ pub use crate::sys::ext as windows; #[cfg(any(target_os = "linux", target_os = "l4re"))] pub mod linux; +#[cfg(not(doc))] +#[cfg(target_os = "wasi")] +pub mod wasi; + #[cfg(target_os = "android")] pub mod android; #[cfg(target_os = "dragonfly")] @@ -71,7 +75,5 @@ pub mod redox; pub mod solaris; #[cfg(target_os = "vxworks")] pub mod vxworks; -#[cfg(target_os = "wasi")] -pub mod wasi; pub mod raw; From 94e75acf1fd5933ba5821e9b1935796f0bbf23e0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Feb 2021 10:47:26 -0800 Subject: [PATCH 5/6] Mention "wasi" in the comment about "main modules". --- library/std/src/os/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index ca8c4c9c420a3..500e8267cf821 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -3,7 +3,7 @@ #![stable(feature = "os", since = "1.0.0")] #![allow(missing_docs, nonstandard_style, missing_debug_implementations)] -// When documenting libstd we want to show unix/windows/linux modules as these are the "main +// When documenting libstd we want to show unix/windows/linux/wasi modules as these are the "main // modules" that are used across platforms, so all modules are enabled when `cfg(doc)` is set. // This should help show platform-specific functionality in a hopefully cross-platform way in the // documentation. From 7d5242a03a9e30fe880ff1af83a3ad7df5e62159 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Feb 2021 10:58:21 -0800 Subject: [PATCH 6/6] x.py fmt --- library/std/src/sys/wasi/fs.rs | 2 +- library/std/src/sys/wasi/net.rs | 2 +- library/std/src/sys/wasi/stdio.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 41203aa218dc5..bcf7da46b4b07 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -1,5 +1,6 @@ #![deny(unsafe_op_in_unsafe_fn)] +use super::fd::WasiFd; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; @@ -9,7 +10,6 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Arc; -use super::fd::WasiFd; use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 7fa4f2923b8a5..3f294e7df418e 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -1,10 +1,10 @@ #![deny(unsafe_op_in_unsafe_fn)] +use super::fd::WasiFd; use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use super::fd::WasiFd; use crate::sys::{unsupported, Void}; use crate::sys_common::FromInner; use crate::time::Duration; diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index c665ee2399660..209d5b996e5b4 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -1,8 +1,8 @@ #![deny(unsafe_op_in_unsafe_fn)] +use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; -use super::fd::WasiFd; pub struct Stdin; pub struct Stdout;