From ef1bd087ee8f741972783b0ac7caa41518cca9a9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Jul 2016 21:35:47 -0700 Subject: [PATCH 1/4] std: Fix `Thread::set_name()` for newlib and solaris The `use ffi::CStr` in `unix/thread.rs` was previously guarded, but now all platforms need it for `Thread::set_name()`. Newlib and Solaris do nothing here, as they have no way to set a thread name, but they still define the same method signature. --- src/libstd/sys/unix/thread.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 371319a93d2..1061ca87f64 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -12,7 +12,6 @@ use prelude::v1::*; use alloc::boxed::FnBox; use cmp; -#[cfg(not(any(target_env = "newlib", target_os = "solaris")))] use ffi::CStr; use io; use libc; From 9503b130d1624c47838f1632b9bca3a64e663992 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Jul 2016 21:35:54 -0700 Subject: [PATCH 2/4] std: Fix IPV6 imports for solaris Like BSDs, Solaris maps `IPV6_ADD_MEMBERSHIP` and `IPV6_DROP_MEMBERSHIP` from `IPV6_JOIN_GROUP` and `IPV6_LEAVE_GROUP` respectively. --- src/libstd/sys/common/net.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 8b7af17f92b..442618c55b3 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -25,19 +25,23 @@ use time::Duration; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd"))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris"))] use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd")))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris")))] use sys::net::netc::IPV6_ADD_MEMBERSHIP; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd"))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris"))] use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd")))] + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris")))] use sys::net::netc::IPV6_DROP_MEMBERSHIP; //////////////////////////////////////////////////////////////////////////////// From 726fa9f09f467cd445758ac8b1bbe8a786aadc9b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Jul 2016 21:43:31 -0700 Subject: [PATCH 3/4] libc: fast-forward for solaris `RTLD_DEFAULT` --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index 45d85899e99..b0d62534d48 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 45d85899e99d33e291b2bf3259881b46cc5365d7 +Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb From 79fb5522bd5bf79c7dad7adfd516ad364dff3e9e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Jul 2016 21:43:53 -0700 Subject: [PATCH 4/4] std: clear errno before readdir, then check it (solaris) A `NULL` from `readdir` could be the end of stream or an error. The only way to know is to check `errno`, so it must be set to a known value first, like a 0 that POSIX will never use. This patch adds `set_errno`, uses it to clear the value before calling `readdir`, then checks it again after to see the reason for a `NULL`. --- src/libstd/sys/unix/fs.rs | 8 +++++++- src/libstd/sys/unix/os.rs | 43 +++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0524851df91..fe946ae0ba4 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -205,9 +205,15 @@ impl Iterator for ReadDir { // of the thread safety, on Illumos the readdir(3C) function is safe to use // in threaded applications and it is generally preferred over the // readdir_r(3C) function. + super::os::set_errno(0); let entry_ptr = libc::readdir(self.dirp.0); if entry_ptr.is_null() { - return None + // NULL can mean either the end is reached or an error occurred. + // So we had to clear errno beforehand to check for an error now. + return match super::os::errno() { + 0 => None, + e => Some(Err(Error::from_raw_os_error(e))), + } } let name = (*entry_ptr).d_name.as_ptr(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 21ce6b19ceb..34b36b854f4 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -35,31 +35,40 @@ use vec; const TMPBUF_SZ: usize = 128; static ENV_LOCK: Mutex = Mutex::new(); + +extern { + #[cfg_attr(any(target_os = "linux", target_os = "emscripten"), + link_name = "__errno_location")] + #[cfg_attr(any(target_os = "bitrig", + target_os = "netbsd", + target_os = "openbsd", + target_os = "android", + target_env = "newlib"), + link_name = "__errno")] + #[cfg_attr(target_os = "solaris", link_name = "___errno")] + #[cfg_attr(any(target_os = "macos", + target_os = "ios", + target_os = "freebsd"), + link_name = "__error")] + fn errno_location() -> *mut c_int; +} + /// Returns the platform-specific value of errno #[cfg(not(target_os = "dragonfly"))] pub fn errno() -> i32 { - extern { - #[cfg_attr(any(target_os = "linux", target_os = "emscripten"), - link_name = "__errno_location")] - #[cfg_attr(any(target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "android", - target_env = "newlib"), - link_name = "__errno")] - #[cfg_attr(target_os = "solaris", link_name = "___errno")] - #[cfg_attr(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"), - link_name = "__error")] - fn errno_location() -> *const c_int; - } - unsafe { (*errno_location()) as i32 } } +/// Sets the platform-specific value of errno +#[cfg(target_os = "solaris")] // only needed for readdir so far +pub fn set_errno(e: i32) { + unsafe { + *errno_location() = e as c_int + } +} + #[cfg(target_os = "dragonfly")] pub fn errno() -> i32 { extern {