]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/sys/unix/os.rs
Add support for the Haiku operating system on x86 and x86_64 machines
[rust.git] / src / libstd / sys / unix / os.rs
index c29e87f91c9a7e247471f2c4749e3264e663d572..850c3d52715365aa5ba290565d226526d48a6166 100644 (file)
@@ -12,7 +12,6 @@
 
 #![allow(unused_imports)] // lots of cfg code here
 
-use prelude::v1::*;
 use os::unix::prelude::*;
 
 use error::Error as StdError;
@@ -52,6 +51,7 @@
                    target_os = "ios",
                    target_os = "freebsd"),
                link_name = "__error")]
+    #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
     fn errno_location() -> *mut c_int;
 }
 
@@ -304,6 +304,49 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(target_os = "haiku")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    // Use Haiku's image info functions
+    #[repr(C)]
+    struct image_info {
+        id: i32,
+        type_: i32,
+        sequence: i32,
+        init_order: i32,
+        init_routine: *mut libc::c_void,    // function pointer
+        term_routine: *mut libc::c_void,    // function pointer
+        device: libc::dev_t,
+        node: libc::ino_t,
+        name: [libc::c_char; 1024],         // MAXPATHLEN
+        text: *mut libc::c_void,
+        data: *mut libc::c_void,
+        text_size: i32,
+        data_size: i32,
+        api_version: i32,
+        abi: i32,
+    }
+
+    unsafe {
+        extern {
+            fn _get_next_image_info(team_id: i32, cookie: *mut i32,
+                info: *mut image_info, size: i32) -> i32;
+        }
+
+        let mut info: image_info = mem::zeroed();
+        let mut cookie: i32 = 0;
+        // the executable can be found at team id 0
+        let result = _get_next_image_info(0, &mut cookie, &mut info,
+            mem::size_of::<image_info>() as i32);
+        if result != 0 {
+            use io::ErrorKind;
+            Err(io::Error::new(ErrorKind::Other, "Error getting executable path"))
+        } else {
+            let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
+            Ok(PathBuf::from(OsStr::from_bytes(name)))
+        }
+    }
+}
+
 pub struct Args {
     iter: vec::IntoIter<OsString>,
     _dont_send_or_sync_me: PhantomData<*mut ()>,
@@ -413,7 +456,8 @@ pub fn args() -> Args {
           target_os = "openbsd",
           target_os = "solaris",
           target_os = "nacl",
-          target_os = "emscripten"))]
+          target_os = "emscripten",
+          target_os = "haiku"))]
 pub fn args() -> Args {
     use sys_common;
     let bytes = sys_common::args::clone().unwrap_or(Vec::new());
@@ -585,18 +629,15 @@ unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
             n if n < 0 => 512 as usize,
             n => n as usize,
         };
-        let me = libc::getuid();
-        loop {
-            let mut buf = Vec::with_capacity(amt);
-            let mut passwd: libc::passwd = mem::zeroed();
-
-            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 mut buf = Vec::with_capacity(amt);
+        let mut passwd: libc::passwd = mem::zeroed();
+
+        if getpwduid_r(libc::getuid(), &mut passwd, &mut buf).is_some() {
+            let ptr = passwd.pw_dir as *const _;
+            let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
+            Some(OsStringExt::from_vec(bytes))
+        } else {
+            None
         }
     }
 }