aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/unix
diff options
context:
space:
mode:
authorFenrir <[email protected]>2018-08-19 17:48:00 -0600
committerFenrir <[email protected]>2018-08-19 17:56:18 -0600
commit5d28bfcfd6086c3328837de9695099ea39048d0d (patch)
treea514fde042ff2a504a03305bfe0894ff8cd8d47e /ctr-std/src/sys/unix
parentUpdate for latest nightly 2018-06-09 (#70) (diff)
downloadarchived-ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.tar.xz
archived-ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.zip
Update for nightly-2018-08-18
Diffstat (limited to 'ctr-std/src/sys/unix')
-rw-r--r--ctr-std/src/sys/unix/args.rs19
-rw-r--r--ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs18
-rw-r--r--ctr-std/src/sys/unix/condvar.rs13
-rw-r--r--ctr-std/src/sys/unix/env.rs11
-rw-r--r--ctr-std/src/sys/unix/ext/fs.rs127
-rw-r--r--ctr-std/src/sys/unix/ext/mod.rs1
-rw-r--r--ctr-std/src/sys/unix/ext/net.rs6
-rw-r--r--ctr-std/src/sys/unix/fast_thread_local.rs7
-rw-r--r--ctr-std/src/sys/unix/fs.rs56
-rw-r--r--ctr-std/src/sys/unix/mod.rs1
-rw-r--r--ctr-std/src/sys/unix/mutex.rs9
-rw-r--r--ctr-std/src/sys/unix/os.rs39
-rw-r--r--ctr-std/src/sys/unix/process/process_common.rs6
-rw-r--r--ctr-std/src/sys/unix/rand.rs29
-rw-r--r--ctr-std/src/sys/unix/thread.rs5
-rw-r--r--ctr-std/src/sys/unix/time.rs4
16 files changed, 241 insertions, 110 deletions
diff --git a/ctr-std/src/sys/unix/args.rs b/ctr-std/src/sys/unix/args.rs
index e1c7ffc..c3c033d 100644
--- a/ctr-std/src/sys/unix/args.rs
+++ b/ctr-std/src/sys/unix/args.rs
@@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args {
target_os = "emscripten",
target_os = "haiku",
target_os = "l4re",
- target_os = "fuchsia"))]
+ target_os = "fuchsia",
+ target_os = "hermit"))]
mod imp {
use os::unix::prelude::*;
use ptr;
@@ -79,20 +80,20 @@ mod imp {
static mut ARGC: isize = 0;
static mut ARGV: *const *const u8 = ptr::null();
+ // We never call `ENV_LOCK.init()`, so it is UB to attempt to
+ // acquire this mutex reentrantly!
static LOCK: Mutex = Mutex::new();
pub unsafe fn init(argc: isize, argv: *const *const u8) {
- LOCK.lock();
+ let _guard = LOCK.lock();
ARGC = argc;
ARGV = argv;
- LOCK.unlock();
}
pub unsafe fn cleanup() {
- LOCK.lock();
+ let _guard = LOCK.lock();
ARGC = 0;
ARGV = ptr::null();
- LOCK.unlock();
}
pub fn args() -> Args {
@@ -104,13 +105,11 @@ mod imp {
fn clone() -> Vec<OsString> {
unsafe {
- LOCK.lock();
- let ret = (0..ARGC).map(|i| {
+ let _guard = LOCK.lock();
+ (0..ARGC).map(|i| {
let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
OsStringExt::from_vec(cstr.to_bytes().to_vec())
- }).collect();
- LOCK.unlock();
- return ret
+ }).collect()
}
}
}
diff --git a/ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs b/ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs
index 1b92fc0..6e84156 100644
--- a/ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs
+++ b/ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs
@@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame])
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
@@ -94,14 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
};
- if cx.idx < cx.frames.len() {
- cx.frames[cx.idx] = Frame {
- symbol_addr: symaddr as *mut u8,
- exact_position: ip as *mut u8,
- inline_context: 0,
- };
- cx.idx += 1;
- }
+ 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/ctr-std/src/sys/unix/condvar.rs b/ctr-std/src/sys/unix/condvar.rs
index 4f878d8..2007da7 100644
--- a/ctr-std/src/sys/unix/condvar.rs
+++ b/ctr-std/src/sys/unix/condvar.rs
@@ -41,13 +41,15 @@ impl Condvar {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
- target_os = "android"))]
+ target_os = "android",
+ target_os = "hermit"))]
pub unsafe fn init(&mut self) {}
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
- target_os = "android")))]
+ target_os = "android",
+ target_os = "hermit")))]
pub unsafe fn init(&mut self) {
use mem;
let mut attr: libc::pthread_condattr_t = mem::uninitialized();
@@ -83,7 +85,10 @@ impl Condvar {
// where we configure condition variable to use monotonic clock (instead of
// default system clock). This approach avoids all problems that result
// from changes made to the system time.
- #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
+ #[cfg(not(any(target_os = "macos",
+ target_os = "ios",
+ target_os = "android",
+ target_os = "hermit")))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
use mem;
@@ -113,7 +118,7 @@ impl Condvar {
// This implementation is modeled after libcxx's condition_variable
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
use ptr;
use time::Instant;
diff --git a/ctr-std/src/sys/unix/env.rs b/ctr-std/src/sys/unix/env.rs
index 00cf7ec..ad116c5 100644
--- a/ctr-std/src/sys/unix/env.rs
+++ b/ctr-std/src/sys/unix/env.rs
@@ -172,3 +172,14 @@ pub mod os {
pub const EXE_SUFFIX: &'static str = "";
pub const EXE_EXTENSION: &'static str = "";
}
+
+#[cfg(target_os = "hermit")]
+pub mod os {
+ pub const FAMILY: &'static str = "unix";
+ pub const OS: &'static str = "hermit";
+ pub const DLL_PREFIX: &'static str = "lib";
+ pub const DLL_SUFFIX: &'static str = ".so";
+ pub const DLL_EXTENSION: &'static str = "so";
+ pub const EXE_SUFFIX: &'static str = "";
+ pub const EXE_EXTENSION: &'static str = "";
+}
diff --git a/ctr-std/src/sys/unix/ext/fs.rs b/ctr-std/src/sys/unix/ext/fs.rs
index 4e98101..507e9d8 100644
--- a/ctr-std/src/sys/unix/ext/fs.rs
+++ b/ctr-std/src/sys/unix/ext/fs.rs
@@ -59,6 +59,78 @@ pub trait FileExt {
#[stable(feature = "file_offset", since = "1.15.0")]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+ /// Reads the exact number of byte required to fill `buf` from the given offset.
+ ///
+ /// The offset is relative to the start of the file and thus independent
+ /// from the current cursor.
+ ///
+ /// The current file cursor is not affected by this function.
+ ///
+ /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
+ ///
+ /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
+ /// [`read_at`]: #tymethod.read_at
+ ///
+ /// # Errors
+ ///
+ /// If this function encounters an error of the kind
+ /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
+ /// will continue.
+ ///
+ /// If this function encounters an "end of file" before completely filling
+ /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
+ /// The contents of `buf` are unspecified in this case.
+ ///
+ /// If any other read error is encountered then this function immediately
+ /// returns. The contents of `buf` are unspecified in this case.
+ ///
+ /// If this function returns an error, it is unspecified how many bytes it
+ /// has read, but it will never read more than would be necessary to
+ /// completely fill the buffer.
+ ///
+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+ /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(rw_exact_all_at)]
+ /// use std::io;
+ /// use std::fs::File;
+ /// use std::os::unix::prelude::FileExt;
+ ///
+ /// fn main() -> io::Result<()> {
+ /// let mut buf = [0u8; 8];
+ /// let file = File::open("foo.txt")?;
+ ///
+ /// // We now read exactly 8 bytes from the offset 10.
+ /// file.read_exact_at(&mut buf, 10)?;
+ /// println!("read {} bytes: {:?}", buf.len(), buf);
+ /// Ok(())
+ /// }
+ /// ```
+ #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
+ while !buf.is_empty() {
+ match self.read_at(buf, offset) {
+ Ok(0) => break,
+ Ok(n) => {
+ let tmp = buf;
+ buf = &mut tmp[n..];
+ offset += n as u64;
+ }
+ Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
+ }
+ if !buf.is_empty() {
+ Err(io::Error::new(io::ErrorKind::UnexpectedEof,
+ "failed to fill whole buffer"))
+ } else {
+ Ok(())
+ }
+ }
+
/// Writes a number of bytes starting from a given offset.
///
/// Returns the number of bytes written.
@@ -93,6 +165,61 @@ pub trait FileExt {
/// ```
#[stable(feature = "file_offset", since = "1.15.0")]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+
+ /// Attempts to write an entire buffer starting from a given offset.
+ ///
+ /// The offset is relative to the start of the file and thus independent
+ /// from the current cursor.
+ ///
+ /// The current file cursor is not affected by this function.
+ ///
+ /// This method will continuously call [`write_at`] until there is no more data
+ /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
+ /// returned. This method will not return until the entire buffer has been
+ /// successfully written or such an error occurs. The first error that is
+ /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
+ /// returned.
+ ///
+ /// # Errors
+ ///
+ /// This function will return the first error of
+ /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
+ ///
+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+ /// [`write_at`]: #tymethod.write_at
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(rw_exact_all_at)]
+ /// use std::fs::File;
+ /// use std::io;
+ /// use std::os::unix::prelude::FileExt;
+ ///
+ /// fn main() -> io::Result<()> {
+ /// let file = File::open("foo.txt")?;
+ ///
+ /// // We now write at the offset 10.
+ /// file.write_all_at(b"sushi", 10)?;
+ /// Ok(())
+ /// }
+ /// ```
+ #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+ fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
+ while !buf.is_empty() {
+ match self.write_at(buf, offset) {
+ Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
+ "failed to write whole buffer")),
+ Ok(n) => {
+ buf = &buf[n..];
+ offset += n as u64
+ }
+ Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(())
+ }
}
#[stable(feature = "file_offset", since = "1.15.0")]
diff --git a/ctr-std/src/sys/unix/ext/mod.rs b/ctr-std/src/sys/unix/ext/mod.rs
index c221f7c..88e4237 100644
--- a/ctr-std/src/sys/unix/ext/mod.rs
+++ b/ctr-std/src/sys/unix/ext/mod.rs
@@ -35,6 +35,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(cfg(unix))]
+#![allow(missing_docs)]
pub mod io;
pub mod ffi;
diff --git a/ctr-std/src/sys/unix/ext/net.rs b/ctr-std/src/sys/unix/ext/net.rs
index e277b1a..55f43cc 100644
--- a/ctr-std/src/sys/unix/ext/net.rs
+++ b/ctr-std/src/sys/unix/ext/net.rs
@@ -524,6 +524,9 @@ impl UnixStream {
/// println!("Got error: {:?}", err);
/// }
/// ```
+ ///
+ /// # Platform specific
+ /// On Redox this always returns None.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
@@ -846,6 +849,9 @@ impl UnixListener {
/// println!("Got error: {:?}", err);
/// }
/// ```
+ ///
+ /// # Platform specific
+ /// On Redox this always returns None.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
diff --git a/ctr-std/src/sys/unix/fast_thread_local.rs b/ctr-std/src/sys/unix/fast_thread_local.rs
index 6cdbe5d..c13a0fe 100644
--- a/ctr-std/src/sys/unix/fast_thread_local.rs
+++ b/ctr-std/src/sys/unix/fast_thread_local.rs
@@ -20,7 +20,7 @@
// fallback implementation to use as well.
//
// Due to rust-lang/rust#18804, make sure this is not generic!
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
use libc;
use mem;
@@ -55,11 +55,6 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
_tlv_atexit(dtor, t);
}
-// Just use the thread_local fallback implementation, at least until there's
-// a more direct implementation.
-#[cfg(target_os = "fuchsia")]
-pub use sys_common::thread_local::register_dtor_fallback as register_dtor;
-
pub fn requires_move_before_drop() -> bool {
// The macOS implementation of TLS apparently had an odd aspect to it
// where the pointer we have may be overwritten while this destructor
diff --git a/ctr-std/src/sys/unix/fs.rs b/ctr-std/src/sys/unix/fs.rs
index 7743403..7a89d98 100644
--- a/ctr-std/src/sys/unix/fs.rs
+++ b/ctr-std/src/sys/unix/fs.rs
@@ -25,10 +25,12 @@ use sys_common::{AsInner, FromInner};
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
+#[cfg(any(target_os = "linux", target_os = "emscripten"))]
+use libc::fstatat64;
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
-use libc::{fstatat, dirfd};
+use libc::dirfd;
#[cfg(target_os = "android")]
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64,
+use libc::{stat as stat64, fstat as fstat64, fstatat as fstatat64, lstat as lstat64, lseek64,
dirent as dirent64, open as open64};
#[cfg(not(any(target_os = "linux",
target_os = "emscripten",
@@ -57,7 +59,10 @@ struct InnerReadDir {
}
#[derive(Clone)]
-pub struct ReadDir(Arc<InnerReadDir>);
+pub struct ReadDir {
+ inner: Arc<InnerReadDir>,
+ end_of_stream: bool,
+}
struct Dir(*mut libc::DIR);
@@ -213,7 +218,7 @@ impl fmt::Debug for ReadDir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
// Thus the result will be e g 'ReadDir("/home")'
- fmt::Debug::fmt(&*self.0.root, f)
+ fmt::Debug::fmt(&*self.inner.root, f)
}
}
@@ -229,7 +234,7 @@ impl Iterator for ReadDir {
// 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.0.dirp.0);
+ let entry_ptr = libc::readdir(self.inner.dirp.0);
if entry_ptr.is_null() {
// 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.
@@ -257,6 +262,10 @@ impl Iterator for ReadDir {
#[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ if self.end_of_stream {
+ return None;
+ }
+
unsafe {
let mut ret = DirEntry {
entry: mem::zeroed(),
@@ -264,7 +273,14 @@ impl Iterator for ReadDir {
};
let mut entry_ptr = ptr::null_mut();
loop {
- if readdir64_r(self.0.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+ if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+ if entry_ptr.is_null() {
+ // We encountered an error (which will be returned in this iteration), but
+ // we also reached the end of the directory stream. The `end_of_stream`
+ // flag is enabled to make sure that we return `None` in the next iteration
+ // (instead of looping forever)
+ self.end_of_stream = true;
+ }
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
@@ -287,7 +303,7 @@ impl Drop for Dir {
impl DirEntry {
pub fn path(&self) -> PathBuf {
- self.dir.0.root.join(OsStr::from_bytes(self.name_bytes()))
+ self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
}
pub fn file_name(&self) -> OsString {
@@ -296,13 +312,10 @@ impl DirEntry {
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
pub fn metadata(&self) -> io::Result<FileAttr> {
- let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?;
+ let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- fstatat(fd,
- self.entry.d_name.as_ptr(),
- &mut stat as *mut _ as *mut _,
- libc::AT_SYMLINK_NOFOLLOW)
+ fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
})?;
Ok(FileAttr { stat: stat })
}
@@ -312,12 +325,12 @@ impl DirEntry {
lstat(&self.path())
}
- #[cfg(any(target_os = "solaris", target_os = "haiku"))]
+ #[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
pub fn file_type(&self) -> io::Result<FileType> {
lstat(&self.path()).map(|m| m.file_type())
}
- #[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
+ #[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -339,7 +352,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
- target_os = "fuchsia"))]
+ target_os = "fuchsia",
+ target_os = "hermit"))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
}
@@ -370,7 +384,8 @@ impl DirEntry {
target_os = "linux",
target_os = "emscripten",
target_os = "l4re",
- target_os = "haiku"))]
+ target_os = "haiku",
+ target_os = "hermit"))]
fn name_bytes(&self) -> &[u8] {
unsafe {
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
@@ -692,7 +707,10 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
Err(Error::last_os_error())
} else {
let inner = InnerReadDir { dirp: Dir(ptr), root };
- Ok(ReadDir(Arc::new(inner)))
+ Ok(ReadDir{
+ inner: Arc::new(inner),
+ end_of_stream: false,
+ })
}
}
}
@@ -787,7 +805,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ stat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
@@ -796,7 +814,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ lstat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
diff --git a/ctr-std/src/sys/unix/mod.rs b/ctr-std/src/sys/unix/mod.rs
index c1298e5..c738003 100644
--- a/ctr-std/src/sys/unix/mod.rs
+++ b/ctr-std/src/sys/unix/mod.rs
@@ -28,6 +28,7 @@ use libc;
#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
#[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform;
#[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform;
+#[cfg(all(not(dox), target_os = "hermit"))] pub use os::hermit as platform;
pub use self::rand::hashmap_random_keys;
pub use libc::strlen;
diff --git a/ctr-std/src/sys/unix/mutex.rs b/ctr-std/src/sys/unix/mutex.rs
index 52cf3f9..1d447de 100644
--- a/ctr-std/src/sys/unix/mutex.rs
+++ b/ctr-std/src/sys/unix/mutex.rs
@@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {}
#[allow(dead_code)] // sys isn't exported yet
impl Mutex {
pub const fn new() -> Mutex {
- // Might be moved and address is changing it is better to avoid
- // initialization of potentially opaque OS data before it landed
+ // Might be moved to a different address, so it is better to avoid
+ // initialization of potentially opaque OS data before it landed.
+ // Be very careful using this newly constructed `Mutex`, reentrant
+ // locking is undefined behavior until `init` is called!
Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
}
#[inline]
@@ -49,9 +51,6 @@ impl Mutex {
// references, we instead create the mutex with type
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
// re-lock it from the same thread, thus avoiding undefined behavior.
- //
- // We can't do anything for StaticMutex, but that type is deprecated
- // anyways.
let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
let r = libc::pthread_mutexattr_init(&mut attr);
debug_assert_eq!(r, 0);
diff --git a/ctr-std/src/sys/unix/os.rs b/ctr-std/src/sys/unix/os.rs
index 4c86fdd..f8f0bbd 100644
--- a/ctr-std/src/sys/unix/os.rs
+++ b/ctr-std/src/sys/unix/os.rs
@@ -33,6 +33,8 @@ use sys::fd;
use vec;
const TMPBUF_SZ: usize = 128;
+// We never call `ENV_LOCK.init()`, so it is UB to attempt to
+// acquire this mutex reentrantly!
static ENV_LOCK: Mutex = Mutex::new();
@@ -47,6 +49,7 @@ extern {
target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
+ target_os = "hermit",
target_env = "newlib"),
link_name = "__errno")]
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
@@ -376,7 +379,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
}
}
-#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
+#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
pub fn current_exe() -> io::Result<PathBuf> {
use io::ErrorKind;
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
@@ -409,26 +412,19 @@ pub unsafe fn environ() -> *mut *const *const c_char {
/// environment variables of the current process.
pub fn env() -> Env {
unsafe {
- ENV_LOCK.lock();
+ let _guard = ENV_LOCK.lock();
let mut environ = *environ();
- if environ == ptr::null() {
- ENV_LOCK.unlock();
- panic!("os::env() failure getting env string from OS: {}",
- io::Error::last_os_error());
- }
let mut result = Vec::new();
- while *environ != ptr::null() {
+ while environ != ptr::null() && *environ != ptr::null() {
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
result.push(key_value);
}
environ = environ.offset(1);
}
- let ret = Env {
+ return Env {
iter: result.into_iter(),
_dont_send_or_sync_me: PhantomData,
- };
- ENV_LOCK.unlock();
- return ret
+ }
}
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
@@ -452,15 +448,14 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
// always None as well
let k = CString::new(k.as_bytes())?;
unsafe {
- ENV_LOCK.lock();
+ let _guard = ENV_LOCK.lock();
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
let ret = if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
};
- ENV_LOCK.unlock();
- return Ok(ret)
+ Ok(ret)
}
}
@@ -469,10 +464,8 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
let v = CString::new(v.as_bytes())?;
unsafe {
- ENV_LOCK.lock();
- let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ());
- ENV_LOCK.unlock();
- return ret
+ let _guard = ENV_LOCK.lock();
+ cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
}
}
@@ -480,10 +473,8 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
let nbuf = CString::new(n.as_bytes())?;
unsafe {
- ENV_LOCK.lock();
- let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ());
- ENV_LOCK.unlock();
- return ret
+ let _guard = ENV_LOCK.lock();
+ cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
}
}
@@ -572,7 +563,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> {
// ignoring any extra dot-separated parts. Otherwise return None.
#[cfg(target_env = "gnu")]
fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
- let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
+ let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
match (parsed_ints.next(), parsed_ints.next()) {
(Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)),
_ => None
diff --git a/ctr-std/src/sys/unix/process/process_common.rs b/ctr-std/src/sys/unix/process/process_common.rs
index 6396bb3..77f125f 100644
--- a/ctr-std/src/sys/unix/process/process_common.rs
+++ b/ctr-std/src/sys/unix/process/process_common.rs
@@ -52,7 +52,7 @@ pub struct Command {
uid: Option<uid_t>,
gid: Option<gid_t>,
saw_nul: bool,
- closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
+ closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
@@ -155,12 +155,12 @@ impl Command {
self.gid
}
- pub fn get_closures(&mut self) -> &mut Vec<Box<FnMut() -> io::Result<()> + Send + Sync>> {
+ pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
&mut self.closures
}
pub fn before_exec(&mut self,
- f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
+ f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) {
self.closures.push(f);
}
diff --git a/ctr-std/src/sys/unix/rand.rs b/ctr-std/src/sys/unix/rand.rs
index caa1894..01c0ada 100644
--- a/ctr-std/src/sys/unix/rand.rs
+++ b/ctr-std/src/sys/unix/rand.rs
@@ -183,35 +183,10 @@ mod imp {
mod imp {
#[link(name = "zircon")]
extern {
- fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
- }
-
- fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
- unsafe {
- let mut actual = 0;
- let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
- if status == 0 {
- Ok(actual)
- } else {
- Err(status)
- }
- }
+ fn zx_cprng_draw(buffer: *mut u8, len: usize);
}
pub fn fill_bytes(v: &mut [u8]) {
- let mut buf = v;
- while !buf.is_empty() {
- let ret = getrandom(buf);
- match ret {
- Err(err) => {
- panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
- err, buf.len())
- }
- Ok(actual) => {
- let move_buf = buf;
- buf = &mut move_buf[(actual as usize)..];
- }
- }
- }
+ unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
}
}
diff --git a/ctr-std/src/sys/unix/thread.rs b/ctr-std/src/sys/unix/thread.rs
index 7fdecc9..f3a45d2 100644
--- a/ctr-std/src/sys/unix/thread.rs
+++ b/ctr-std/src/sys/unix/thread.rs
@@ -49,7 +49,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
}
impl Thread {
- pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
+ pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
-> io::Result<Thread> {
let p = box p;
let mut native: libc::pthread_t = mem::zeroed();
@@ -138,7 +138,8 @@ impl Thread {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
- target_os = "emscripten"))]
+ target_os = "emscripten",
+ target_os = "hermit"))]
pub fn set_name(_name: &CStr) {
// Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
}
diff --git a/ctr-std/src/sys/unix/time.rs b/ctr-std/src/sys/unix/time.rs
index 89786eb..0b1fb72 100644
--- a/ctr-std/src/sys/unix/time.rs
+++ b/ctr-std/src/sys/unix/time.rs
@@ -345,9 +345,9 @@ mod inner {
}
}
- #[cfg(not(target_os = "dragonfly"))]
+ #[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
pub type clock_t = libc::c_int;
- #[cfg(target_os = "dragonfly")]
+ #[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
pub type clock_t = libc::c_ulong;
fn now(clock: clock_t) -> Timespec {