summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorNikita Baksalyar <nikita.baksalyar@gmail.com>2016-01-21 19:30:22 +0300
committerNikita Baksalyar <nikita.baksalyar@gmail.com>2016-01-31 18:57:26 +0300
commitf189d7a6937c063f9592136a39c836b17c008a93 (patch)
treea31b16fa2af96d112a2e470d7a169b460d961efb /src/libstd/sys
parent9041b930585806b948b4cc68933047ffdc96f6f9 (diff)
downloadrust-f189d7a6937c063f9592136a39c836b17c008a93.tar.gz
rust-f189d7a6937c063f9592136a39c836b17c008a93.zip
Add Illumos support
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.rs52
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/os.rs62
-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, 127 insertions, 24 deletions
diff --git a/src/libstd/sys/common/args.rs b/src/libstd/sys/common/args.rs
index 4cfddb036e9..f17a6d5a4b8 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 = "sunos"))]
 mod imp {
     use prelude::v1::*;
 
diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs
index 179a27a2ec8..d699a5be090 100644
--- a/src/libstd/sys/common/libunwind.rs
+++ b/src/libstd/sys/common/libunwind.rs
@@ -102,6 +102,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
 
 #[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")),
                target_os = "freebsd",
+               target_os = "sunos",
                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..1aeed306aa5 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 = "sunos")))]
     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 = "sunos"))]
     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 d2d2ce35d84..694aff6bbec 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -14,8 +14,7 @@ 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;
@@ -25,6 +24,8 @@ use sys::platform::raw;
 use sys::{cvt, cvt_r};
 use sys_common::{AsInner, FromInner};
 use vec::Vec;
+#[cfg(target_os = "sunos")]
+use core_collections::borrow::ToOwned;
 
 pub struct File(FileDesc);
 
@@ -46,6 +47,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 = "sunos")]
+    name: Arc<Vec<u8>>
 }
 
 #[derive(Clone)]
@@ -132,6 +139,32 @@ impl FromInner<raw::mode_t> for FilePermissions {
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
+    #[cfg(target_os = "sunos")]
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        unsafe {
+            loop {
+                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: Arc::new(::slice::from_raw_parts(name as *const u8,
+                                                           namelen as usize).to_owned()),
+                    root: self.root.clone()
+                };
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_os = "sunos"))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             let mut ret = DirEntry {
@@ -140,7 +173,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 +207,12 @@ impl DirEntry {
         lstat(&self.path())
     }
 
+    #[cfg(target_os = "sunos")]
+    pub fn file_type(&self) -> io::Result<FileType> {
+        stat(&self.path()).map(|m| m.file_type())
+    }
+
+    #[cfg(not(target_os = "sunos"))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
             libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -189,7 +228,8 @@ impl DirEntry {
 
     #[cfg(any(target_os = "macos",
               target_os = "ios",
-              target_os = "linux"))]
+              target_os = "linux",
+              target_os = "sunos"))]
     pub fn ino(&self) -> raw::ino_t {
         self.entry.d_ino
     }
@@ -234,6 +274,10 @@ impl DirEntry {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
         }
     }
+    #[cfg(target_os = "sunos")]
+    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..635a885fa43 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 = "sunos")]     pub use os::sunos 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..e77cd65edde 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 = "sunos", link_name = "___errno")]
         #[cfg_attr(target_os = "dragonfly", link_name = "__dfly_error")]
         #[cfg_attr(any(target_os = "macos",
                        target_os = "ios",
@@ -257,6 +258,28 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(any(target_os = "sunos"))]
+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();
+            if filename[0] == b'/' {
+                Ok(PathBuf::from(<OsStr as OsStrExt>::from_bytes(filename)))
+            } else {
+                // Prepend current working directory to the path if
+                // it doesn't contain an absolute pathname.
+                return getcwd().map(|cwd| cwd.join(<OsStr as OsStrExt>::from_bytes(filename)))
+            }
+        }
+    }
+}
+
 pub struct Args {
     iter: vec::IntoIter<OsString>,
     _dont_send_or_sync_me: *mut (),
@@ -359,6 +382,7 @@ pub fn args() -> Args {
           target_os = "bitrig",
           target_os = "netbsd",
           target_os = "openbsd",
+          target_os = "sunos",
           target_os = "nacl"))]
 pub fn args() -> Args {
     use sys_common;
@@ -481,6 +505,28 @@ pub fn home_dir() -> Option<PathBuf> {
         fallback()
     }).map(PathBuf::from);
 
+    #[cfg(not(target_os = "sunos"))]
+    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 = "sunos")]
+    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(()) }
+    }
+
     #[cfg(any(target_os = "android",
               target_os = "ios",
               target_os = "nacl"))]
@@ -497,16 +543,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 4a91cece143..000fa097e10 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -93,7 +93,7 @@ fn os2c(s: &OsStr) -> CString {
 pub struct ExitStatus(c_int);
 
 #[cfg(any(target_os = "linux", target_os = "android",
-          target_os = "nacl"))]
+          target_os = "nacl", target_os = "sunos"))]
 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 c7614db3299..31f37f31578 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 = "sunos",
           all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd"))]
 mod imp {
@@ -167,6 +168,7 @@ mod imp {
               target_os = "bitrig",
               target_os = "dragonfly",
               target_os = "freebsd",
+              target_os = "sunos",
               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..49d5832f037 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 = "sunos")))]
 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 = "sunos"))]
+    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 = "sunos")))]
 #[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 = "sunos"))]
 #[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 = "sunos"))]
     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 = "sunos")]
+    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 -