From 35de5c9b35be9feef992c3d03ed95a7176a15726 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 13 Aug 2021 08:58:05 -0700 Subject: [PATCH] Change WASI's `RawFd` from `u32` to `c_int` (`i32`). WASI previously used `u32` as its `RawFd` type, since its "file descriptors" are unsigned table indices, and there's no fundamental reason why WASI can't have more than 2^31 handles. However, this creates myriad little incompability problems with code that also supports Unix platforms, where `RawFd` is `c_int`. While WASI isn't a Unix, it often shares code with Unix, and this difference made such shared code inconvenient. #87329 is the most recent example of such code. So, switch WASI to use `c_int`, which is `i32`. This will mean that code intending to support WASI should ideally avoid assuming that negative file descriptors are invalid, even though POSIX itself says that file descriptors are never negative. This is a breaking change, but `RawFd` is considerd an experimental feature in [the documentation]. [the documentation]: https://doc.rust-lang.org/stable/std/os/wasi/io/type.RawFd.html --- library/std/src/os/wasi/io.rs | 21 +++++--- library/std/src/sys/wasi/fd.rs | 89 +++++++++++++++++++------------ library/std/src/sys/wasi/fs.rs | 7 +-- library/std/src/sys/wasi/net.rs | 13 ++--- library/std/src/sys/wasi/stdio.rs | 7 +-- 5 files changed, 83 insertions(+), 54 deletions(-) diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs index cf4501b98cb..b6bc74da8e7 100644 --- a/library/std/src/os/wasi/io.rs +++ b/library/std/src/os/wasi/io.rs @@ -6,11 +6,18 @@ use crate::fs; use crate::io; use crate::net; +use crate::os::raw; use crate::sys; use crate::sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. -pub type RawFd = u32; +/// +/// This has type `c_int` to ease compatibility with code that also compiles on +/// Unix configurations, however unlike Unix and POSIX, in WASI negative file +/// descriptors are valid. Only `-1` is reserved for indicating errors. Code +/// intending to be portable across Unix platforms and WASI should avoid +/// assuming that negative file descriptors are invalid. +pub type RawFd = raw::c_int; /// A trait to extract the raw WASI file descriptor from an underlying /// object. @@ -161,41 +168,41 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl AsRawFd for io::Stdout { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl AsRawFd for io::Stderr { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } impl<'a> AsRawFd for io::StdinLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl<'a> AsRawFd for io::StdoutLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl<'a> AsRawFd for io::StderrLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index ba66eba2ad3..1f6ea8d6e8d 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -5,10 +5,11 @@ use super::err2io; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; +use crate::os::raw::c_int; #[derive(Debug)] pub struct WasiFd { - fd: wasi::Fd, + fd: c_int, } fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { @@ -26,38 +27,38 @@ fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { } impl WasiFd { - pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { + pub unsafe fn from_raw(fd: c_int) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> wasi::Fd { + pub fn into_raw(self) -> c_int { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> wasi::Fd { + pub fn as_raw(&self) -> c_int { self.fd } pub fn datasync(&self) -> io::Result<()> { - unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } + unsafe { wasi::fd_datasync(self.fd as wasi::Fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pread(self.fd as wasi::Fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pwrite(self.fd as wasi::Fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_read(self.fd as wasi::Fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_write(self.fd as wasi::Fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result { @@ -66,37 +67,37 @@ impl WasiFd { SeekFrom::End(pos) => (wasi::WHENCE_END, pos), SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } + unsafe { wasi::fd_seek(self.fd as wasi::Fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result { - unsafe { wasi::fd_tell(self.fd).map_err(err2io) } + unsafe { wasi::fd_tell(self.fd as wasi::Fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_flags(self.fd as wasi::Fd, flags).map_err(err2io) } } pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_rights(self.fd as wasi::Fd, base, inheriting).map_err(err2io) } } pub fn sync(&self) -> io::Result<()> { - unsafe { wasi::fd_sync(self.fd).map_err(err2io) } + unsafe { wasi::fd_sync(self.fd as wasi::Fd).map_err(err2io) } } pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { - unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } + unsafe { wasi::fd_advise(self.fd as wasi::Fd, offset, len, advice).map_err(err2io) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } + unsafe { wasi::fd_allocate(self.fd as wasi::Fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_create_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn link( @@ -107,7 +108,14 @@ impl WasiFd { new_path: &str, ) -> io::Result<()> { unsafe { - wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io) + wasi::path_link( + self.fd as wasi::Fd, + old_flags, + old_path, + new_fd.fd as wasi::Fd, + new_path, + ) + .map_err(err2io) } } @@ -122,7 +130,7 @@ impl WasiFd { ) -> io::Result { unsafe { wasi::path_open( - self.fd, + self.fd as wasi::Fd, dirflags, path, oflags, @@ -130,25 +138,34 @@ impl WasiFd { fs_rights_inheriting, fs_flags, ) - .map(|fd| WasiFd::from_raw(fd)) + .map(|fd| WasiFd::from_raw(fd as c_int)) .map_err(err2io) } } pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result { - unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) } + unsafe { + wasi::fd_readdir(self.fd as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie) + .map_err(err2io) + } } pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result { - unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) } + unsafe { + wasi::path_readlink(self.fd as wasi::Fd, path, buf.as_mut_ptr(), buf.len()) + .map_err(err2io) + } } pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) } + unsafe { + wasi::path_rename(self.fd as wasi::Fd, old_path, new_fd.fd as wasi::Fd, new_path) + .map_err(err2io) + } } pub fn filestat_get(&self) -> io::Result { - unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } + unsafe { wasi::fd_filestat_get(self.fd as wasi::Fd).map_err(err2io) } } pub fn filestat_set_times( @@ -157,11 +174,13 @@ impl WasiFd { mtim: wasi::Timestamp, fstflags: wasi::Fstflags, ) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) } + unsafe { + wasi::fd_filestat_set_times(self.fd as wasi::Fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } + unsafe { wasi::fd_filestat_set_size(self.fd as wasi::Fd, size).map_err(err2io) } } pub fn path_filestat_get( @@ -169,7 +188,7 @@ impl WasiFd { flags: wasi::Lookupflags, path: &str, ) -> io::Result { - unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } + unsafe { wasi::path_filestat_get(self.fd as wasi::Fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( @@ -181,21 +200,21 @@ impl WasiFd { fstflags: wasi::Fstflags, ) -> io::Result<()> { unsafe { - wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags) + wasi::path_filestat_set_times(self.fd as wasi::Fd, flags, path, atim, mtim, fstflags) .map_err(err2io) } } pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } + unsafe { wasi::path_symlink(old_path, self.fd as wasi::Fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } + unsafe { wasi::path_unlink_file(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_remove_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn sock_recv( @@ -203,11 +222,11 @@ impl WasiFd { ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::Riflags, ) -> io::Result<(usize, wasi::Roflags)> { - unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } + unsafe { wasi::sock_recv(self.fd as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io) } } pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result { - unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } + unsafe { wasi::sock_send(self.fd as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { @@ -216,7 +235,7 @@ impl WasiFd { Shutdown::Write => wasi::SDFLAGS_WR, Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD, }; - unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } + unsafe { wasi::sock_shutdown(self.fd as wasi::Fd, how).map_err(err2io) } } } @@ -224,6 +243,6 @@ impl Drop for WasiFd { fn drop(&mut self) { // FIXME: can we handle the return code here even though we can't on // unix? - let _ = unsafe { wasi::fd_close(self.fd) }; + let _ = unsafe { wasi::fd_close(self.fd as wasi::Fd) }; } } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 8ffa1c88d88..55c9c652a8b 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -6,6 +6,7 @@ use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; +use crate::os::raw::c_int; use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -454,8 +455,8 @@ impl File { } } -impl FromInner for File { - fn from_inner(fd: u32) -> File { +impl FromInner for File { + fn from_inner(fd: c_int) -> File { unsafe { File { fd: WasiFd::from_raw(fd) } } } } @@ -653,7 +654,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); return Ok(( - ManuallyDrop::new(WasiFd::from_raw(fd as u32)), + ManuallyDrop::new(WasiFd::from_raw(fd as c_int)), PathBuf::from(OsString::from_vec(relative)), )); } diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 06860673d90..50b7352933e 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -5,6 +5,7 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::os::raw::c_int; use crate::sys::unsupported; use crate::sys_common::FromInner; use crate::time::Duration; @@ -115,8 +116,8 @@ impl TcpStream { } } -impl FromInner for TcpStream { - fn from_inner(fd: u32) -> TcpStream { +impl FromInner for TcpStream { + fn from_inner(fd: c_int) -> TcpStream { unsafe { TcpStream { fd: WasiFd::from_raw(fd) } } } } @@ -181,8 +182,8 @@ impl TcpListener { } } -impl FromInner for TcpListener { - fn from_inner(fd: u32) -> TcpListener { +impl FromInner for TcpListener { + fn from_inner(fd: c_int) -> TcpListener { unsafe { TcpListener { fd: WasiFd::from_raw(fd) } } } } @@ -331,8 +332,8 @@ impl UdpSocket { } } -impl FromInner for UdpSocket { - fn from_inner(fd: u32) -> UdpSocket { +impl FromInner for UdpSocket { + fn from_inner(fd: c_int) -> UdpSocket { unsafe { UdpSocket { fd: WasiFd::from_raw(fd) } } } } diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index 209d5b996e5..8782f333a1f 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -3,6 +3,7 @@ use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; +use crate::os::raw; pub struct Stdin; pub struct Stdout; @@ -14,7 +15,7 @@ impl Stdin { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 0 } } @@ -40,7 +41,7 @@ impl Stdout { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 1 } } @@ -69,7 +70,7 @@ impl Stderr { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 2 } }