diff options
| author | Baoshan <pangbw@gmail.com> | 2019-09-10 21:21:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-10 21:21:48 -0700 |
| commit | 5e8bf872f6adf145b75610dc216e942a84343179 (patch) | |
| tree | fba9fd9e3b84c88b19e650ba1da44075f23b7220 /src/libstd/sys | |
| parent | 76f17219c71973fd4a58f2f8020eec4d8f5dcd11 (diff) | |
| parent | 34e82a7b793a6cdd27df762bf46bab8cdc92b14a (diff) | |
| download | rust-5e8bf872f6adf145b75610dc216e942a84343179.tar.gz rust-5e8bf872f6adf145b75610dc216e942a84343179.zip | |
Merge pull request #21 from rust-lang/master
Sync with rust-lang/rust master branch
Diffstat (limited to 'src/libstd/sys')
40 files changed, 508 insertions, 1108 deletions
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs index e719b362cbf..03a59d6d7c8 100644 --- a/src/libstd/sys/cloudabi/shims/process.rs +++ b/src/libstd/sys/cloudabi/shims/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv<DefaultEnvKey>, + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -37,7 +39,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) {} - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index 000bb19f269..cc1c04a83e7 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -27,8 +27,7 @@ impl Condvar { pub unsafe fn wait(&self, mutex: &Mutex) { let guard = self.inner.lock(); - mutex.unlock(); - WaitQueue::wait(guard); + WaitQueue::wait(guard, || mutex.unlock()); mutex.lock() } diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs index f325fb1dd58..662da8b3f66 100644 --- a/src/libstd/sys/sgx/mutex.rs +++ b/src/libstd/sys/sgx/mutex.rs @@ -22,7 +22,7 @@ impl Mutex { let mut guard = self.inner.lock(); if *guard.lock_var() { // Another thread has the lock, wait - WaitQueue::wait(guard) + WaitQueue::wait(guard, ||{}) // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -83,7 +83,7 @@ impl ReentrantMutex { match guard.lock_var().owner { Some(tcs) if tcs != thread::current() => { // Another thread has the lock, wait - WaitQueue::wait(guard); + WaitQueue::wait(guard, ||{}); // Another thread has passed the lock to us }, _ => { diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs index a02e009d953..edf933d10e0 100644 --- a/src/libstd/sys/sgx/process.rs +++ b/src/libstd/sys/sgx/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv<DefaultEnvKey> + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 30c47e44eef..e2f94b1d928 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -31,7 +31,7 @@ impl RWLock { if *wguard.lock_var() || !wguard.queue_empty() { // Another thread has or is waiting for the write lock, wait drop(wguard); - WaitQueue::wait(rguard); + WaitQueue::wait(rguard, ||{}); // Another thread has passed the lock to us } else { // No waiting writers, acquire the read lock @@ -62,7 +62,7 @@ impl RWLock { if *wguard.lock_var() || rguard.lock_var().is_some() { // Another thread has the lock, wait drop(rguard); - WaitQueue::wait(wguard); + WaitQueue::wait(wguard, ||{}); // Another thread has passed the lock to us } else { // We are just now obtaining the lock @@ -97,6 +97,7 @@ impl RWLock { if let Ok(mut wguard) = WaitQueue::notify_one(wguard) { // A writer was waiting, pass the lock *wguard.lock_var_mut() = true; + wguard.drop_after(rguard); } else { // No writers were waiting, the lock is released rtassert!(rguard.queue_empty()); @@ -117,21 +118,26 @@ impl RWLock { rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZeroUsize>>>, wguard: SpinMutexGuard<'_, WaitVariable<bool>>, ) { - if let Err(mut wguard) = WaitQueue::notify_one(wguard) { - // No writers waiting, release the write lock - *wguard.lock_var_mut() = false; - if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { - // One or more readers were waiting, pass the lock to them - if let NotifiedTcs::All { count } = rguard.notified_tcs() { - *rguard.lock_var_mut() = Some(count) + match WaitQueue::notify_one(wguard) { + Err(mut wguard) => { + // No writers waiting, release the write lock + *wguard.lock_var_mut() = false; + if let Ok(mut rguard) = WaitQueue::notify_all(rguard) { + // One or more readers were waiting, pass the lock to them + if let NotifiedTcs::All { count } = rguard.notified_tcs() { + *rguard.lock_var_mut() = Some(count) + } else { + unreachable!() // called notify_all + } + rguard.drop_after(wguard); } else { - unreachable!() // called notify_all + // No readers waiting, the lock is released } - } else { - // No readers waiting, the lock is released + }, + Ok(wguard) => { + // There was a thread waiting for write, just pass the lock + wguard.drop_after(rguard); } - } else { - // There was a thread waiting for write, just pass the lock } } diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index d542f9b4101..3cb40e509b6 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -98,6 +98,12 @@ impl<'a, T> WaitGuard<'a, T> { pub fn notified_tcs(&self) -> NotifiedTcs { self.notified_tcs } + + /// Drop this `WaitGuard`, after dropping another `guard`. + pub fn drop_after<U>(self, guard: U) { + drop(guard); + drop(self); + } } impl<'a, T> Deref for WaitGuard<'a, T> { @@ -140,7 +146,7 @@ impl WaitQueue { /// until a wakeup event. /// /// This function does not return until this thread has been awoken. - pub fn wait<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>) { + pub fn wait<T, F: FnOnce()>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>, before_wait: F) { // very unsafe: check requirements of UnsafeList::push unsafe { let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry { @@ -149,6 +155,7 @@ impl WaitQueue { })); let entry = guard.queue.inner.push(&mut entry); drop(guard); + before_wait(); while !entry.lock().wake { // don't panic, this would invalidate `entry` during unwinding let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); @@ -545,7 +552,7 @@ mod tests { assert!(WaitQueue::notify_one(wq2.lock()).is_ok()); }); - WaitQueue::wait(locked); + WaitQueue::wait(locked, ||{}); t1.join().unwrap(); } diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index bba4b21c462..056a20345f4 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -1,5 +1,6 @@ pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; +pub use crate::ffi::OsString as EnvKey; mod process_common; #[cfg(not(target_os = "fuchsia"))] diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 21fca23a8fe..713d3085559 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -1,19 +1,27 @@ use crate::os::unix::prelude::*; -use crate::ffi::{OsString, OsStr, CString, CStr}; +use crate::ffi::{OsString, OsStr, CString}; use crate::fmt; use crate::io; use crate::ptr; use crate::sys::fd::FileDesc; -use crate::sys::fs::{File, OpenOptions}; +use crate::sys::fs::File; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; +#[cfg(not(target_os = "fuchsia"))] +use { + crate::ffi::CStr, + crate::sys::fs::OpenOptions, +}; + use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; cfg_if::cfg_if! { - if #[cfg(target_os = "redox")] { + if #[cfg(target_os = "fuchsia")] { + // fuchsia doesn't have /dev/null + } else if #[cfg(target_os = "redox")] { const DEV_NULL: &'static str = "null:\0"; } else { const DEV_NULL: &'static str = "/dev/null\0"; @@ -69,7 +77,7 @@ pub struct Command { program: CString, args: Vec<CString>, argv: Argv, - env: CommandEnv<DefaultEnvKey>, + env: CommandEnv, cwd: Option<CString>, uid: Option<uid_t>, @@ -107,6 +115,11 @@ pub enum ChildStdio { Inherit, Explicit(c_int), Owned(FileDesc), + + // On Fuchsia, null stdio is the default, so we simply don't specify + // any actions at the time of spawning. + #[cfg(target_os = "fuchsia")] + Null, } pub enum Stdio { @@ -201,7 +214,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -271,7 +284,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); @@ -325,6 +338,7 @@ impl Stdio { Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours))) } + #[cfg(not(target_os = "fuchsia"))] Stdio::Null => { let mut opts = OpenOptions::new(); opts.read(readable); @@ -335,6 +349,11 @@ impl Stdio { let fd = File::open_c(&path, &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } + + #[cfg(target_os = "fuchsia")] + Stdio::Null => { + Ok((ChildStdio::Null, None)) + } } } } @@ -357,6 +376,9 @@ impl ChildStdio { ChildStdio::Inherit => None, ChildStdio::Explicit(fd) => Some(fd), ChildStdio::Owned(ref fd) => Some(fd.raw()), + + #[cfg(target_os = "fuchsia")] + ChildStdio::Null => None, } } } diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 7c6be9b0a60..fff9fc6b3bb 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -48,30 +48,51 @@ impl Command { use crate::sys::process::zircon::*; let envp = match maybe_envp { - Some(envp) => envp.as_ptr(), + // None means to clone the current environment, which is done in the + // flags below. None => ptr::null(), + Some(envp) => envp.as_ptr(), }; - let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd { - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_TRANSFER_FD, - local_fd, - target_fd, - ..Default::default() - } - } else { - fdio_spawn_action_t { - action: FDIO_SPAWN_ACTION_CLONE_FD, - local_fd: target_fd, - target_fd, - ..Default::default() + let make_action = |local_io: &ChildStdio, target_fd| -> io::Result<fdio_spawn_action_t> { + if let Some(local_fd) = local_io.fd() { + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd, + target_fd, + ..Default::default() + }) + } else { + if let ChildStdio::Null = local_io { + // acts as no-op + return Ok(Default::default()); + } + + let mut handle = ZX_HANDLE_INVALID; + let status = fdio_fd_clone(target_fd, &mut handle); + if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED { + // This descriptor is closed; skip it rather than generating an + // error. + return Ok(Default::default()); + } + zx_cvt(status)?; + + let mut cloned_fd = 0; + zx_cvt(fdio_fd_create(handle, &mut cloned_fd))?; + + Ok(fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd: cloned_fd as i32, + target_fd, + ..Default::default() + }) } }; // Clone stdin, stdout, and stderr - let action1 = transfer_or_clone(stdio.stdin.fd(), 0); - let action2 = transfer_or_clone(stdio.stdout.fd(), 1); - let action3 = transfer_or_clone(stdio.stderr.fd(), 2); + let action1 = make_action(&stdio.stdin, 0)?; + let action2 = make_action(&stdio.stdout, 1)?; + let action3 = make_action(&stdio.stderr, 2)?; let actions = [action1, action2, action3]; // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc @@ -84,9 +105,11 @@ impl Command { let mut process_handle: zx_handle_t = 0; zx_cvt(fdio_spawn_etc( - 0, - FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, - self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(), + ZX_HANDLE_INVALID, + FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE + | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null + self.get_argv()[0], self.get_argv().as_ptr(), envp, + actions.len() as size_t, actions.as_ptr(), &mut process_handle, ptr::null_mut(), ))?; diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index a9711c71b7a..e6a742bd45d 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -178,23 +178,22 @@ impl Command { cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?; } - if cfg!(not(any(target_os = "l4re"))) { + #[cfg(not(target_os = "l4re"))] + { if let Some(u) = self.get_gid() { cvt(libc::setgid(u as gid_t))?; } if let Some(u) = self.get_uid() { + // When dropping privileges from root, the `setgroups` call + // will remove any extraneous groups. If we don't call this, + // then even though our uid has dropped, we may still have + // groups that enable us to do super-user things. This will + // fail if we aren't root, so don't bother checking the + // return value, this is just done as an optimistic + // privilege dropping function. //FIXME: Redox kernel does not support setgroups yet - if cfg!(not(target_os = "redox")) { - // When dropping privileges from root, the `setgroups` call - // will remove any extraneous groups. If we don't call this, - // then even though our uid has dropped, we may still have - // groups that enable us to do super-user things. This will - // fail if we aren't root, so don't bother checking the - // return value, this is just done as an optimistic - // privilege dropping function. - let _ = libc::setgroups(0, ptr::null()); - } - + #[cfg(not(target_os = "redox"))] + let _ = libc::setgroups(0, ptr::null()); cvt(libc::setuid(u as uid_t))?; } } @@ -203,7 +202,7 @@ impl Command { } // emscripten has no signal support. - #[cfg(not(any(target_os = "emscripten")))] + #[cfg(not(target_os = "emscripten"))] { use crate::mem::MaybeUninit; // Reset signal handling so the child process starts in a diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index ec715d5490f..1ba48de3c07 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -2,8 +2,9 @@ use crate::convert::TryInto; use crate::io; +use crate::i64; +use crate::mem::MaybeUninit; use crate::os::raw::c_char; -use crate::u64; use libc::{c_int, c_void, size_t}; @@ -14,8 +15,8 @@ pub type zx_status_t = i32; pub const ZX_HANDLE_INVALID: zx_handle_t = 0; -pub type zx_time_t = u64; -pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX; +pub type zx_time_t = i64; +pub const ZX_TIME_INFINITE : zx_time_t = i64::MAX; pub type zx_signals_t = u32; @@ -120,8 +121,11 @@ pub struct fdio_spawn_action_t { extern { pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char, - action_count: u64, actions: *const fdio_spawn_action_t, + action_count: size_t, actions: *const fdio_spawn_action_t, process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t; + + pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t; + pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t; } // fdio_spawn_etc flags diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 02f377d55c9..fd6796ad22c 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -311,6 +311,7 @@ mod inner { pub fn actually_monotonic() -> bool { (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) || (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) || + cfg!(target_os = "fuchsia") || false // last clause, used so `||` is always trailing above } diff --git a/src/libstd/sys/vxworks/backtrace/mod.rs b/src/libstd/sys/vxworks/backtrace/mod.rs deleted file mode 100644 index 0887e5a4df9..00000000000 --- a/src/libstd/sys/vxworks/backtrace/mod.rs +++ /dev/null @@ -1,110 +0,0 @@ -/// Backtrace support built on libgcc with some extra OS-specific support -/// -/// Some methods of getting a backtrace: -/// -/// * The backtrace() functions on unix. It turns out this doesn't work very -/// well for green threads on macOS, and the address to symbol portion of it -/// suffers problems that are described below. -/// -/// * Using libunwind. This is more difficult than it sounds because libunwind -/// isn't installed everywhere by default. It's also a bit of a hefty library, -/// so possibly not the best option. When testing, libunwind was excellent at -/// getting both accurate backtraces and accurate symbols across platforms. -/// This route was not chosen in favor of the next option, however. -/// -/// * We're already using libgcc_s for exceptions in rust (triggering thread -/// unwinding and running destructors on the stack), and it turns out that it -/// conveniently comes with a function that also gives us a backtrace. All of -/// these functions look like _Unwind_*, but it's not quite the full -/// repertoire of the libunwind API. Due to it already being in use, this was -/// the chosen route of getting a backtrace. -/// -/// After choosing libgcc_s for backtraces, the sad part is that it will only -/// give us a stack trace of instruction pointers. Thankfully these instruction -/// pointers are accurate (they work for green and native threads), but it's -/// then up to us again to figure out how to translate these addresses to -/// symbols. As with before, we have a few options. Before, that, a little bit -/// of an interlude about symbols. This is my very limited knowledge about -/// symbol tables, and this information is likely slightly wrong, but the -/// general idea should be correct. -/// -/// When talking about symbols, it's helpful to know a few things about where -/// symbols are located. Some symbols are located in the dynamic symbol table -/// of the executable which in theory means that they're available for dynamic -/// linking and lookup. Other symbols end up only in the local symbol table of -/// the file. This loosely corresponds to pub and priv functions in Rust. -/// -/// Armed with this knowledge, we know that our solution for address to symbol -/// translation will need to consult both the local and dynamic symbol tables. -/// With that in mind, here's our options of translating an address to -/// a symbol. -/// -/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr() -/// behind the scenes to translate, and this is why backtrace() was not used. -/// Conveniently, this method works fantastically on macOS. It appears dladdr() -/// uses magic to consult the local symbol table, or we're putting everything -/// in the dynamic symbol table anyway. Regardless, for macOS, this is the -/// method used for translation. It's provided by the system and easy to do.o -/// -/// Sadly, all other systems have a dladdr() implementation that does not -/// consult the local symbol table. This means that most functions are blank -/// because they don't have symbols. This means that we need another solution. -/// -/// * Use unw_get_proc_name(). This is part of the libunwind api (not the -/// libgcc_s version of the libunwind api), but involves taking a dependency -/// to libunwind. We may pursue this route in the future if we bundle -/// libunwind, but libunwind was unwieldy enough that it was not chosen at -/// this time to provide this functionality. -/// -/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a -/// semi-reasonable solution. The stdlib already knows how to spawn processes, -/// so in theory it could invoke readelf, parse the output, and consult the -/// local/dynamic symbol tables from there. This ended up not getting chosen -/// due to the craziness of the idea plus the advent of the next option. -/// -/// * Use `libbacktrace`. It turns out that this is a small library bundled in -/// the gcc repository which provides backtrace and symbol translation -/// functionality. All we really need from it is the backtrace functionality, -/// and we only really need this on everything that's not macOS, so this is the -/// chosen route for now. -/// -/// In summary, the current situation uses libgcc_s to get a trace of stack -/// pointers, and we use dladdr() or libbacktrace to translate these addresses -/// to symbols. This is a bit of a hokey implementation as-is, but it works for -/// all unix platforms we support right now, so it at least gets the job done. - -pub use self::tracing::unwind_backtrace; -pub use self::printing::{foreach_symbol_fileline, resolve_symname}; - -// tracing impls: -mod tracing; -// symbol resolvers: -mod printing; - -#[cfg(not(target_os = "emscripten"))] -pub mod gnu { - use crate::io; - use crate::fs; - - use libc::c_char; - - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { - use crate::env; - use crate::os::unix::ffi::OsStrExt; - - let filename = env::current_exe()?; - let file = fs::File::open(&filename)?; - let mut filename_cstr: Vec<_> = filename.as_os_str().as_bytes().iter() - .map(|&x| x as c_char).collect(); - filename_cstr.push(0); // Null terminate - Ok((filename_cstr, file)) - } -} - -pub struct BacktraceContext; diff --git a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs deleted file mode 100644 index 202164dd3c4..00000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::io; -use crate::intrinsics; -use crate::ffi::CStr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -pub fn resolve_symname<F>(frame: Frame, - callback: F, - _: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> -{ - unsafe { - let mut info: Dl_info = intrinsics::init(); - let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 || - info.dli_sname.is_null() { - None - } else { - CStr::from_ptr(info.dli_sname).to_str().ok() - }; - callback(symname) - } -} - -#[repr(C)] -struct Dl_info { - dli_fname: *const libc::c_char, - dli_fbase: *mut libc::c_void, - dli_sname: *const libc::c_char, - dli_saddr: *mut libc::c_void, -} - -extern { - #[ link_name = "_rtld_dladdr" ] - fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/printing/mod.rs b/src/libstd/sys/vxworks/backtrace/printing/mod.rs deleted file mode 100644 index d090caede43..00000000000 --- a/src/libstd/sys/vxworks/backtrace/printing/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -mod dladdr; - -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; -use crate::io; - -#[cfg(target_os = "emscripten")] -pub use self::dladdr::resolve_symname; - -#[cfg(target_os = "emscripten")] -pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool> -where - F: FnMut(&[u8], u32) -> io::Result<()> -{ - Ok(false) -} - -#[cfg(not(target_os = "emscripten"))] -pub use crate::sys_common::gnu::libbacktrace::foreach_symbol_fileline; - -#[cfg(not(target_os = "emscripten"))] -pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()> -where - F: FnOnce(Option<&str>) -> io::Result<()> -{ - crate::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| { - if symname.is_some() { - callback(symname) - } else { - dladdr::resolve_symname(frame, callback, bc) - } - }, bc) -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs deleted file mode 100644 index a628d107ad6..00000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs +++ /dev/null @@ -1,39 +0,0 @@ -/// As always - iOS on arm uses SjLj exceptions and -/// _Unwind_Backtrace is even not available there. Still, -/// backtraces could be extracted using a backtrace function, -/// which thanks god is public -/// -/// As mentioned in a huge comment block in `super::super`, backtrace -/// doesn't play well with green threads, so while it is extremely nice and -/// simple to use it should be used only on iOS devices as the only viable -/// option. - -use crate::io; -use crate::ptr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - const FRAME_LEN: usize = 100; - assert!(FRAME_LEN >= frames.len()); - let mut raw_frames = [ptr::null_mut(); FRAME_LEN]; - let nb_frames = unsafe { - backtrace(raw_frames.as_mut_ptr(), raw_frames.len() as libc::c_int) - } as usize; - for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) { - *to = Frame { - exact_position: *from as *mut u8, - symbol_addr: *from as *mut u8, - inline_context: 0, - }; - } - Ok((nb_frames as usize, BacktraceContext)) -} - -extern { - fn backtrace(buf: *mut *mut libc::c_void, sz: libc::c_int) -> libc::c_int; -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs deleted file mode 100644 index e6379132baf..00000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::error::Error; -use crate::fmt; -use crate::io; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -use unwind as uw; - -struct Context<'a> { - idx: usize, - frames: &'a mut [Frame], -} - -#[derive(Debug)] -struct UnwindError(uw::_Unwind_Reason_Code); - -impl Error for UnwindError { - fn description(&self) -> &'static str { - "unexpected return value while unwinding" - } -} - -impl fmt::Display for UnwindError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}: {:?}", self.description(), self.0) - } -} - -#[inline(never)] // if we know this is a function call, we can skip it when - // tracing -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - let mut cx = Context { - idx: 0, - frames, - }; - let result_unwind = unsafe { - uw::_Unwind_Backtrace(trace_fn, - &mut cx as *mut Context<'_> - as *mut libc::c_void) - }; - // See libunwind:src/unwind/Backtrace.c for the return values. - // No, there is no doc. - match result_unwind { - // These return codes seem to be benign and need to be ignored for backtraces - // to show up properly on all tested platforms. - uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { - Ok((cx.idx, BacktraceContext)) - } - _ => { - Err(io::Error::new(io::ErrorKind::Other, - UnwindError(result_unwind))) - } - } -} - -extern fn trace_fn(ctx: *mut uw::_Unwind_Context, - arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { - let cx = unsafe { &mut *(arg as *mut Context<'_>) }; - if cx.idx >= cx.frames.len() { - return uw::_URC_NORMAL_STOP; - } - - let mut ip_before_insn = 0; - let mut ip = unsafe { - uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void - }; - if !ip.is_null() && ip_before_insn == 0 { - // this is a non-signaling frame, so `ip` refers to the address - // after the calling instruction. account for that. - ip = (ip as usize - 1) as *mut _; - } - - // dladdr() on osx gets whiny when we use FindEnclosingFunction, and - // it appears to work fine without it, so we only use - // FindEnclosingFunction on non-osx platforms. In doing so, we get a - // slightly more accurate stack trace in the process. - // - // This is often because panic involves the last instruction of a - // function being "call std::rt::begin_unwind", with no ret - // instructions after it. This means that the return instruction - // pointer points *outside* of the calling function, and by - // unwinding it we go back to the original function. - let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { - ip - } else { - unsafe { uw::_Unwind_FindEnclosingFunction(ip) } - }; - - cx.frames[cx.idx] = Frame { - symbol_addr: symaddr as *mut u8, - exact_position: ip as *mut u8, - inline_context: 0, - }; - cx.idx += 1; - - uw::_URC_NO_REASON -} diff --git a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs deleted file mode 100644 index 11863e64545..00000000000 --- a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub use self::imp::*; - -#[cfg(not(all(target_os = "ios", target_arch = "arm")))] -#[path = "gcc_s.rs"] -mod imp; -#[cfg(all(target_os = "ios", target_arch = "arm"))] -#[path = "backtrace_fn.rs"] -mod imp; diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs index f5a2e263d25..2e021980778 100644 --- a/src/libstd/sys/vxworks/fast_thread_local.rs +++ b/src/libstd/sys/vxworks/fast_thread_local.rs @@ -1,33 +1,10 @@ +// Copyright (c) 2019 Wind River Systems, Inc. + #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -// Since what appears to be glibc 2.18 this symbol has been shipped which -// GCC and clang both use to invoke destructors in thread_local globals, so -// let's do the same! -// -// Note, however, that we run on lots older linuxes, as well as cross -// compiling from a newer linux to an older linux, so we also have a -// fallback implementation to use as well. -// -// Due to rust-lang/rust#18804, make sure this is not generic! pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use crate::mem; use crate::sys_common::thread_local::register_dtor_fallback; - - extern { - #[linkage = "extern_weak"] - static __dso_handle: *mut u8; - #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; - } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) - (dtor, t, &__dso_handle as *const _ as *mut _); - return - } register_dtor_fallback(t, dtor); } diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index ba797354a73..509140229fd 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -7,11 +7,13 @@ use crate::ptr; use crate::sys::fd::FileDesc; use crate::sys::fs::{File, OpenOptions}; use crate::sys::pipe::{self, AnonPipe}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; use crate::collections::BTreeMap; use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; +pub use crate::ffi::OsString as EnvKey; + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -37,7 +39,7 @@ pub struct Command { program: CString, args: Vec<CString>, argv: Argv, - env: CommandEnv<DefaultEnvKey>, + env: CommandEnv, cwd: Option<CString>, uid: Option<uid_t>, @@ -170,7 +172,7 @@ impl Command { self.stderr = Some(stderr); } - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } @@ -240,7 +242,7 @@ impl CStringArray { } } -fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray { +fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); for (k, v) in env { let mut k: OsString = k.into(); diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 58af8cbe48e..ef896f6a6e8 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -77,7 +77,7 @@ impl Thread { } pub fn set_name(_name: &CStr) { - assert!(false, "FIXME: set_name"); + // VxWorks does not provide a way to set the task name except at creation time } pub fn sleep(dur: Duration) { diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs index 8b4b354d9fc..3280c4990dc 100644 --- a/src/libstd/sys/wasi/args.rs +++ b/src/libstd/sys/wasi/args.rs @@ -1,11 +1,10 @@ -use crate::ffi::CStr; -use crate::io; -use crate::sys::cvt_wasi; use crate::ffi::OsString; use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStringExt; use crate::vec; +use ::wasi::wasi_unstable as wasi; + pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } @@ -19,31 +18,17 @@ pub struct Args { /// Returns the command line arguments pub fn args() -> Args { - maybe_args().unwrap_or_else(|_| { - Args { - iter: Vec::new().into_iter(), - _dont_send_or_sync_me: PhantomData - } - }) -} - -fn maybe_args() -> io::Result<Args> { - unsafe { - let (mut argc, mut argv_buf_size) = (0, 0); - cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?; - - let mut argc = vec![core::ptr::null_mut::<libc::c_char>(); argc]; - let mut argv_buf = vec![0; argv_buf_size]; - cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?; - - let args = argc.into_iter() - .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec()) - .map(|bytes| OsString::from_vec(bytes)) - .collect::<Vec<_>>(); - Ok(Args { - iter: args.into_iter(), - _dont_send_or_sync_me: PhantomData, - }) + let buf = wasi::args_sizes_get().and_then(|args_sizes| { + let mut buf = Vec::with_capacity(args_sizes.get_count()); + wasi::args_get(args_sizes, |arg| { + let arg = OsString::from_vec(arg.to_vec()); + buf.push(arg); + })?; + Ok(buf) + }).unwrap_or(vec![]); + Args { + iter: buf.into_iter(), + _dont_send_or_sync_me: PhantomData } } diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs index 0ec4122f385..9fa4abfd171 100644 --- a/src/libstd/sys/wasi/ext/fs.rs +++ b/src/libstd/sys/wasi/ext/fs.rs @@ -8,6 +8,8 @@ use crate::os::wasi::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; +use ::wasi::wasi_unstable as wasi; + /// WASI-specific extensions to [`File`]. /// /// [`File`]: ../../../../std/fs/struct.File.html @@ -336,16 +338,16 @@ pub trait FileTypeExt { impl FileTypeExt for fs::FileType { fn is_block_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE + self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE } fn is_character_device(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE + self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE } fn is_socket_dgram(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM } fn is_socket_stream(&self) -> bool { - self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM + self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM } } diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs index 12afd1d42dc..f1839df3801 100644 --- a/src/libstd/sys/wasi/ext/io.rs +++ b/src/libstd/sys/wasi/ext/io.rs @@ -8,6 +8,8 @@ use crate::sys; use crate::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; +use ::wasi::wasi_unstable as wasi; + /// Raw file descriptors. pub type RawFd = u32; @@ -125,18 +127,18 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as u32 + wasi::STDIN_FD } } impl AsRawFd for io::Stdout { fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as u32 + wasi::STDOUT_FD } } impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as u32 + wasi::STDERR_FD } } diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 25692ec0868..5b7a8678b66 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -3,348 +3,248 @@ use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; -use crate::sys::cvt_wasi; -use libc::{self, c_char, c_void}; +use super::err2io; +use ::wasi::wasi_unstable as wasi; #[derive(Debug)] pub struct WasiFd { - fd: libc::__wasi_fd_t, + fd: wasi::Fd, } -// FIXME: these should probably all be fancier structs, builders, enums, etc -pub type LookupFlags = u32; -pub type FdFlags = u16; -pub type Advice = u8; -pub type Rights = u64; -pub type Oflags = u16; -pub type DirCookie = u64; -pub type Timestamp = u64; -pub type FstFlags = u16; -pub type RiFlags = u16; -pub type RoFlags = u16; -pub type SiFlags = u16; - -fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) { +fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] { assert_eq!( mem::size_of::<IoSliceMut<'_>>(), - mem::size_of::<libc::__wasi_iovec_t>() + mem::size_of::<wasi::IoVec>() ); assert_eq!( mem::align_of::<IoSliceMut<'_>>(), - mem::align_of::<libc::__wasi_iovec_t>() + mem::align_of::<wasi::IoVec>() ); - (a.as_ptr() as *const libc::__wasi_iovec_t, a.len()) + /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } -fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) { +fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] { assert_eq!( mem::size_of::<IoSlice<'_>>(), - mem::size_of::<libc::__wasi_ciovec_t>() + mem::size_of::<wasi::CIoVec>() ); assert_eq!( mem::align_of::<IoSlice<'_>>(), - mem::align_of::<libc::__wasi_ciovec_t>() + mem::align_of::<wasi::CIoVec>() ); - (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len()) + /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout + unsafe { mem::transmute(a) } } impl WasiFd { - pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd { + pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> libc::__wasi_fd_t { + pub fn into_raw(self) -> wasi::Fd { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> libc::__wasi_fd_t { + pub fn as_raw(&self) -> wasi::Fd { self.fd } pub fn datasync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) }) + unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?; - Ok(read) + unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - let mut read = 0; - let (ptr, len) = iovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?; - Ok(read) + unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let mut read = 0; - let (ptr, len) = ciovec(bufs); - cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?; - Ok(read) + unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> { let (whence, offset) = match pos { - SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64), - SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos), - SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos), + SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64), + SeekFrom::End(pos) => (wasi::WHENCE_END, pos), + SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?; - Ok(pos) + unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result<u64> { - let mut pos = 0; - cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?; - Ok(pos) + unsafe { wasi::fd_tell(self.fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get - pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) }) + pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> { + unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } } - pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) }) + 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) } } pub fn sync(&self) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) }) + unsafe { wasi::fd_sync(self.fd).map_err(err2io) } } - pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) }) + 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) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) }) + unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } } pub fn link( &self, - old_flags: LookupFlags, + old_flags: wasi::LookupFlags, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8], ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_link( - self.fd, - old_flags, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { + wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path) + .map_err(err2io) + } } pub fn open( &self, - dirflags: LookupFlags, + dirflags: wasi::LookupFlags, path: &[u8], - oflags: Oflags, - fs_rights_base: Rights, - fs_rights_inheriting: Rights, - fs_flags: FdFlags, + oflags: wasi::OFlags, + fs_rights_base: wasi::Rights, + fs_rights_inheriting: wasi::Rights, + fs_flags: wasi::FdFlags, ) -> io::Result<WasiFd> { unsafe { - let mut fd = 0; - cvt_wasi(libc::__wasi_path_open( + wasi::path_open( self.fd, dirflags, - path.as_ptr() as *const c_char, - path.len(), + path, oflags, fs_rights_base, fs_rights_inheriting, fs_flags, - &mut fd, - ))?; - Ok(WasiFd::from_raw(fd)) + ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io) } } - pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_fd_readdir( - self.fd, - buf.as_mut_ptr() as *mut c_void, - buf.len(), - cookie, - &mut used, - ) - })?; - Ok(used) + pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> { + unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) } } pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> { - let mut used = 0; - cvt_wasi(unsafe { - libc::__wasi_path_readlink( - self.fd, - path.as_ptr() as *const c_char, - path.len(), - buf.as_mut_ptr() as *mut c_char, - buf.len(), - &mut used, - ) - })?; - Ok(used) + unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) } } pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_rename( - self.fd, - old_path.as_ptr() as *const c_char, - old_path.len(), - new_fd.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { + wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) + } } - pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) }) + pub fn filestat_get(&self) -> io::Result<wasi::FileStat> { + unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } } pub fn filestat_set_times( &self, - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) }) + unsafe { + wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) }) + unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } } pub fn path_filestat_get( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - buf: *mut libc::__wasi_filestat_t, - ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_get( - self.fd, - flags, - path.as_ptr() as *const c_char, - path.len(), - buf, - ) - }) + ) -> io::Result<wasi::FileStat> { + unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( &self, - flags: LookupFlags, + flags: wasi::LookupFlags, path: &[u8], - atim: Timestamp, - mtim: Timestamp, - fstflags: FstFlags, + atim: wasi::Timestamp, + mtim: wasi::Timestamp, + fstflags: wasi::FstFlags, ) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_filestat_set_times( + unsafe { + wasi::path_filestat_set_times( self.fd, flags, - path.as_ptr() as *const c_char, - path.len(), + path, atim, mtim, fstflags, - ) - }) + ).map_err(err2io) + } } pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_symlink( - old_path.as_ptr() as *const c_char, - old_path.len(), - self.fd, - new_path.as_ptr() as *const c_char, - new_path.len(), - ) - }) + unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> { - cvt_wasi(unsafe { - libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len()) - }) + unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } } pub fn sock_recv( &self, ri_data: &mut [IoSliceMut<'_>], - ri_flags: RiFlags, - ) -> io::Result<(usize, RoFlags)> { - let mut ro_datalen = 0; - let mut ro_flags = 0; - let (ptr, len) = iovec(ri_data); - cvt_wasi(unsafe { - libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags) - })?; - Ok((ro_datalen, ro_flags)) + ri_flags: wasi::RiFlags, + ) -> io::Result<(usize, wasi::RoFlags)> { + unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } } - pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result<usize> { - let mut so_datalen = 0; - let (ptr, len) = ciovec(si_data); - cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?; - Ok(so_datalen) + pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result<usize> { + unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { let how = match how { - Shutdown::Read => libc::__WASI_SHUT_RD, - Shutdown::Write => libc::__WASI_SHUT_WR, - Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD, + Shutdown::Read => wasi::SHUT_RD, + Shutdown::Write => wasi::SHUT_WR, + Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD, }; - cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?; - Ok(()) + unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } } } impl Drop for WasiFd { fn drop(&mut self) { - unsafe { - // FIXME: can we handle the return code here even though we can't on - // unix? - libc::__wasi_fd_close(self.fd); - } + // FIXME: can we handle the return code here even though we can't on + // unix? + let _ = unsafe { wasi::fd_close(self.fd) }; } } diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index 172c60385b3..4113f6a2e09 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -7,7 +7,7 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sync::Arc; -use crate::sys::fd::{DirCookie, WasiFd}; +use crate::sys::fd::WasiFd; use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; @@ -15,18 +15,20 @@ use crate::sys_common::FromInner; pub use crate::sys_common::fs::copy; pub use crate::sys_common::fs::remove_dir_all; +use ::wasi::wasi_unstable as wasi; + pub struct File { fd: WasiFd, } #[derive(Clone)] pub struct FileAttr { - meta: libc::__wasi_filestat_t, + meta: wasi::FileStat, } pub struct ReadDir { inner: Arc<ReadDirInner>, - cookie: Option<DirCookie>, + cookie: Option<wasi::DirCookie>, buf: Vec<u8>, offset: usize, cap: usize, @@ -38,7 +40,7 @@ struct ReadDirInner { } pub struct DirEntry { - meta: libc::__wasi_dirent_t, + meta: wasi::Dirent, name: Vec<u8>, inner: Arc<ReadDirInner>, } @@ -47,11 +49,11 @@ pub struct DirEntry { pub struct OpenOptions { read: bool, write: bool, - dirflags: libc::__wasi_lookupflags_t, - fdflags: libc::__wasi_fdflags_t, - oflags: libc::__wasi_oflags_t, - rights_base: Option<libc::__wasi_rights_t>, - rights_inheriting: Option<libc::__wasi_rights_t>, + dirflags: wasi::LookupFlags, + fdflags: wasi::FdFlags, + oflags: wasi::OFlags, + rights_base: Option<wasi::Rights>, + rights_inheriting: Option<wasi::Rights>, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -61,19 +63,13 @@ pub struct FilePermissions { #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub struct FileType { - bits: libc::__wasi_filetype_t, + bits: wasi::FileType, } #[derive(Debug)] pub struct DirBuilder {} impl FileAttr { - fn zero() -> FileAttr { - FileAttr { - meta: unsafe { mem::zeroed() }, - } - } - pub fn size(&self) -> u64 { self.meta.st_size } @@ -101,7 +97,7 @@ impl FileAttr { Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim)) } - pub fn as_wasi(&self) -> &libc::__wasi_filestat_t { + pub fn as_wasi(&self) -> &wasi::FileStat { &self.meta } } @@ -118,18 +114,18 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_DIRECTORY + self.bits == wasi::FILETYPE_DIRECTORY } pub fn is_file(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_REGULAR_FILE + self.bits == wasi::FILETYPE_REGULAR_FILE } pub fn is_symlink(&self) -> bool { - self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK + self.bits == wasi::FILETYPE_SYMBOLIC_LINK } - pub fn bits(&self) -> libc::__wasi_filetype_t { + pub fn bits(&self) -> wasi::FileType { self.bits } } @@ -173,7 +169,7 @@ impl Iterator for ReadDir { // must have been truncated at the end of the buffer, so reset our // offset so we can go back and reread into the buffer, picking up // where we last left off. - let dirent_size = mem::size_of::<libc::__wasi_dirent_t>(); + let dirent_size = mem::size_of::<wasi::Dirent>(); if data.len() < dirent_size { assert!(self.cookie.is_some()); assert!(self.buf.len() >= dirent_size); @@ -182,7 +178,7 @@ impl Iterator for ReadDir { } let (dirent, data) = data.split_at(dirent_size); let dirent = - unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) }; + unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) }; // If the file name was truncated, then we need to reinvoke // `readdir` so we truncate our buffer to start over and reread this @@ -241,7 +237,7 @@ impl DirEntry { }) } - pub fn ino(&self) -> libc::__wasi_inode_t { + pub fn ino(&self) -> wasi::Inode { self.meta.d_ino } } @@ -249,7 +245,7 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { let mut base = OpenOptions::default(); - base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW; + base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW; return base; } @@ -262,23 +258,23 @@ impl OpenOptions { } pub fn truncate(&mut self, truncate: bool) { - self.oflag(libc::__WASI_O_TRUNC, truncate); + self.oflag(wasi::O_TRUNC, truncate); } pub fn create(&mut self, create: bool) { - self.oflag(libc::__WASI_O_CREAT, create); + self.oflag(wasi::O_CREAT, create); } pub fn create_new(&mut self, create_new: bool) { - self.oflag(libc::__WASI_O_EXCL, create_new); - self.oflag(libc::__WASI_O_CREAT, create_new); + self.oflag(wasi::O_EXCL, create_new); + self.oflag(wasi::O_CREAT, create_new); } pub fn directory(&mut self, directory: bool) { - self.oflag(libc::__WASI_O_DIRECTORY, directory); + self.oflag(wasi::O_DIRECTORY, directory); } - fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) { + fn oflag(&mut self, bit: wasi::OFlags, set: bool) { if set { self.oflags |= bit; } else { @@ -287,26 +283,26 @@ impl OpenOptions { } pub fn append(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_APPEND, set); + self.fdflag(wasi::FDFLAG_APPEND, set); } pub fn dsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_DSYNC, set); + self.fdflag(wasi::FDFLAG_DSYNC, set); } pub fn nonblock(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set); + self.fdflag(wasi::FDFLAG_NONBLOCK, set); } pub fn rsync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_RSYNC, set); + self.fdflag(wasi::FDFLAG_RSYNC, set); } pub fn sync(&mut self, set: bool) { - self.fdflag(libc::__WASI_FDFLAG_SYNC, set); + self.fdflag(wasi::FDFLAG_SYNC, set); } - fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) { + fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) { if set { self.fdflags |= bit; } else { @@ -314,15 +310,15 @@ impl OpenOptions { } } - pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_base(&mut self, rights: wasi::Rights) { self.rights_base = Some(rights); } - pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) { + pub fn fs_rights_inheriting(&mut self, rights: wasi::Rights) { self.rights_inheriting = Some(rights); } - fn rights_base(&self) -> libc::__wasi_rights_t { + fn rights_base(&self) -> wasi::Rights { if let Some(rights) = self.rights_base { return rights; } @@ -334,52 +330,52 @@ impl OpenOptions { // based on that. let mut base = 0; if self.read { - base |= libc::__WASI_RIGHT_FD_READ; - base |= libc::__WASI_RIGHT_FD_READDIR; + base |= wasi::RIGHT_FD_READ; + base |= wasi::RIGHT_FD_READDIR; } if self.write { - base |= libc::__WASI_RIGHT_FD_WRITE; - base |= libc::__WASI_RIGHT_FD_DATASYNC; - base |= libc::__WASI_RIGHT_FD_ALLOCATE; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE; + base |= wasi::RIGHT_FD_WRITE; + base |= wasi::RIGHT_FD_DATASYNC; + base |= wasi::RIGHT_FD_ALLOCATE; + base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE; } // FIXME: some of these should probably be read-only or write-only... - base |= libc::__WASI_RIGHT_FD_ADVISE; - base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS; - base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES; - base |= libc::__WASI_RIGHT_FD_SEEK; - base |= libc::__WASI_RIGHT_FD_SYNC; - base |= libc::__WASI_RIGHT_FD_TELL; - base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_CREATE_FILE; - base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET; - base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE; - base |= libc::__WASI_RIGHT_PATH_LINK_TARGET; - base |= libc::__WASI_RIGHT_PATH_OPEN; - base |= libc::__WASI_RIGHT_PATH_READLINK; - base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY; - base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE; - base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET; - base |= libc::__WASI_RIGHT_PATH_SYMLINK; - base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE; - base |= libc::__WASI_RIGHT_POLL_FD_READWRITE; + base |= wasi::RIGHT_FD_ADVISE; + base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS; + base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES; + base |= wasi::RIGHT_FD_SEEK; + base |= wasi::RIGHT_FD_SYNC; + base |= wasi::RIGHT_FD_TELL; + base |= wasi::RIGHT_PATH_CREATE_DIRECTORY; + base |= wasi::RIGHT_PATH_CREATE_FILE; + base |= wasi::RIGHT_PATH_FILESTAT_GET; + base |= wasi::RIGHT_PATH_LINK_SOURCE; + base |= wasi::RIGHT_PATH_LINK_TARGET; + base |= wasi::RIGHT_PATH_OPEN; + base |= wasi::RIGHT_PATH_READLINK; + base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY; + base |= wasi::RIGHT_PATH_RENAME_SOURCE; + base |= wasi::RIGHT_PATH_RENAME_TARGET; + base |= wasi::RIGHT_PATH_SYMLINK; + base |= wasi::RIGHT_PATH_UNLINK_FILE; + base |= wasi::RIGHT_POLL_FD_READWRITE; return base; } - fn rights_inheriting(&self) -> libc::__wasi_rights_t { + fn rights_inheriting(&self) -> wasi::Rights { self.rights_inheriting.unwrap_or_else(|| self.rights_base()) } - pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) { + pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) { self.dirflags = flags; } } impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { - let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?; + let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?; open_at(&dir, &file, opts) } @@ -388,14 +384,12 @@ impl File { } pub fn file_attr(&self) -> io::Result<FileAttr> { - let mut ret = FileAttr::zero(); - self.fd.filestat_get(&mut ret.meta)?; - Ok(ret) + self.fd.filestat_get().map(|meta| FileAttr { meta }) } pub fn metadata_at( &self, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result<FileAttr> { metadata_at(&self.fd, flags, path) @@ -477,7 +471,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?; dir.create_directory(file.as_os_str().as_bytes()) } } @@ -508,13 +502,13 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> { } pub fn unlink(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?; dir.unlink_file(file.as_os_str().as_bytes()) } pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?; - let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?; + let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?; + let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?; old.rename( old_file.as_os_str().as_bytes(), &new, @@ -529,12 +523,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(p: &Path) -> io::Result<()> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?; dir.remove_directory(file.as_os_str().as_bytes()) } pub fn readlink(p: &Path) -> io::Result<PathBuf> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?; read_link(&dir, &file) } @@ -570,15 +564,15 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?; dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes()) } pub fn link(src: &Path, dst: &Path) -> io::Result<()> { - let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?; - let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?; + let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?; + let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?; src.link( - libc::__WASI_LOOKUP_SYMLINK_FOLLOW, + wasi::LOOKUP_SYMLINK_FOLLOW, src_file.as_os_str().as_bytes(), &dst, dst_file.as_os_str().as_bytes(), @@ -586,23 +580,22 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { } pub fn stat(p: &Path) -> io::Result<FileAttr> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; - metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file) + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; + metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file) } pub fn lstat(p: &Path) -> io::Result<FileAttr> { - let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?; + let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?; metadata_at(&dir, 0, &file) } fn metadata_at( fd: &WasiFd, - flags: libc::__wasi_lookupflags_t, + flags: wasi::LookupFlags, path: &Path, ) -> io::Result<FileAttr> { - let mut ret = FileAttr::zero(); - fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?; - Ok(ret) + fd.path_filestat_get(flags, path.as_os_str().as_bytes()) + .map(|meta| FileAttr { meta }) } pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { @@ -652,12 +645,12 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> { /// to any preopened file descriptor. fn open_parent( p: &Path, - rights: libc::__wasi_rights_t, + rights: wasi::Rights, ) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> { let p = CString::new(p.as_os_str().as_bytes())?; unsafe { let mut ret = ptr::null(); - let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); + let fd = libc::__wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret); if fd == -1 { let msg = format!( "failed to find a preopened file descriptor \ @@ -677,15 +670,4 @@ fn open_parent( return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path)); } - - // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API - // there is published - extern "C" { - pub fn __wasilibc_find_relpath( - path: *const libc::c_char, - rights_base: libc::__wasi_rights_t, - rights_inheriting: libc::__wasi_rights_t, - relative_path: *mut *const libc::c_char, - ) -> libc::c_int; - } } diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ffecca5d1b6..4be92faed30 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,11 +1,12 @@ use crate::marker::PhantomData; use crate::slice; -use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void}; +use ::wasi::wasi_unstable as wasi; +use core::ffi::c_void; #[repr(transparent)] pub struct IoSlice<'a> { - vec: __wasi_ciovec_t, + vec: wasi::CIoVec, _p: PhantomData<&'a [u8]>, } @@ -13,7 +14,7 @@ impl<'a> IoSlice<'a> { #[inline] pub fn new(buf: &'a [u8]) -> IoSlice<'a> { IoSlice { - vec: __wasi_ciovec_t { + vec: wasi::CIoVec { buf: buf.as_ptr() as *const c_void, buf_len: buf.len(), }, @@ -43,7 +44,7 @@ impl<'a> IoSlice<'a> { #[repr(transparent)] pub struct IoSliceMut<'a> { - vec: __wasi_iovec_t, + vec: wasi::IoVec, _p: PhantomData<&'a mut [u8]>, } @@ -51,7 +52,7 @@ impl<'a> IoSliceMut<'a> { #[inline] pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { IoSliceMut { - vec: __wasi_iovec_t { + vec: wasi::IoVec { buf: buf.as_mut_ptr() as *mut c_void, buf_len: buf.len() }, diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index f842869e08e..517e3be9cb5 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -14,10 +14,10 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use libc; -use crate::io::{Error, ErrorKind}; +use crate::io as std_io; use crate::mem; use crate::os::raw::c_char; +use ::wasi::wasi_unstable as wasi; pub mod alloc; pub mod args; @@ -56,16 +56,43 @@ pub mod ext; pub fn init() { } -pub fn unsupported<T>() -> crate::io::Result<T> { +pub fn unsupported<T>() -> std_io::Result<T> { Err(unsupported_err()) } -pub fn unsupported_err() -> Error { - Error::new(ErrorKind::Other, "operation not supported on wasm yet") +pub fn unsupported_err() -> std_io::Error { + std_io::Error::new( + std_io::ErrorKind::Other, + "operation not supported on wasm yet", + ) } -pub fn decode_error_kind(_code: i32) -> ErrorKind { - ErrorKind::Other +pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { + use std_io::ErrorKind::*; + if errno > u16::max_value() as i32 || errno < 0 { + return Other; + } + let code = match wasi::Error::new(errno as u16) { + Some(code) => code, + None => return Other, + }; + match code { + wasi::ECONNREFUSED => ConnectionRefused, + wasi::ECONNRESET => ConnectionReset, + wasi::EPERM | wasi::EACCES => PermissionDenied, + wasi::EPIPE => BrokenPipe, + wasi::ENOTCONN => NotConnected, + wasi::ECONNABORTED => ConnectionAborted, + wasi::EADDRNOTAVAIL => AddrNotAvailable, + wasi::EADDRINUSE => AddrInUse, + wasi::ENOENT => NotFound, + wasi::EINTR => Interrupted, + wasi::EINVAL => InvalidInput, + wasi::ETIMEDOUT => TimedOut, + wasi::EEXIST => AlreadyExists, + wasi::EAGAIN => WouldBlock, + _ => Other, + } } // This enum is used as the storage for a bunch of types which can't actually @@ -89,40 +116,16 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { let mut ret = (0u64, 0u64); unsafe { - let base = &mut ret as *mut (u64, u64) as *mut libc::c_void; + let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void; let len = mem::size_of_val(&ret); - cvt_wasi(libc::__wasi_random_get(base, len)).unwrap(); - } - return ret -} - -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 + let ret = wasi::raw::__wasi_random_get(base, len); + if ret != 0 { + panic!("__wasi_random_get failure") } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> { - if t.is_minus_one() { - Err(Error::last_os_error()) - } else { - Ok(t) } + return ret } -pub fn cvt_wasi(r: u16) -> crate::io::Result<()> { - if r != libc::__WASI_ESUCCESS { - Err(Error::from_raw_os_error(r as i32)) - } else { - Ok(()) - } +fn err2io(err: wasi::Error) -> std_io::Error { + std_io::Error::from_raw_os_error(err.get() as i32) } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 822ea02a11b..feee8407825 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -9,7 +9,7 @@ use crate::path::{self, PathBuf}; use crate::ptr; use crate::str; use crate::sys::memchr; -use crate::sys::{cvt, unsupported, Void}; +use crate::sys::{unsupported, Void}; use crate::vec; #[cfg(not(target_feature = "atomics"))] @@ -28,16 +28,11 @@ pub fn errno() -> i32 { } pub fn error_string(errno: i32) -> String { - extern { - fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char, - buflen: libc::size_t) -> libc::c_int; - } - let mut buf = [0 as libc::c_char; 1024]; let p = buf.as_mut_ptr(); unsafe { - if strerror_r(errno as libc::c_int, p, buf.len()) < 0 { + if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 { panic!("strerror_r failure"); } str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() @@ -89,7 +84,6 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result<PathBuf> { unsupported() } - pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, @@ -182,3 +176,26 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("unsupported"); } + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs index 788b829f4ba..1c4d028b761 100644 --- a/src/libstd/sys/wasi/process.rs +++ b/src/libstd/sys/wasi/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv<DefaultEnvKey> + env: CommandEnv } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 2bf8d803c01..1d57b9922e5 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -1,8 +1,9 @@ use crate::io::{self, IoSlice, IoSliceMut}; -use crate::libc; use crate::mem::ManuallyDrop; use crate::sys::fd::WasiFd; +use ::wasi::wasi_unstable as wasi; + pub struct Stdin; pub struct Stdout; pub struct Stderr; @@ -17,7 +18,7 @@ impl Stdin { } pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) }) .read(data) } } @@ -32,7 +33,7 @@ impl Stdout { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) }) .write(data) } @@ -51,7 +52,7 @@ impl Stderr { } pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> { - ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) }) + ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) }) .write(data) } @@ -73,7 +74,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - err.raw_os_error() == Some(libc::__WASI_EBADF as i32) + err.raw_os_error() == Some(wasi::EBADF.get() as i32) } pub fn panic_output() -> Option<impl io::Write> { diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 5e69e4d948f..28a504f1979 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -1,10 +1,10 @@ -use crate::cmp; use crate::ffi::CStr; use crate::io; -use crate::sys::cvt; +use crate::mem; use crate::sys::{unsupported, Void}; use crate::time::Duration; -use libc; + +use ::wasi::wasi_unstable as wasi; pub struct Thread(Void); @@ -19,8 +19,8 @@ impl Thread { } pub fn yield_now() { - let ret = unsafe { libc::__wasi_sched_yield() }; - debug_assert_eq!(ret, 0); + let ret = wasi::sched_yield(); + debug_assert_eq!(ret, Ok(())); } pub fn set_name(_name: &CStr) { @@ -28,19 +28,37 @@ impl Thread { } pub fn sleep(dur: Duration) { - let mut secs = dur.as_secs(); - let mut nsecs = dur.subsec_nanos() as i32; - - unsafe { - while secs > 0 || nsecs > 0 { - let mut ts = libc::timespec { - tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t, - tv_nsec: nsecs, - }; - secs -= ts.tv_sec as u64; - cvt(libc::nanosleep(&ts, &mut ts)).unwrap(); - nsecs = 0; - } + let nanos = dur.as_nanos(); + assert!(nanos <= u64::max_value() as u128); + + const CLOCK_ID: wasi::Userdata = 0x0123_45678; + + let clock = wasi::raw::__wasi_subscription_u_clock_t { + identifier: CLOCK_ID, + clock_id: wasi::CLOCK_MONOTONIC, + timeout: nanos as u64, + precision: 0, + flags: 0, + }; + + let in_ = [wasi::Subscription { + userdata: 0, + type_: wasi::EVENTTYPE_CLOCK, + u: wasi::raw::__wasi_subscription_u { clock: clock }, + }]; + let (res, event) = unsafe { + let mut out: [wasi::Event; 1] = mem::zeroed(); + let res = wasi::poll_oneoff(&in_, &mut out); + (res, out[0]) + }; + match (res, event) { + (Ok(1), wasi::Event { + userdata: CLOCK_ID, + error: 0, + type_: wasi::EVENTTYPE_CLOCK, + .. + }) => {} + _ => panic!("thread::sleep(): unexpected result of poll_oneoff"), } } diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs index 3f14c80928c..4394a22f9c2 100644 --- a/src/libstd/sys/wasi/time.rs +++ b/src/libstd/sys/wasi/time.rs @@ -1,7 +1,5 @@ use crate::time::Duration; -use crate::mem; -use crate::sys::cvt_wasi; -use libc; +use ::wasi::wasi_unstable as wasi; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -12,23 +10,19 @@ pub struct SystemTime(Duration); pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); fn current_time(clock: u32) -> Duration { - unsafe { - let mut ts = mem::zeroed(); - cvt_wasi(libc::__wasi_clock_time_get( - clock, - 1, // precision... seems ignored though? - &mut ts, - )).unwrap(); - Duration::new( - (ts / 1_000_000_000) as u64, - (ts % 1_000_000_000) as u32, - ) - } + let ts = wasi::clock_time_get( + clock, + 1, // precision... seems ignored though? + ).unwrap(); + Duration::new( + (ts / 1_000_000_000) as u64, + (ts % 1_000_000_000) as u32, + ) } impl Instant { pub fn now() -> Instant { - Instant(current_time(libc::__WASI_CLOCK_MONOTONIC)) + Instant(current_time(wasi::CLOCK_MONOTONIC)) } pub const fn zero() -> Instant { @@ -54,10 +48,10 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(current_time(libc::__WASI_CLOCK_REALTIME)) + SystemTime(current_time(wasi::CLOCK_REALTIME)) } - pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime { + pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { SystemTime(Duration::from_nanos(ts)) } diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index b3c77b86995..8279e5280e9 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -1,7 +1,6 @@ use crate::ffi::OsString; use crate::marker::PhantomData; use crate::vec; -use crate::sys::ArgsSysCall; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { // On wasm these should always be null, so there's nothing for us to do here @@ -11,9 +10,8 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { - let v = ArgsSysCall::perform(); Args { - iter: v.into_iter(), + iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData, } } diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index 56cbafcfdb8..de0bb38dc31 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -15,11 +15,6 @@ //! guaranteed to be a runtime error! use crate::os::raw::c_char; -use crate::ptr; -use crate::sys::os_str::Buf; -use crate::sys_common::{AsInner, FromInner}; -use crate::ffi::{OsString, OsStr}; -use crate::time::Duration; pub mod alloc; pub mod args; @@ -89,7 +84,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - ExitSysCall::perform(1) + crate::arch::wasm32::unreachable() } // We don't have randomness yet, but I totally used a random number generator to @@ -100,218 +95,3 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } - -// Implement a minimal set of system calls to enable basic IO -pub enum SysCallIndex { - Read = 0, - Write = 1, - Exit = 2, - Args = 3, - GetEnv = 4, - SetEnv = 5, - Time = 6, -} - -#[repr(C)] -pub struct ReadSysCall { - fd: usize, - ptr: *mut u8, - len: usize, - result: usize, -} - -impl ReadSysCall { - pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { - let mut call_record = ReadSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { - call_record.result - } else { - 0 - } - } -} - -#[repr(C)] -pub struct WriteSysCall { - fd: usize, - ptr: *const u8, - len: usize, -} - -impl WriteSysCall { - pub fn perform(fd: usize, buffer: &[u8]) { - let mut call_record = WriteSysCall { - fd, - len: buffer.len(), - ptr: buffer.as_ptr() - }; - unsafe { syscall(SysCallIndex::Write, &mut call_record); } - } -} - -#[repr(C)] -pub struct ExitSysCall { - code: usize, -} - -impl ExitSysCall { - pub fn perform(code: usize) -> ! { - let mut call_record = ExitSysCall { - code - }; - unsafe { - syscall(SysCallIndex::Exit, &mut call_record); - crate::intrinsics::abort(); - } - } -} - -fn receive_buffer<E, F: FnMut(&mut [u8]) -> Result<usize, E>>(estimate: usize, mut f: F) - -> Result<Vec<u8>, E> -{ - let mut buffer = vec![0; estimate]; - loop { - let result = f(&mut buffer)?; - if result <= buffer.len() { - buffer.truncate(result); - break; - } - buffer.resize(result, 0); - } - Ok(buffer) -} - -#[repr(C)] -pub struct ArgsSysCall { - ptr: *mut u8, - len: usize, - result: usize -} - -impl ArgsSysCall { - pub fn perform() -> Vec<OsString> { - receive_buffer(1024, |buffer| -> Result<usize, !> { - let mut call_record = ArgsSysCall { - len: buffer.len(), - ptr: buffer.as_mut_ptr(), - result: 0 - }; - if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { - Ok(call_record.result) - } else { - Ok(0) - } - }) - .unwrap() - .split(|b| *b == 0) - .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) - .collect() - } -} - -#[repr(C)] -pub struct GetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *mut u8, - value_len: usize, - result: usize -} - -impl GetEnvSysCall { - pub fn perform(key: &OsStr) -> Option<OsString> { - let key_buf = &AsInner::as_inner(key).inner; - receive_buffer(64, |buffer| { - let mut call_record = GetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: buffer.len(), - value_ptr: buffer.as_mut_ptr(), - result: !0usize - }; - if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { - if call_record.result == !0usize { - Err(()) - } else { - Ok(call_record.result) - } - } else { - Err(()) - } - }).ok().map(|s| { - FromInner::from_inner(Buf { inner: s }) - }) - } -} - -#[repr(C)] -pub struct SetEnvSysCall { - key_ptr: *const u8, - key_len: usize, - value_ptr: *const u8, - value_len: usize -} - -impl SetEnvSysCall { - pub fn perform(key: &OsStr, value: Option<&OsStr>) { - let key_buf = &AsInner::as_inner(key).inner; - let value_buf = value.map(|v| &AsInner::as_inner(v).inner); - let mut call_record = SetEnvSysCall { - key_len: key_buf.len(), - key_ptr: key_buf.as_ptr(), - value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), - value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) - }; - unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } - } -} - -pub enum TimeClock { - Monotonic = 0, - System = 1, -} - -#[repr(C)] -pub struct TimeSysCall { - clock: usize, - secs_hi: usize, - secs_lo: usize, - nanos: usize -} - -impl TimeSysCall { - pub fn perform(clock: TimeClock) -> Duration { - let mut call_record = TimeSysCall { - clock: clock as usize, - secs_hi: 0, - secs_lo: 0, - nanos: 0 - }; - if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { - Duration::new( - ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), - call_record.nanos as u32 - ) - } else { - panic!("Time system call is not implemented by WebAssembly host"); - } - } -} - -unsafe fn syscall<T>(index: SysCallIndex, data: &mut T) -> bool { - #[cfg(feature = "wasm_syscall")] - extern { - #[no_mangle] - fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; - } - - #[cfg(not(feature = "wasm_syscall"))] - unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } - - rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 -} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs index 5d21999a991..890049e8bfa 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/wasm/os.rs @@ -4,7 +4,7 @@ use crate::fmt; use crate::io; use crate::path::{self, PathBuf}; use crate::str; -use crate::sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; +use crate::sys::{unsupported, Void}; pub fn errno() -> i32 { 0 @@ -73,16 +73,16 @@ pub fn env() -> Env { panic!("not supported on web assembly") } -pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { - Ok(GetEnvSysCall::perform(k)) +pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> { + Ok(None) } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, Some(v))) +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown")) } -pub fn unsetenv(k: &OsStr) -> io::Result<()> { - Ok(SetEnvSysCall::perform(k, None)) +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown")) } pub fn temp_dir() -> PathBuf { @@ -94,7 +94,9 @@ pub fn home_dir() -> Option<PathBuf> { } pub fn exit(_code: i32) -> ! { - ExitSysCall::perform(_code as isize as usize) + unsafe { + crate::arch::wasm32::unreachable(); + } } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs index a02e009d953..edf933d10e0 100644 --- a/src/libstd/sys/wasm/process.rs +++ b/src/libstd/sys/wasm/process.rs @@ -4,14 +4,16 @@ use crate::io; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys::{unsupported, Void}; -use crate::sys_common::process::{CommandEnv, DefaultEnvKey}; +use crate::sys_common::process::CommandEnv; + +pub use crate::ffi::OsString as EnvKey; //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// pub struct Command { - env: CommandEnv<DefaultEnvKey> + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -38,7 +40,7 @@ impl Command { pub fn arg(&mut self, _arg: &OsStr) { } - pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index b8899a9c847..5a4e4505e93 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -1,5 +1,4 @@ use crate::io; -use crate::sys::{ReadSysCall, WriteSysCall}; pub struct Stdin; pub struct Stdout; @@ -12,8 +11,8 @@ impl Stdin { } impl io::Read for Stdin { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - Ok(ReadSysCall::perform(0, buf)) + fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { + Ok(0) } } @@ -25,7 +24,6 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - WriteSysCall::perform(1, buf); Ok(buf.len()) } @@ -42,7 +40,6 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - WriteSysCall::perform(2, buf); Ok(buf.len()) } @@ -57,10 +54,6 @@ pub fn is_ebadf(_err: &io::Error) -> bool { true } -pub fn panic_output() -> Option<impl io::Write> { - if cfg!(feature = "wasm_syscall") { - Stderr::new().ok() - } else { - None - } +pub fn panic_output() -> Option<Vec<u8>> { + None } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index 3f71461eea4..dd9ad3760b0 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -1,5 +1,4 @@ use crate::time::Duration; -use crate::sys::{TimeSysCall, TimeClock}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); @@ -11,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - Instant(TimeSysCall::perform(TimeClock::Monotonic)) + panic!("time not implemented on wasm32-unknown-unknown") } pub const fn zero() -> Instant { @@ -37,7 +36,7 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime(TimeSysCall::perform(TimeClock::System)) + panic!("time not implemented on wasm32-unknown-unknown") } pub fn sub_time(&self, other: &SystemTime) diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 05e0ca67064..8658deb8546 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -19,7 +19,7 @@ use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::sys_common::process::{CommandEnv, EnvKey}; +use crate::sys_common::process::CommandEnv; use crate::borrow::Borrow; use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; @@ -30,30 +30,28 @@ use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[doc(hidden)] -pub struct WindowsEnvKey(OsString); +pub struct EnvKey(OsString); -impl From<OsString> for WindowsEnvKey { +impl From<OsString> for EnvKey { fn from(k: OsString) -> Self { let mut buf = k.into_inner().into_inner(); buf.make_ascii_uppercase(); - WindowsEnvKey(FromInner::from_inner(FromInner::from_inner(buf))) + EnvKey(FromInner::from_inner(FromInner::from_inner(buf))) } } -impl From<WindowsEnvKey> for OsString { - fn from(k: WindowsEnvKey) -> Self { k.0 } +impl From<EnvKey> for OsString { + fn from(k: EnvKey) -> Self { k.0 } } -impl Borrow<OsStr> for WindowsEnvKey { +impl Borrow<OsStr> for EnvKey { fn borrow(&self) -> &OsStr { &self.0 } } -impl AsRef<OsStr> for WindowsEnvKey { +impl AsRef<OsStr> for EnvKey { fn as_ref(&self) -> &OsStr { &self.0 } } -impl EnvKey for WindowsEnvKey {} - fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> { if str.as_ref().encode_wide().any(|b| b == 0) { @@ -66,7 +64,7 @@ fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> { pub struct Command { program: OsString, args: Vec<OsString>, - env: CommandEnv<WindowsEnvKey>, + env: CommandEnv, cwd: Option<OsString>, flags: u32, detach: bool, // not currently exposed in std::process @@ -110,7 +108,7 @@ impl Command { pub fn arg(&mut self, arg: &OsStr) { self.args.push(arg.to_os_string()) } - pub fn env_mut(&mut self) -> &mut CommandEnv<WindowsEnvKey> { + pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env } pub fn cwd(&mut self, dir: &OsStr) { @@ -498,7 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> { } } -fn make_envp(maybe_env: Option<BTreeMap<WindowsEnvKey, OsString>>) +fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>) -> io::Result<(*mut c_void, Vec<u16>)> { // On Windows we pass an "environment block" which is not a char**, but // rather a concatenation of null-terminated k=v\0 sequences, with a final |
