about summary refs log tree commit diff
path: root/src/libstd/sys/unix/os.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys/unix/os.rs')
-rw-r--r--src/libstd/sys/unix/os.rs62
1 files changed, 53 insertions, 9 deletions
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))
         }
     }
 }