about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/args.rs3
-rw-r--r--src/libstd/sys/common/libunwind.rs1
-rw-r--r--src/libstd/sys/unix/fd.rs4
-rw-r--r--src/libstd/sys/unix/fs.rs56
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/os.rs64
-rw-r--r--src/libstd/sys/unix/process.rs2
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs2
-rw-r--r--src/libstd/sys/unix/thread.rs24
9 files changed, 132 insertions, 25 deletions
diff --git a/src/libstd/sys/common/args.rs b/src/libstd/sys/common/args.rs
index 4cfddb036e9..4600983eb3b 100644
--- a/src/libstd/sys/common/args.rs
+++ b/src/libstd/sys/common/args.rs
@@ -38,7 +38,8 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
           target_os = "dragonfly",
           target_os = "bitrig",
           target_os = "netbsd",
-          target_os = "openbsd"))]
+          target_os = "openbsd",
+          target_os = "solaris"))]
 mod imp {
     use prelude::v1::*;
 
diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs
index f44a8cb21e9..956f6005f1c 100644
--- a/src/libstd/sys/common/libunwind.rs
+++ b/src/libstd/sys/common/libunwind.rs
@@ -101,6 +101,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
 
 #[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")),
                target_os = "freebsd",
+               target_os = "solaris",
                all(target_os = "linux", target_env = "musl", not(target_arch = "x86_64"))),
            link(name = "gcc_s"))]
 #[cfg_attr(all(target_os = "linux", target_env = "musl", target_arch = "x86_64", not(test)),
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index e09f4ca27bc..94775341c38 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -50,14 +50,14 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
-    #[cfg(not(target_env = "newlib"))]
+    #[cfg(not(any(target_env = "newlib", target_os = "solaris")))]
     pub fn set_cloexec(&self) {
         unsafe {
             let ret = libc::ioctl(self.fd, libc::FIOCLEX);
             debug_assert_eq!(ret, 0);
         }
     }
-    #[cfg(target_env = "newlib")]
+    #[cfg(any(target_env = "newlib", target_os = "solaris"))]
     pub fn set_cloexec(&self) {
         unsafe {
             let previous = libc::fcntl(self.fd, libc::F_GETFD);
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 91931811234..f5d03cad657 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
 use io::prelude::*;
 use os::unix::prelude::*;
 
 use ffi::{CString, CStr, OsString, OsStr};
 use fmt;
 use io::{self, Error, ErrorKind, SeekFrom};
-use libc::{dirent, readdir_r};
-use libc::{self, c_int, off_t, mode_t};
+use libc::{self, dirent, c_int, off_t, mode_t};
 use mem;
 use path::{Path, PathBuf};
 use ptr;
@@ -24,7 +24,6 @@ use sys::fd::FileDesc;
 use sys::platform::raw;
 use sys::{cvt, cvt_r};
 use sys_common::{AsInner, FromInner};
-use vec::Vec;
 
 pub struct File(FileDesc);
 
@@ -46,6 +45,12 @@ unsafe impl Sync for Dir {}
 pub struct DirEntry {
     entry: dirent,
     root: Arc<PathBuf>,
+    // We need to store an owned copy of the directory name
+    // on Solaris because a) it uses a zero-length array to
+    // store the name, b) its lifetime between readdir calls
+    // is not guaranteed.
+    #[cfg(target_os = "solaris")]
+    name: Box<[u8]>
 }
 
 #[derive(Clone)]
@@ -132,6 +137,36 @@ impl FromInner<raw::mode_t> for FilePermissions {
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
+    #[cfg(target_os = "solaris")]
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        unsafe {
+            loop {
+                // Although readdir_r(3) would be a correct function to use here because
+                // 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.
+                let entry_ptr = libc::readdir(self.dirp.0);
+                if entry_ptr.is_null() {
+                    return None
+                }
+
+                let name = (*entry_ptr).d_name.as_ptr();
+                let namelen = libc::strlen(name) as usize;
+
+                let ret = DirEntry {
+                    entry: *entry_ptr,
+                    name: ::slice::from_raw_parts(name as *const u8,
+                                                  namelen as usize).to_owned().into_boxed_slice(),
+                    root: self.root.clone()
+                };
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_os = "solaris"))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             let mut ret = DirEntry {
@@ -140,7 +175,7 @@ impl Iterator for ReadDir {
             };
             let mut entry_ptr = ptr::null_mut();
             loop {
-                if readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                if libc::readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
                     return Some(Err(Error::last_os_error()))
                 }
                 if entry_ptr.is_null() {
@@ -174,6 +209,12 @@ impl DirEntry {
         lstat(&self.path())
     }
 
+    #[cfg(target_os = "solaris")]
+    pub fn file_type(&self) -> io::Result<FileType> {
+        stat(&self.path()).map(|m| m.file_type())
+    }
+
+    #[cfg(not(target_os = "solaris"))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
             libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -189,7 +230,8 @@ impl DirEntry {
 
     #[cfg(any(target_os = "macos",
               target_os = "ios",
-              target_os = "linux"))]
+              target_os = "linux",
+              target_os = "solaris"))]
     pub fn ino(&self) -> raw::ino_t {
         self.entry.d_ino
     }
@@ -228,6 +270,10 @@ impl DirEntry {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
         }
     }
+    #[cfg(target_os = "solaris")]
+    fn name_bytes(&self) -> &[u8] {
+        &*self.name
+    }
 }
 
 impl OpenOptions {
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 2e89becfa67..f8a4bcdecd7 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -25,6 +25,7 @@ use ops::Neg;
 #[cfg(target_os = "nacl")]      pub use os::nacl as platform;
 #[cfg(target_os = "netbsd")]    pub use os::netbsd as platform;
 #[cfg(target_os = "openbsd")]   pub use os::openbsd as platform;
+#[cfg(target_os = "solaris")]   pub use os::solaris as platform;
 
 pub mod backtrace;
 pub mod condvar;
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index c62960d74cb..da770514593 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -45,6 +45,7 @@ pub fn errno() -> i32 {
                        target_os = "android",
                        target_env = "newlib"),
                    link_name = "__errno")]
+        #[cfg_attr(target_os = "solaris", link_name = "___errno")]
         #[cfg_attr(target_os = "dragonfly", link_name = "__dfly_error")]
         #[cfg_attr(any(target_os = "macos",
                        target_os = "ios",
@@ -257,6 +258,30 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(any(target_os = "solaris"))]
+pub fn current_exe() -> io::Result<PathBuf> {
+    extern {
+        fn getexecname() -> *const c_char;
+    }
+    unsafe {
+        let path = getexecname();
+        if path.is_null() {
+            Err(io::Error::last_os_error())
+        } else {
+            let filename = CStr::from_ptr(path).to_bytes();
+            let path = PathBuf::from(<OsStr as OsStrExt>::from_bytes(filename));
+
+            // Prepend a current working directory to the path if
+            // it doesn't contain an absolute pathname.
+            if filename[0] == b'/' {
+                Ok(path)
+            } else {
+                getcwd().map(|cwd| cwd.join(path))
+            }
+        }
+    }
+}
+
 pub struct Args {
     iter: vec::IntoIter<OsString>,
     _dont_send_or_sync_me: *mut (),
@@ -359,6 +384,7 @@ pub fn args() -> Args {
           target_os = "bitrig",
           target_os = "netbsd",
           target_os = "openbsd",
+          target_os = "solaris",
           target_os = "nacl"))]
 pub fn args() -> Args {
     use sys_common;
@@ -489,6 +515,28 @@ pub fn home_dir() -> Option<PathBuf> {
                   target_os = "ios",
                   target_os = "nacl")))]
     unsafe fn fallback() -> Option<OsString> {
+        #[cfg(not(target_os = "solaris"))]
+        unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
+                              buf: &mut Vec<c_char>) -> Option<()> {
+            let mut result = ptr::null_mut();
+            match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
+                                   buf.capacity() as libc::size_t,
+                                   &mut result) {
+                0 if !result.is_null() => Some(()),
+                _ => None
+            }
+        }
+
+        #[cfg(target_os = "solaris")]
+        unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
+                              buf: &mut Vec<c_char>) -> Option<()> {
+            // getpwuid_r semantics is different on Illumos/Solaris:
+            // http://illumos.org/man/3c/getpwuid_r
+            let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
+                                          buf.capacity() as libc::size_t);
+            if result.is_null() { None } else { Some(()) }
+        }
+
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
             n if n < 0 => 512 as usize,
             n => n as usize,
@@ -497,16 +545,14 @@ pub fn home_dir() -> Option<PathBuf> {
         loop {
             let mut buf = Vec::with_capacity(amt);
             let mut passwd: libc::passwd = mem::zeroed();
-            let mut result = ptr::null_mut();
-            match libc::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(),
-                                   buf.capacity() as libc::size_t,
-                                   &mut result) {
-                0 if !result.is_null() => {}
-                _ => return None
+
+            if getpwduid_r(me, &mut passwd, &mut buf).is_some() {
+                let ptr = passwd.pw_dir as *const _;
+                let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
+                return Some(OsStringExt::from_vec(bytes))
+            } else {
+                return None;
             }
-            let ptr = passwd.pw_dir as *const _;
-            let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
-            return Some(OsStringExt::from_vec(bytes))
         }
     }
 }
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 04b39f0851a..3ce2c684f07 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -131,7 +131,7 @@ impl fmt::Debug for Command {
 pub struct ExitStatus(c_int);
 
 #[cfg(any(target_os = "linux", target_os = "android",
-          target_os = "nacl"))]
+          target_os = "nacl", target_os = "solaris"))]
 mod status_imp {
     pub fn WIFEXITED(status: i32) -> bool { (status & 0xff) == 0 }
     pub fn WEXITSTATUS(status: i32) -> i32 { (status >> 8) & 0xff }
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index b5cbcaa44d5..84407b3bee8 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -39,6 +39,7 @@ impl Drop for Handler {
           target_os = "bitrig",
           target_os = "dragonfly",
           target_os = "freebsd",
+          target_os = "solaris",
           all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd"))]
 mod imp {
@@ -179,6 +180,7 @@ mod imp {
               target_os = "bitrig",
               target_os = "dragonfly",
               target_os = "freebsd",
+              target_os = "solaris",
               all(target_os = "netbsd", not(target_vendor = "rumprun")),
               target_os = "openbsd")))]
 mod imp {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 0faa1465c32..277aa5f19f0 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -12,7 +12,7 @@ use prelude::v1::*;
 
 use alloc::boxed::FnBox;
 use cmp;
-#[cfg(not(target_env = "newlib"))]
+#[cfg(not(any(target_env = "newlib", target_os = "solaris")))]
 use ffi::CString;
 use io;
 use libc;
@@ -122,9 +122,9 @@ impl Thread {
                                      carg.as_ptr() as *mut libc::c_void);
         }
     }
-    #[cfg(target_env = "newlib")]
-    pub unsafe fn set_name(_name: &str) {
-        // Newlib has no way to set a thread name.
+    #[cfg(any(target_env = "newlib", target_os = "solaris"))]
+    pub fn set_name(_name: &str) {
+        // Newlib and Illumos has no way to set a thread name.
     }
 
     pub fn sleep(dur: Duration) {
@@ -170,7 +170,8 @@ impl Drop for Thread {
           not(target_os = "macos"),
           not(target_os = "bitrig"),
           not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
-          not(target_os = "openbsd")))]
+          not(target_os = "openbsd"),
+          not(target_os = "solaris")))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     pub unsafe fn current() -> Option<usize> { None }
@@ -182,7 +183,8 @@ pub mod guard {
           target_os = "macos",
           target_os = "bitrig",
           all(target_os = "netbsd", not(target_vendor = "rumprun")),
-          target_os = "openbsd"))]
+          target_os = "openbsd",
+          target_os = "solaris"))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     use prelude::v1::*;
@@ -194,7 +196,8 @@ pub mod guard {
 
     #[cfg(any(target_os = "macos",
               target_os = "bitrig",
-              target_os = "openbsd"))]
+              target_os = "openbsd",
+              target_os = "solaris"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         current().map(|s| s as *mut libc::c_void)
     }
@@ -253,6 +256,13 @@ pub mod guard {
         Some(stackaddr as usize + offset * psize)
     }
 
+    #[cfg(target_os = "solaris")]
+    pub unsafe fn current() -> Option<usize> {
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
+        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
+        Some(current_stack.ss_sp as usize)
+    }
+
     #[cfg(target_os = "macos")]
     pub unsafe fn current() -> Option<usize> {
         Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as libc::size_t -