From 06698f4e8fdd913637e498c8e90154003cebbccd Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 6 Mar 2023 21:19:57 -0800 Subject: [PATCH] wip on wasi support --- .vscode/settings.json | 6 ++ Cargo.toml | 2 +- src/errno.rs | 223 +++++++++++++++++++++++++++++++++++++++--- src/fcntl.rs | 26 +++-- src/lib.rs | 14 ++- src/sys/mod.rs | 1 + src/sys/stat.rs | 23 +++-- src/sys/uio.rs | 4 +- src/unistd.rs | 35 +++++-- 9 files changed, 288 insertions(+), 46 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..fb390742cc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.cargo.target": "wasm32-wasi", + "rust-analyzer.cargo.noDefaultFeatures": true, + "rust-analyzer.check.allTargets": false, + "rust-analyzer.cargo.features": ["fs", "uio", "zerocopy"] +} diff --git a/Cargo.toml b/Cargo.toml index 960d4f61b3..d88b4330ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ targets = [ ] [dependencies] -libc = { git = "https://github.com/rust-lang/libc", rev = "44cc30c6b68427d3628926868758d35fe561bbe6", features = [ "extra_traits" ] } +libc = { path = "../libc", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" pin-utils = { version = "0.1.0", optional = true } diff --git a/src/errno.rs b/src/errno.rs index d8ad28de85..50dd74c64b 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -22,7 +22,8 @@ cfg_if! { } else if #[cfg(any(target_os = "linux", target_os = "redox", target_os = "dragonfly", - target_os = "fuchsia"))] { + target_os = "fuchsia", + target_os = "wasi"))] { unsafe fn errno_location() -> *mut c_int { libc::__errno_location() } @@ -109,6 +110,7 @@ impl ErrnoSentinel for *mut c_void { } } +#[cfg(not(target_os = "wasi"))] impl ErrnoSentinel for libc::sighandler_t { fn sentinel() -> Self { libc::SIG_ERR @@ -160,6 +162,7 @@ fn desc(errno: Errno) -> &'static str { EACCES => "Permission denied", EFAULT => "Bad address", #[cfg(not(target_os = "haiku"))] + #[cfg(not(target_os = "wasi"))] ENOTBLK => "Block device required", EBUSY => "Device or resource busy", EEXIST => "File exists", @@ -197,8 +200,10 @@ fn desc(errno: Errno) -> &'static str { ENOPROTOOPT => "Protocol not available", EPROTONOSUPPORT => "Protocol not supported", #[cfg(not(target_os = "haiku"))] + #[cfg(not(target_os = "wasi"))] ESOCKTNOSUPPORT => "Socket type not supported", #[cfg(not(target_os = "haiku"))] + #[cfg(not(target_os = "wasi"))] EPFNOSUPPORT => "Protocol family not supported", #[cfg(not(target_os = "haiku"))] EAFNOSUPPORT => "Address family not supported by protocol", @@ -212,11 +217,14 @@ fn desc(errno: Errno) -> &'static str { ENOBUFS => "No buffer space available", EISCONN => "Transport endpoint is already connected", ENOTCONN => "Transport endpoint is not connected", + #[cfg(not(target_os = "wasi"))] ESHUTDOWN => "Cannot send after transport endpoint shutdown", #[cfg(not(target_os = "haiku"))] + #[cfg(not(target_os = "wasi"))] ETOOMANYREFS => "Too many references: cannot splice", ETIMEDOUT => "Connection timed out", ECONNREFUSED => "Connection refused", + #[cfg(not(target_os = "wasi"))] EHOSTDOWN => "Host is down", EHOSTUNREACH => "No route to host", @@ -459,7 +467,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "android", target_os = "illumos", target_os = "solaris", - target_os = "fuchsia" + target_os = "fuchsia", + target_os = "wasi" ))] EPROTO => "Protocol error", @@ -482,7 +491,8 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any( target_os = "linux", target_os = "android", - target_os = "fuchsia" + target_os = "fuchsia", + target_os = "wasi" ))] EBADMSG => "Not a data message", @@ -660,7 +670,8 @@ fn desc(errno: Errno) -> &'static str { #[cfg(any( target_os = "linux", target_os = "android", - target_os = "fuchsia" + target_os = "fuchsia", + target_os = "wasi" ))] EDQUOT => "Quota exceeded", @@ -687,7 +698,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "illumos", target_os = "solaris", target_os = "fuchsia", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] ECANCELED => "Operation canceled", @@ -768,7 +780,7 @@ fn desc(errno: Errno) -> &'static str { ))] ENOLINK => "Link has been severed", - #[cfg(target_os = "freebsd")] + #[cfg(any(target_os = "freebsd", target_os = "wasi"))] ENOTCAPABLE => "Capabilities insufficient", #[cfg(target_os = "freebsd")] @@ -793,7 +805,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "netbsd", target_os = "redox", target_os = "illumos", - target_os = "solaris" + target_os = "solaris", + target_os = "wasi" ))] EOVERFLOW => "Value too large to be stored in data type", @@ -804,7 +817,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "ios", target_os = "netbsd", target_os = "redox", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] EILSEQ => "Illegal byte sequence", @@ -848,7 +862,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "openbsd" + target_os = "openbsd", + target_os = "wasi" ))] ENOTRECOVERABLE => "State not recoverable", @@ -857,7 +872,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "openbsd" + target_os = "openbsd", + target_os = "wasi" ))] EOWNERDEAD => "Previous owner died", @@ -870,7 +886,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "netbsd", target_os = "illumos", target_os = "solaris", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] ENOTSUP => "Operation not supported", @@ -919,7 +936,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "redox", target_os = "illumos", target_os = "solaris", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] ESTALE => "Stale NFS file handle", @@ -1037,7 +1055,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "macos", target_os = "ios", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] EMULTIHOP => "Reserved", @@ -1053,7 +1072,8 @@ fn desc(errno: Errno) -> &'static str { target_os = "macos", target_os = "ios", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi" ))] ENOLINK => "Reserved", @@ -1405,6 +1425,181 @@ mod consts { } } +#[cfg(target_os = "wasi")] +mod consts { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[repr(i32)] + #[non_exhaustive] + pub enum Errno { + UnknownErrno = 0, + E2BIG = libc::E2BIG, + EACCES = libc::EACCES, + EADDRINUSE = libc::EADDRINUSE, + EADDRNOTAVAIL = libc::EADDRNOTAVAIL, + EAFNOSUPPORT = libc::EAFNOSUPPORT, + EAGAIN = libc::EAGAIN, + EALREADY = libc::EALREADY, + EBADF = libc::EBADF, + EBADMSG = libc::EBADMSG, + EBUSY = libc::EBUSY, + ECANCELED = libc::ECANCELED, + ECHILD = libc::ECHILD, + ECONNABORTED = libc::ECONNABORTED, + ECONNREFUSED = libc::ECONNREFUSED, + ECONNRESET = libc::ECONNRESET, + EDEADLK = libc::EDEADLK, + EDESTADDRREQ = libc::EDESTADDRREQ, + EDOM = libc::EDOM, + EDQUOT = libc::EDQUOT, + EEXIST = libc::EEXIST, + EFAULT = libc::EFAULT, + EFBIG = libc::EFBIG, + EHOSTUNREACH = libc::EHOSTUNREACH, + EIDRM = libc::EIDRM, + EILSEQ = libc::EILSEQ, + EINPROGRESS = libc::EINPROGRESS, + EINTR = libc::EINTR, + EINVAL = libc::EINVAL, + EIO = libc::EIO, + EISCONN = libc::EISCONN, + EISDIR = libc::EISDIR, + ELOOP = libc::ELOOP, + EMFILE = libc::EMFILE, + EMLINK = libc::EMLINK, + EMSGSIZE = libc::EMSGSIZE, + EMULTIHOP = libc::EMULTIHOP, + ENAMETOOLONG = libc::ENAMETOOLONG, + ENETDOWN = libc::ENETDOWN, + ENETRESET = libc::ENETRESET, + ENETUNREACH = libc::ENETUNREACH, + ENFILE = libc::ENFILE, + ENOBUFS = libc::ENOBUFS, + ENODEV = libc::ENODEV, + ENOENT = libc::ENOENT, + ENOEXEC = libc::ENOEXEC, + ENOLCK = libc::ENOLCK, + ENOLINK = libc::ENOLINK, + ENOMEM = libc::ENOMEM, + ENOMSG = libc::ENOMSG, + ENOPROTOOPT = libc::ENOPROTOOPT, + ENOSPC = libc::ENOSPC, + ENOSYS = libc::ENOSYS, + ENOTCONN = libc::ENOTCONN, + ENOTDIR = libc::ENOTDIR, + ENOTEMPTY = libc::ENOTEMPTY, + ENOTRECOVERABLE = libc::ENOTRECOVERABLE, + ENOTSOCK = libc::ENOTSOCK, + ENOTSUP = libc::ENOTSUP, + ENOTTY = libc::ENOTTY, + ENXIO = libc::ENXIO, + EOVERFLOW = libc::EOVERFLOW, + EOWNERDEAD = libc::EOWNERDEAD, + EPERM = libc::EPERM, + EPIPE = libc::EPIPE, + EPROTO = libc::EPROTO, + EPROTONOSUPPORT = libc::EPROTONOSUPPORT, + EPROTOTYPE = libc::EPROTOTYPE, + ERANGE = libc::ERANGE, + EROFS = libc::EROFS, + ESPIPE = libc::ESPIPE, + ESRCH = libc::ESRCH, + ESTALE = libc::ESTALE, + ETIMEDOUT = libc::ETIMEDOUT, + ETXTBSY = libc::ETXTBSY, + EXDEV = libc::EXDEV, + ENOTCAPABLE = libc::ENOTCAPABLE, + } + + impl Errno { + pub const EWOULDBLOCK: Errno = Errno::EAGAIN; + pub const ENOTSUP: Errno = Errno::ENOTSUP; + } + + pub const fn from_i32(e: i32) -> Errno { + use self::Errno::*; + + match e { + libc::E2BIG => E2BIG, + libc::EACCES => EACCES, + libc::EADDRINUSE => EADDRINUSE, + libc::EADDRNOTAVAIL => EADDRNOTAVAIL, + libc::EAFNOSUPPORT => EAFNOSUPPORT, + libc::EAGAIN => EAGAIN, + libc::EALREADY => EALREADY, + libc::EBADF => EBADF, + libc::EBADMSG => EBADMSG, + libc::EBUSY => EBUSY, + libc::ECANCELED => ECANCELED, + libc::ECHILD => ECHILD, + libc::ECONNABORTED => ECONNABORTED, + libc::ECONNREFUSED => ECONNREFUSED, + libc::ECONNRESET => ECONNRESET, + libc::EDEADLK => EDEADLK, + libc::EDESTADDRREQ => EDESTADDRREQ, + libc::EDOM => EDOM, + libc::EDQUOT => EDQUOT, + libc::EEXIST => EEXIST, + libc::EFAULT => EFAULT, + libc::EFBIG => EFBIG, + libc::EHOSTUNREACH => EHOSTUNREACH, + libc::EIDRM => EIDRM, + libc::EILSEQ => EILSEQ, + libc::EINPROGRESS => EINPROGRESS, + libc::EINTR => EINTR, + libc::EINVAL => EINVAL, + libc::EIO => EIO, + libc::EISCONN => EISCONN, + libc::EISDIR => EISDIR, + libc::ELOOP => ELOOP, + libc::EMFILE => EMFILE, + libc::EMLINK => EMLINK, + libc::EMSGSIZE => EMSGSIZE, + libc::EMULTIHOP => EMULTIHOP, + libc::ENAMETOOLONG => ENAMETOOLONG, + libc::ENETDOWN => ENETDOWN, + libc::ENETRESET => ENETRESET, + libc::ENETUNREACH => ENETUNREACH, + libc::ENFILE => ENFILE, + libc::ENOBUFS => ENOBUFS, + libc::ENODEV => ENODEV, + libc::ENOENT => ENOENT, + libc::ENOEXEC => ENOEXEC, + libc::ENOLCK => ENOLCK, + libc::ENOLINK => ENOLINK, + libc::ENOMEM => ENOMEM, + libc::ENOMSG => ENOMSG, + libc::ENOPROTOOPT => ENOPROTOOPT, + libc::ENOSPC => ENOSPC, + libc::ENOSYS => ENOSYS, + libc::ENOTCONN => ENOTCONN, + libc::ENOTDIR => ENOTDIR, + libc::ENOTEMPTY => ENOTEMPTY, + libc::ENOTRECOVERABLE => ENOTRECOVERABLE, + libc::ENOTSOCK => ENOTSOCK, + libc::ENOTSUP => ENOTSUP, + libc::ENOTTY => ENOTTY, + libc::ENXIO => ENXIO, + libc::EOVERFLOW => EOVERFLOW, + libc::EOWNERDEAD => EOWNERDEAD, + libc::EPERM => EPERM, + libc::EPIPE => EPIPE, + libc::EPROTO => EPROTO, + libc::EPROTONOSUPPORT => EPROTONOSUPPORT, + libc::EPROTOTYPE => EPROTOTYPE, + libc::ERANGE => ERANGE, + libc::EROFS => EROFS, + libc::ESPIPE => ESPIPE, + libc::ESRCH => ESRCH, + libc::ESTALE => ESTALE, + libc::ETIMEDOUT => ETIMEDOUT, + libc::ETXTBSY => ETXTBSY, + libc::EXDEV => EXDEV, + libc::ENOTCAPABLE => ENOTCAPABLE, + _ => UnknownErrno, + } + } +} + #[cfg(any(target_os = "macos", target_os = "ios"))] mod consts { #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/src/fcntl.rs b/src/fcntl.rs index a9ef9ad1bc..4c69e61ae1 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1,11 +1,12 @@ -use crate::errno::Errno; +use crate::{errno::Errno, RawFd}; use libc::{self, c_char, c_int, c_uint, size_t, ssize_t}; use std::ffi::OsString; #[cfg(not(target_os = "redox"))] use std::os::raw; +#[cfg(unix)] use std::os::unix::ffi::OsStringExt; -use std::os::unix::io::RawFd; - +#[cfg(target_os = "wasi")] +use std::os::wasi::ffi::OsStringExt; #[cfg(feature = "fs")] use crate::{sys::stat::Mode, NixPath, Result}; #[cfg(any(target_os = "android", target_os = "linux"))] @@ -54,7 +55,7 @@ libc_bitflags!( /// Open the file in append-only mode. O_APPEND; /// Generate a signal when input or output becomes possible. - #[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))] + #[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku", target_os = "wasi")))] #[cfg_attr(docsrs, doc(cfg(all())))] O_ASYNC; /// Closes the file descriptor once an `execve` call is made. @@ -124,7 +125,7 @@ libc_bitflags!( #[cfg_attr(docsrs, doc(cfg(all())))] O_NOCTTY; /// Same as `O_NONBLOCK`. - #[cfg(not(any(target_os = "redox", target_os = "haiku")))] + #[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "wasi")))] #[cfg_attr(docsrs, doc(cfg(all())))] O_NDELAY; /// `open()` will fail if the given path is a symbolic link. @@ -191,6 +192,12 @@ libc_bitflags!( feature! { #![feature = "fs"] +#[cfg(unix)] +pub const PATH_MAX: usize = libc::PATH_MAX; + +#[cfg(target_os = "wasi")] +pub const PATH_MAX: usize = 4096; // max is whatever the host system is... so guess posix? + // The conversion is not identical on all operating systems. #[allow(clippy::useless_conversion)] pub fn open( @@ -441,7 +448,7 @@ libc_bitflags!( feature! { #![feature = "fs"] -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[derive(Debug, Eq, Hash, PartialEq)] #[non_exhaustive] pub enum FcntlArg<'a> { @@ -492,9 +499,11 @@ pub enum FcntlArg { F_GETFL, F_SETFL(OFlag), // O_NONBLOCK } +#[cfg(not(target_os = "wasi"))] pub use self::FcntlArg::*; // TODO: Figure out how to handle value fcntl returns +#[cfg(not(target_os = "wasi"))] pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result { let res = unsafe { match arg { @@ -556,7 +565,7 @@ pub enum FlockArg { UnlockNonblock, } -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> { use self::FlockArg::*; @@ -900,8 +909,7 @@ pub fn fspacectl_all( ))] mod posix_fadvise { use crate::errno::Errno; - use crate::Result; - use std::os::unix::io::RawFd; + use crate::{Result, RawFd}; #[cfg(feature = "fs")] libc_enum! { diff --git a/src/lib.rs b/src/lib.rs index 6349d37e0f..1ee028b684 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ //! * `user` - Stuff relating to users and groups //! * `zerocopy` - APIs like `sendfile` and `copy_file_range` #![crate_name = "nix"] -#![cfg(unix)] +#![cfg(any(unix, target_os = "wasi"))] #![cfg_attr(docsrs, doc(cfg(all())))] #![allow(non_camel_case_types)] #![cfg_attr(test, deny(warnings))] @@ -161,7 +161,10 @@ pub mod unistd; use std::ffi::{CStr, CString, OsStr}; use std::mem::MaybeUninit; +#[cfg(unix)] use std::os::unix::ffi::OsStrExt; +#[cfg(target_os = "wasi")] +use std::os::wasi::ffi::OsStrExt; use std::path::{Path, PathBuf}; use std::{ptr, result, slice}; @@ -336,3 +339,12 @@ impl NixPath for PathBuf { self.as_os_str().with_nix_path(f) } } + + +/// Raw file descriptors. +#[cfg(unix)] +pub type RawFd = std::os::unix::io::RawFd; + +/// Raw file descriptors. +#[cfg(target_os = "wasi")] +pub type RawFd = std::os::wasi::io::RawFd; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 383f08df04..2f301d0bf7 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -165,6 +165,7 @@ feature! { pub mod statfs; } +#[cfg(unix)] feature! { #![feature = "fs"] pub mod statvfs; diff --git a/src/sys/stat.rs b/src/sys/stat.rs index 78203bfbe3..3f4bfda8e2 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -12,9 +12,8 @@ pub use libc::{dev_t, mode_t}; #[cfg(not(target_os = "redox"))] use crate::fcntl::{at_rawfd, AtFlags}; use crate::sys::time::{TimeSpec, TimeVal}; -use crate::{errno::Errno, NixPath, Result}; +use crate::{errno::Errno, NixPath, Result, RawFd}; use std::mem; -use std::os::unix::io::RawFd; libc_bitflags!( /// "File type" flags for `mknod` and related functions. @@ -33,6 +32,7 @@ libc_bitflags!( libc_bitflags! { /// "File mode / permissions" flags. pub struct Mode: mode_t { + #[cfg(not(target_os = "redox"))] /// Read, write and execute for owner. S_IRWXU; /// Read for owner. @@ -170,6 +170,7 @@ libc_bitflags! { } /// Create a special or ordinary file, by pathname. +#[cfg(not(target_os = "wasi"))] pub fn mknod( path: &P, kind: SFlag, @@ -188,7 +189,8 @@ pub fn mknod( target_os = "ios", target_os = "macos", target_os = "redox", - target_os = "haiku" + target_os = "haiku", + target_os = "wasi", )))] #[cfg_attr(docsrs, doc(cfg(all())))] pub fn mknodat( @@ -231,6 +233,7 @@ pub const fn makedev(major: u64, minor: u64) -> dev_t { | (minor & 0x0000_00ff) } +#[cfg(unix)] pub fn umask(mode: Mode) -> Mode { let prev = unsafe { libc::umask(mode.bits() as mode_t) }; Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode") @@ -294,6 +297,7 @@ pub fn fstatat( /// # References /// /// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html). +#[cfg(unix)] pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> { let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) }; @@ -323,7 +327,7 @@ pub enum FchmodatFlags { /// # References /// /// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html). -#[cfg(not(target_os = "redox"))] +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[cfg_attr(docsrs, doc(cfg(all())))] pub fn fchmodat( dirfd: Option, @@ -357,17 +361,18 @@ pub fn fchmodat( /// # References /// /// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html). +#[cfg(unix)] pub fn utimes( path: &P, atime: &TimeVal, mtime: &TimeVal, ) -> Result<()> { - let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = path.with_nix_path(|cstr| unsafe { - libc::utimes(cstr.as_ptr(), ×[0]) - })?; + let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()]; + let res = path.with_nix_path(|cstr| unsafe { + libc::utimes(cstr.as_ptr(), ×[0]) + })?; - Errno::result(res).map(drop) + Errno::result(res).map(drop) } /// Change the access and modification times of a file without following symlinks. diff --git a/src/sys/uio.rs b/src/sys/uio.rs index ce0fb54ddb..c6137fd470 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -1,10 +1,10 @@ //! Vectored I/O use crate::errno::Errno; -use crate::Result; +use crate::{Result, RawFd}; use libc::{self, c_int, c_void, off_t, size_t}; use std::io::{IoSlice, IoSliceMut}; -use std::os::unix::io::{AsFd, AsRawFd}; +use std::os::fd::{AsFd, AsRawFd}; /// Low-level vectored write to a raw file descriptor /// diff --git a/src/unistd.rs b/src/unistd.rs index a10c17b552..dcc505b005 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1,11 +1,14 @@ //! Safe wrappers around functions found in libc "unistd.h" header use crate::errno::{self, Errno}; +#[cfg(not(target_os = "wasi"))] +#[cfg(feature = "fs")] +use crate::fcntl::{fcntl, FcntlArg::F_SETFD}; #[cfg(not(target_os = "redox"))] #[cfg(feature = "fs")] use crate::fcntl::{at_rawfd, AtFlags}; #[cfg(feature = "fs")] -use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag}; +use crate::fcntl::{FdFlag, OFlag, PATH_MAX}; #[cfg(all( feature = "fs", any( @@ -20,21 +23,26 @@ use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag}; use crate::sys::stat::FileFlag; #[cfg(feature = "fs")] use crate::sys::stat::Mode; -use crate::{Error, NixPath, Result}; +use crate::{Error, NixPath, Result, RawFd}; #[cfg(not(target_os = "redox"))] use cfg_if::cfg_if; use libc::{ self, c_char, c_int, c_long, c_uint, c_void, gid_t, mode_t, off_t, pid_t, - size_t, uid_t, PATH_MAX, + size_t, uid_t }; use std::convert::Infallible; use std::ffi::{CStr, OsString}; #[cfg(not(target_os = "redox"))] use std::ffi::{CString, OsStr}; -#[cfg(not(target_os = "redox"))] +#[cfg(all(unix, not(target_os = "redox")))] use std::os::unix::ffi::OsStrExt; +#[cfg(unix)] use std::os::unix::ffi::OsStringExt; -use std::os::unix::io::RawFd; +#[cfg(target_os = "wasi")] +use std::os::wasi::ffi::{OsStrExt, OsStringExt}; +#[cfg(target_os = "wasi")] +use std::os::wasi::io::{AsFd, AsRawFd}; +#[cfg(unix)] use std::os::unix::io::{AsFd, AsRawFd}; use std::path::PathBuf; use std::{fmt, mem, ptr}; @@ -424,6 +432,7 @@ feature! { /// /// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`). #[inline] +#[cfg(not(target_os = "wasi"))] pub fn dup(oldfd: RawFd) -> Result { let res = unsafe { libc::dup(oldfd) }; @@ -437,6 +446,7 @@ pub fn dup(oldfd: RawFd) -> Result { /// specified fd instead of allocating a new one. See the man pages for more /// detail on the exact behavior of this function. #[inline] +#[cfg(not(target_os = "wasi"))] pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { let res = unsafe { libc::dup2(oldfd, newfd) }; @@ -448,10 +458,12 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { /// /// This function behaves similar to `dup2()` but allows for flags to be /// specified. +#[cfg(not(target_os = "wasi"))] pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { dup3_polyfill(oldfd, newfd, flags) } +#[cfg(not(target_os = "wasi"))] #[inline] fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { if oldfd == newfd { @@ -490,7 +502,7 @@ pub fn chdir(path: &P) -> Result<()> { /// This function may fail in a number of different scenarios. See the man /// pages for additional details on possible failure cases. #[inline] -#[cfg(not(target_os = "fuchsia"))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] pub fn fchdir(dirfd: RawFd) -> Result<()> { let res = unsafe { libc::fchdir(dirfd) }; @@ -562,7 +574,7 @@ pub fn mkdir(path: &P, mode: Mode) -> Result<()> { /// } /// ``` #[inline] -#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] // RedoxFS does not support fifo yet pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { let res = path.with_nix_path(|cstr| unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) @@ -587,7 +599,8 @@ pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { target_os = "ios", target_os = "haiku", target_os = "android", - target_os = "redox" + target_os = "redox", + target_os = "wasi" )))] pub fn mkfifoat( dirfd: Option, @@ -689,7 +702,7 @@ pub fn getcwd() -> Result { } // Trigger the internal buffer resizing logic. - reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?; + reserve_double_buffer_size(&mut buf, PATH_MAX)?; } } } @@ -1188,6 +1201,7 @@ pub fn lseek64( /// Create an interprocess channel. /// /// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html) +#[cfg(not(target_os = "wasi"))] pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> { let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); @@ -1369,7 +1383,7 @@ pub fn unlinkat( } #[inline] -#[cfg(not(target_os = "fuchsia"))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] pub fn chroot(path: &P) -> Result<()> { let res = path.with_nix_path(|cstr| unsafe { libc::chroot(cstr.as_ptr()) })?; @@ -1964,6 +1978,7 @@ feature! { /// // do something with fd /// ``` #[inline] +#[cfg(not(target_os = "wasi"))] pub fn mkstemp(template: &P) -> Result<(RawFd, PathBuf)> { let mut path = template.with_nix_path(|path| path.to_bytes_with_nul().to_owned())?;