Auto merge of #34776 - cuviper:solaris-readdir, r=alexcrichton
std: fix `readdir` errors for 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 currently only matters for solaris targets, as the other unix platforms are using `readdir_r` with a direct error return indication. However, this is getting deprecated (#34668) so they should all eventually switch to `readdir`. This PR adds `set_errno`, uses it to clear the value before calling `readdir`, then checks it again after to see the reason for a `NULL`. A few other small fixes are included just to get solaris compiling at all. I couldn't get cross-compilation completely going, so I don't have a good way to test this beyond a smoke-test cargo build of std. I'd appreciate input from someone more familiar with solaris -- cc @nbaksalyar?
This commit is contained in:
commit
935bd76367
@ -1 +1 @@
|
||||
Subproject commit 45d85899e99d33e291b2bf3259881b46cc5365d7
|
||||
Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb
|
@ -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;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user