Skip to content

Commit 935bd76

Browse files
authored
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?
2 parents 3dbbe2f + 79fb552 commit 935bd76

File tree

5 files changed

+41
-23
lines changed

5 files changed

+41
-23
lines changed

src/libstd/sys/common/net.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,23 @@ use time::Duration;
2525

2626
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
2727
target_os = "ios", target_os = "macos",
28-
target_os = "openbsd", target_os = "netbsd"))]
28+
target_os = "openbsd", target_os = "netbsd",
29+
target_os = "solaris"))]
2930
use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
3031
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
3132
target_os = "ios", target_os = "macos",
32-
target_os = "openbsd", target_os = "netbsd")))]
33+
target_os = "openbsd", target_os = "netbsd",
34+
target_os = "solaris")))]
3335
use sys::net::netc::IPV6_ADD_MEMBERSHIP;
3436
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
3537
target_os = "ios", target_os = "macos",
36-
target_os = "openbsd", target_os = "netbsd"))]
38+
target_os = "openbsd", target_os = "netbsd",
39+
target_os = "solaris"))]
3740
use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
3841
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
3942
target_os = "ios", target_os = "macos",
40-
target_os = "openbsd", target_os = "netbsd")))]
43+
target_os = "openbsd", target_os = "netbsd",
44+
target_os = "solaris")))]
4145
use sys::net::netc::IPV6_DROP_MEMBERSHIP;
4246

4347
////////////////////////////////////////////////////////////////////////////////

src/libstd/sys/unix/fs.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,15 @@ impl Iterator for ReadDir {
205205
// of the thread safety, on Illumos the readdir(3C) function is safe to use
206206
// in threaded applications and it is generally preferred over the
207207
// readdir_r(3C) function.
208+
super::os::set_errno(0);
208209
let entry_ptr = libc::readdir(self.dirp.0);
209210
if entry_ptr.is_null() {
210-
return None
211+
// NULL can mean either the end is reached or an error occurred.
212+
// So we had to clear errno beforehand to check for an error now.
213+
return match super::os::errno() {
214+
0 => None,
215+
e => Some(Err(Error::from_raw_os_error(e))),
216+
}
211217
}
212218

213219
let name = (*entry_ptr).d_name.as_ptr();

src/libstd/sys/unix/os.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,37 @@ use vec;
3535
const TMPBUF_SZ: usize = 128;
3636
static ENV_LOCK: Mutex = Mutex::new();
3737

38+
39+
extern {
40+
#[cfg_attr(any(target_os = "linux", target_os = "emscripten"),
41+
link_name = "__errno_location")]
42+
#[cfg_attr(any(target_os = "bitrig",
43+
target_os = "netbsd",
44+
target_os = "openbsd",
45+
target_os = "android",
46+
target_env = "newlib"),
47+
link_name = "__errno")]
48+
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
49+
#[cfg_attr(any(target_os = "macos",
50+
target_os = "ios",
51+
target_os = "freebsd"),
52+
link_name = "__error")]
53+
fn errno_location() -> *mut c_int;
54+
}
55+
3856
/// Returns the platform-specific value of errno
3957
#[cfg(not(target_os = "dragonfly"))]
4058
pub fn errno() -> i32 {
41-
extern {
42-
#[cfg_attr(any(target_os = "linux", target_os = "emscripten"),
43-
link_name = "__errno_location")]
44-
#[cfg_attr(any(target_os = "bitrig",
45-
target_os = "netbsd",
46-
target_os = "openbsd",
47-
target_os = "android",
48-
target_env = "newlib"),
49-
link_name = "__errno")]
50-
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
51-
#[cfg_attr(any(target_os = "macos",
52-
target_os = "ios",
53-
target_os = "freebsd"),
54-
link_name = "__error")]
55-
fn errno_location() -> *const c_int;
59+
unsafe {
60+
(*errno_location()) as i32
5661
}
62+
}
5763

64+
/// Sets the platform-specific value of errno
65+
#[cfg(target_os = "solaris")] // only needed for readdir so far
66+
pub fn set_errno(e: i32) {
5867
unsafe {
59-
(*errno_location()) as i32
68+
*errno_location() = e as c_int
6069
}
6170
}
6271

src/libstd/sys/unix/thread.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use prelude::v1::*;
1212

1313
use alloc::boxed::FnBox;
1414
use cmp;
15-
#[cfg(not(any(target_env = "newlib", target_os = "solaris")))]
1615
use ffi::CStr;
1716
use io;
1817
use libc;

0 commit comments

Comments
 (0)