about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-22 07:23:16 +0000
committerbors <bors@rust-lang.org>2015-12-22 07:23:16 +0000
commit5178449f1c40b8b3a69f71e4db4e745c87b2ba67 (patch)
tree00905b79d27d878a6271b0647925a7c8becc1d05 /src
parent439e1843b9f53a2ad9e83861f47f95227737e998 (diff)
parent2f42ac438ef4bc2773f5ac0a55ae45b08e575b17 (diff)
downloadrust-5178449f1c40b8b3a69f71e4db4e745c87b2ba67.tar.gz
rust-5178449f1c40b8b3a69f71e4db4e745c87b2ba67.zip
Auto merge of #30175 - alexcrichton:less-c-code, r=brson
All these definitions can now be written in Rust, so do so!
Diffstat (limited to 'src')
-rw-r--r--src/liballoc_jemalloc/lib.rs11
-rw-r--r--src/libstd/rtdeps.rs5
-rw-r--r--src/libstd/sys/unix/fs.rs110
-rw-r--r--src/libstd/sys/unix/os.rs67
-rw-r--r--src/libtest/lib.rs41
-rw-r--r--src/rt/rust_android_dummy.c112
-rw-r--r--src/rt/rust_builtin.c470
7 files changed, 154 insertions, 662 deletions
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 413eac3cf79..eaaa9391d31 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -108,3 +108,14 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
     let flags = align_to_flags(align);
     unsafe { je_nallocx(size as size_t, flags) as usize }
 }
+
+// These symbols are used by jemalloc on android but the really old android
+// we're building on doesn't have them defined, so just make sure the symbols
+// are available.
+#[no_mangle]
+#[cfg(target_os = "android")]
+pub extern fn pthread_atfork(_prefork: *mut u8,
+                             _postfork_parent: *mut u8,
+                             _postfork_child: *mut u8) -> i32 {
+    0
+}
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index 8383b3ec189..9b1046f39a7 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -12,11 +12,6 @@
 //! the standard library This varies per-platform, but these libraries are
 //! necessary for running libstd.
 
-// A few small shims in C that haven't been translated to Rust yet
-#[cfg(all(not(test), not(windows)))]
-#[link(name = "rust_builtin", kind = "static")]
-extern {}
-
 // LLVM implements the `frem` instruction as a call to `fmod`, which lives in
 // libm. Hence, we must explicitly link to it.
 //
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index e634c10d8b7..e8575a6c21c 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -14,7 +14,8 @@ use os::unix::prelude::*;
 use ffi::{CString, CStr, OsString, OsStr};
 use fmt;
 use io::{self, Error, ErrorKind, SeekFrom};
-use libc::{self, c_int, off_t, c_char, mode_t};
+use libc::{dirent, readdir_r};
+use libc::{self, c_int, off_t, mode_t};
 use mem;
 use path::{Path, PathBuf};
 use ptr;
@@ -43,7 +44,7 @@ unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
 pub struct DirEntry {
-    buf: Vec<u8>, // actually *mut libc::dirent
+    entry: dirent,
     root: Arc<PathBuf>,
 }
 
@@ -126,32 +127,22 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        extern {
-            fn rust_dirent_t_size() -> libc::size_t;
-        }
-
-        let mut buf: Vec<u8> = Vec::with_capacity(unsafe {
-            rust_dirent_t_size()
-        });
-        let ptr = buf.as_mut_ptr() as *mut libc::dirent;
-
-        let mut entry_ptr = ptr::null_mut();
-        loop {
-            if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
-                return Some(Err(Error::last_os_error()))
-            }
-            if entry_ptr.is_null() {
-                return None
-            }
-
-            let entry = DirEntry {
-                buf: buf,
+        unsafe {
+            let mut ret = DirEntry {
+                entry: mem::zeroed(),
                 root: self.root.clone()
             };
-            if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
-                buf = entry.buf;
-            } else {
-                return Some(Ok(entry))
+            let mut entry_ptr = ptr::null_mut();
+            loop {
+                if readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                    return Some(Err(Error::last_os_error()))
+                }
+                if entry_ptr.is_null() {
+                    return None
+                }
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
             }
         }
     }
@@ -166,7 +157,7 @@ impl Drop for Dir {
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        self.root.join(<OsStr as OsStrExt>::from_bytes(self.name_bytes()))
+        self.root.join(OsStr::from_bytes(self.name_bytes()))
     }
 
     pub fn file_name(&self) -> OsString {
@@ -178,35 +169,64 @@ impl DirEntry {
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        extern {
-            fn rust_dir_get_mode(ptr: *mut libc::dirent) -> c_int;
-        }
-        unsafe {
-            match rust_dir_get_mode(self.dirent()) {
-                -1 => lstat(&self.path()).map(|m| m.file_type()),
-                n => Ok(FileType { mode: n as mode_t }),
-            }
+        match self.entry.d_type {
+            libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
+            libc::DT_FIFO => Ok(FileType { mode: libc::S_IFIFO }),
+            libc::DT_LNK => Ok(FileType { mode: libc::S_IFLNK }),
+            libc::DT_REG => Ok(FileType { mode: libc::S_IFREG }),
+            libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }),
+            libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }),
+            libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }),
+            _ => lstat(&self.path()).map(|m| m.file_type()),
         }
     }
 
+    #[cfg(any(target_os = "macos",
+              target_os = "ios",
+              target_os = "linux"))]
     pub fn ino(&self) -> raw::ino_t {
-        extern {
-            fn rust_dir_get_ino(ptr: *mut libc::dirent) -> raw::ino_t;
-        }
-        unsafe { rust_dir_get_ino(self.dirent()) }
+        self.entry.d_ino
+    }
+
+    #[cfg(target_os = "android")]
+    pub fn ino(&self) -> raw::ino_t {
+        self.entry.d_ino as raw::ino_t
+    }
+
+    #[cfg(any(target_os = "freebsd",
+              target_os = "openbsd",
+              target_os = "bitrig",
+              target_os = "netbsd",
+              target_os = "dragonfly"))]
+    pub fn ino(&self) -> raw::ino_t {
+        self.entry.d_fileno
     }
 
+    #[cfg(any(target_os = "macos",
+              target_os = "ios",
+              target_os = "netbsd"))]
     fn name_bytes(&self) -> &[u8] {
-        extern {
-            fn rust_list_dir_val(ptr: *mut libc::dirent) -> *const c_char;
+        unsafe {
+            ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
+                                    self.entry.d_namlen as usize)
         }
+    }
+    #[cfg(any(target_os = "freebsd",
+              target_os = "dragonfly",
+              target_os = "bitrig",
+              target_os = "openbsd"))]
+    fn name_bytes(&self) -> &[u8] {
         unsafe {
-            CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
+            ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
+                                    self.entry.d_namelen as usize)
         }
     }
-
-    fn dirent(&self) -> *mut libc::dirent {
-        self.buf.as_ptr() as *mut _
+    #[cfg(any(target_os = "android",
+              target_os = "linux"))]
+    fn name_bytes(&self) -> &[u8] {
+        unsafe {
+            CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
+        }
     }
 }
 
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 12b9d6191a0..c62960d74cb 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -38,12 +38,17 @@ static ENV_LOCK: StaticMutex = StaticMutex::new();
 /// Returns the platform-specific value of errno
 pub fn errno() -> i32 {
     extern {
-        #[cfg_attr(any(target_os = "linux", target_os = "android"), link_name = "__errno_location")]
-        #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd",
+        #[cfg_attr(any(target_os = "linux"), link_name = "__errno_location")]
+        #[cfg_attr(any(target_os = "bitrig",
+                       target_os = "netbsd",
+                       target_os = "openbsd",
+                       target_os = "android",
                        target_env = "newlib"),
                    link_name = "__errno")]
         #[cfg_attr(target_os = "dragonfly", link_name = "__dfly_error")]
-        #[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "freebsd"),
+        #[cfg_attr(any(target_os = "macos",
+                       target_os = "ios",
+                       target_os = "freebsd"),
                    link_name = "__error")]
         fn errno_location() -> *const c_int;
     }
@@ -173,17 +178,19 @@ pub fn current_exe() -> io::Result<PathBuf> {
                        libc::KERN_PROC_PATHNAME as c_int,
                        -1 as c_int];
         let mut sz: libc::size_t = 0;
-        let err = libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                               ptr::null_mut(), &mut sz, ptr::null_mut(),
-                               0 as libc::size_t);
-        if err != 0 { return Err(io::Error::last_os_error()); }
-        if sz == 0 { return Err(io::Error::last_os_error()); }
+        try!(cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                              ptr::null_mut(), &mut sz, ptr::null_mut(),
+                              0 as libc::size_t)));
+        if sz == 0 {
+            return Err(io::Error::last_os_error())
+        }
         let mut v: Vec<u8> = Vec::with_capacity(sz as usize);
-        let err = libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                               v.as_mut_ptr() as *mut libc::c_void, &mut sz,
-                               ptr::null_mut(), 0 as libc::size_t);
-        if err != 0 { return Err(io::Error::last_os_error()); }
-        if sz == 0 { return Err(io::Error::last_os_error()); }
+        try!(cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                              v.as_mut_ptr() as *mut libc::c_void, &mut sz,
+                              ptr::null_mut(), 0 as libc::size_t)));
+        if sz == 0 {
+            return Err(io::Error::last_os_error());
+        }
         v.set_len(sz as usize - 1); // chop off trailing NUL
         Ok(PathBuf::from(OsString::from_vec(v)))
     }
@@ -201,22 +208,28 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 pub fn current_exe() -> io::Result<PathBuf> {
-    use sync::StaticMutex;
-    static LOCK: StaticMutex = StaticMutex::new();
-
-    extern {
-        fn rust_current_exe() -> *const c_char;
-    }
-
-    let _guard = LOCK.lock();
-
     unsafe {
-        let v = rust_current_exe();
-        if v.is_null() {
-            Err(io::Error::last_os_error())
+        let mut mib = [libc::CTL_KERN,
+                       libc::KERN_PROC_ARGS,
+                       libc::getpid(),
+                       libc::KERN_PROC_ARGV];
+        let mib = mib.as_mut_ptr();
+        let mut argv_len = 0;
+        try!(cvt(libc::sysctl(mib, 4, 0 as *mut _, &mut argv_len,
+                              0 as *mut _, 0)));
+        let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize);
+        try!(cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _,
+                              &mut argv_len, 0 as *mut _, 0)));
+        argv.set_len(argv_len as usize);
+        if argv[0].is_null() {
+            return Err(io::Error::new(io::ErrorKind::Other,
+                                      "no current exe available"))
+        }
+        let argv0 = CStr::from_ptr(argv[0]).to_bytes();
+        if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
+            ::fs::canonicalize(OsStr::from_bytes(argv0))
         } else {
-            let vec = CStr::from_ptr(v).to_bytes().to_vec();
-            Ok(PathBuf::from(OsString::from_vec(vec)))
+            Ok(PathBuf::from(OsStr::from_bytes(argv0)))
         }
     }
 }
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 20d7c66cf12..a844bdf1351 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -906,10 +906,45 @@ fn get_concurrency() -> usize {
         }
     }
 
-    #[cfg(unix)]
+    #[cfg(any(target_os = "linux",
+              target_os = "macos",
+              target_os = "ios",
+              target_os = "android"))]
     fn num_cpus() -> usize {
-        extern { fn rust_get_num_cpus() -> libc::uintptr_t; }
-        unsafe { rust_get_num_cpus() as usize }
+        unsafe {
+            libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
+        }
+    }
+
+    #[cfg(any(target_os = "freebsd",
+              target_os = "dragonfly",
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "netbsd"))]
+    fn num_cpus() -> usize {
+        let mut cpus: libc::c_uint = 0;
+        let mut CPUS_SIZE = std::mem::size_of_val(&cpus);
+        let mut mib = [libc::CTL_HW, libc::HW_AVAILCPU, 0, 0];
+
+        unsafe {
+            libc::sysctl(mib.as_mut_ptr(), 2,
+                         &mut cpus as *mut _ as *mut _,
+                         &mut CPUS_SIZE as *mut _ as *mut _,
+                         0 as *mut _, 0);
+        }
+        if cpus < 1 {
+            mib[1] = HW_NCPU;
+            unsafe {
+                libc::sysctl(mib.as_mut_ptr(), 2,
+                             &mut cpus as *mut _ as *mut _,
+                             &mut CPUS_SIZE as *mut _ as *mut _,
+                             0 as *mut _, 0);
+            }
+            if cpus < 1 {
+                cpus = 1;
+            }
+        }
+        cpus as usize
     }
 }
 
diff --git a/src/rt/rust_android_dummy.c b/src/rt/rust_android_dummy.c
deleted file mode 100644
index c322dc6706f..00000000000
--- a/src/rt/rust_android_dummy.c
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifdef __ANDROID__
-
-#include "rust_android_dummy.h"
-#include <math.h>
-#include <errno.h>
-
-int backtrace(void **array, int size) { return 0; }
-
-char **backtrace_symbols(void *const *array, int size) { return 0; }
-
-void backtrace_symbols_fd (void *const *array, int size, int fd) {}
-
-volatile int* __errno_location() {
-    return &errno;
-}
-
-float log2f(float f)
-{
-    return logf( f ) / logf( 2 );
-}
-
-double log2( double n )
-{
-    return log( n ) / log( 2 );
-}
-
-double exp10( double x )
-{
-    return pow( 10, x );
-}
-
-void telldir()
-{
-}
-
-void seekdir()
-{
-}
-
-void mkfifo()
-{
-}
-
-void abs()
-{
-}
-
-void labs()
-{
-}
-
-void rand()
-{
-}
-
-void srand()
-{
-}
-
-void atof()
-{
-}
-
-int glob(const char *pattern,
-                    int flags,
-                    int (*errfunc) (const char *epath, int eerrno),
-                    glob_t *pglob)
-{
-    return 0;
-}
-
-void globfree(glob_t *pglob)
-{
-}
-
-int pthread_atfork(void (*prefork)(void),
-                              void (*postfork_parent)(void),
-                              void (*postfork_child)(void))
-{
-    return 0;
-}
-
-int mlockall(int flags)
-{
-    return 0;
-}
-
-int munlockall(void)
-{
-    return 0;
-}
-
-int shm_open(const char *name, int oflag, mode_t mode)
-{
-    return 0;
-}
-
-int shm_unlink(const char *name)
-{
-    return 0;
-}
-
-int posix_madvise(void *addr, size_t len, int advice)
-{
-    return 0;
-}
-
-#endif
diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c
deleted file mode 100644
index c2168d785b9..00000000000
--- a/src/rt/rust_builtin.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#if !defined(_WIN32)
-
-#include <stdint.h>
-#include <time.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-
-#include <dirent.h>
-#include <pthread.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#include <mach/mach_time.h>
-
-#if !(TARGET_OS_IPHONE)
-#include <crt_externs.h>
-#endif
-#endif
-
-char*
-rust_list_dir_val(struct dirent* entry_ptr) {
-    return entry_ptr->d_name;
-}
-
-// Android's struct dirent does have d_type from the very beginning
-// (android-3). _DIRENT_HAVE_D_TYPE is not defined all the way to android-21
-// though...
-#if defined(__ANDROID__)
-# define _DIRENT_HAVE_D_TYPE
-#endif
-
-int
-rust_dir_get_mode(struct dirent* entry_ptr) {
-#if defined(_DIRENT_HAVE_D_TYPE) || defined(__APPLE__)
-    switch (entry_ptr->d_type) {
-        case DT_BLK: return S_IFBLK;
-        case DT_CHR: return S_IFCHR;
-        case DT_FIFO: return S_IFIFO;
-        case DT_LNK: return S_IFLNK;
-        case DT_REG: return S_IFREG;
-        case DT_SOCK: return S_IFSOCK;
-        case DT_DIR: return S_IFDIR;
-    }
-#endif
-    return -1;
-}
-
-ino_t
-rust_dir_get_ino(struct dirent* entry_ptr) {
-    return entry_ptr->d_ino;
-}
-
-DIR*
-rust_opendir(char *dirname) {
-    return opendir(dirname);
-}
-
-int
-rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
-    return readdir_r(dirp, entry, result);
-}
-
-size_t
-rust_dirent_t_size() {
-    return sizeof(struct dirent);
-}
-
-#if defined(__BSD__)
-static int
-get_num_cpus() {
-    /* swiped from http://stackoverflow.com/questions/150355/
-       programmatically-find-the-number-of-cores-on-a-machine */
-
-    unsigned int numCPU;
-    int mib[4];
-    size_t len = sizeof(numCPU);
-
-    /* set the mib for hw.ncpu */
-    mib[0] = CTL_HW;
-    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
-
-    /* get the number of CPUs from the system */
-    sysctl(mib, 2, &numCPU, &len, NULL, 0);
-
-    if( numCPU < 1 ) {
-        mib[1] = HW_NCPU;
-        sysctl( mib, 2, &numCPU, &len, NULL, 0 );
-
-        if( numCPU < 1 ) {
-            numCPU = 1;
-        }
-    }
-    return numCPU;
-}
-#elif defined(__GNUC__)
-static int
-get_num_cpus() {
-    return sysconf(_SC_NPROCESSORS_ONLN);
-}
-#endif
-
-uintptr_t
-rust_get_num_cpus() {
-    return get_num_cpus();
-}
-
-#if defined(__DragonFly__)
-#include <errno.h>
-// In DragonFly __error() is an inline function and as such
-// no symbol exists for it.
-int *__dfly_error(void) { return __error(); }
-#endif
-
-#if defined(__Bitrig__)
-#include <stdio.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <limits.h>
-
-int rust_get_path(void *p, size_t* sz)
-{
-  int mib[4];
-  char *eq = NULL;
-  char *key = NULL;
-  char *val = NULL;
-  char **menv = NULL;
-  size_t maxlen, len;
-  int nenv = 0;
-  int i;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the argv array */
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC_ARGS;
-  mib[2] = getpid();
-  mib[3] = KERN_PROC_ENV;
-
-  /* get the number of bytes needed to get the env */
-  maxlen = 0;
-  if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1)
-    return -1;
-
-  /* allocate the buffer */
-  if ((menv = calloc(maxlen, sizeof(char))) == NULL)
-    return -1;
-
-  /* get the env array */
-  if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1)
-  {
-    free(menv);
-    return -1;
-  }
-
-  mib[3] = KERN_PROC_NENV;
-  len = sizeof(int);
-  /* get the length of env array */
-  if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1)
-  {
-    free(menv);
-    return -1;
-  }
-
-  /* find _ key and resolve the value */
-  for (i = 0; i < nenv; i++)
-  {
-    if ((eq = strstr(menv[i], "=")) == NULL)
-      continue;
-
-    key = menv[i];
-    val = eq + 1;
-    *eq = '\0';
-
-    if (strncmp(key, "PATH", maxlen) != 0)
-      continue;
-
-    if (p == NULL)
-    {
-      /* return the length of the value + NUL */
-      *sz = strnlen(val, maxlen) + 1;
-      free(menv);
-      return 0;
-    }
-    else
-    {
-      /* copy *sz bytes to the output buffer */
-      memcpy(p, val, *sz);
-      free(menv);
-      return 0;
-    }
-  }
-
-  free(menv);
-  return -1;
-}
-
-int rust_get_path_array(void * p, size_t * sz)
-{
-  char *path, *str;
-  char **buf;
-  int i, num;
-  size_t len;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the length of the PATH value */
-  if (rust_get_path(NULL, &len) == -1)
-    return -1;
-
-  if (len == 0)
-    return -1;
-
-  /* allocate the buffer */
-  if ((path = calloc(len, sizeof(char))) == NULL)
-    return -1;
-
-  /* get the PATH value */
-  if (rust_get_path(path, &len) == -1)
-  {
-    free(path);
-    return -1;
-  }
-
-  /* count the number of parts in the PATH */
-  num = 1;
-  for(str = path; *str != '\0'; str++)
-  {
-    if (*str == ':')
-      num++;
-  }
-
-  /* calculate the size of the buffer for the 2D array */
-  len = (num * sizeof(char*) + 1) + strlen(path) + 1;
-
-  if (p == NULL)
-  {
-    free(path);
-    *sz = len;
-    return 0;
-  }
-
-  /* make sure we have enough buffer space */
-  if (*sz < len)
-  {
-    free(path);
-    return -1;
-  }
-
-  /* zero out the buffer */
-  buf = (char**)p;
-  memset(buf, 0, *sz);
-
-  /* copy the data into the right place */
-  str = p + ((num+1) * sizeof(char*));
-  memcpy(str, path, strlen(path));
-
-  /* parse the path into it's parts */
-  for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;}
-  buf[num] = NULL;
-
-  free(path);
-  return 0;
-}
-
-int rust_get_argv_zero(void* p, size_t* sz)
-{
-  int mib[4];
-  char **argv = NULL;
-  size_t len;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the argv array */
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC_ARGS;
-  mib[2] = getpid();
-  mib[3] = KERN_PROC_ARGV;
-
-  /* request KERN_PROC_ARGV size */
-  len = 0;
-  if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1)
-    return -1;
-
-  /* allocate buffer to receive the values */
-  if ((argv = malloc(len)) == NULL)
-    return -1;
-
-  /* get the argv array */
-  if (sysctl(mib, 4, argv, &len, NULL, 0) == -1)
-  {
-    free(argv);
-    return -1;
-  }
-
-  /* get length of argv[0] */
-  len = strnlen(argv[0], len) + 1;
-
-  if (p == NULL)
-  {
-    *sz = len;
-    free(argv);
-    return 0;
-  }
-
-  if (*sz < len)
-  {
-    free(argv);
-    return -1;
-  }
-
-  memcpy(p, argv[0], len);
-  free(argv);
-  return 0;
-}
-
-const char * rust_current_exe()
-{
-  static char *self = NULL;
-  char *argv0;
-  char **paths;
-  size_t sz;
-  int i;
-  /* If `PATH_MAX` is defined on the platform, `realpath` will truncate the
-   * resolved path up to `PATH_MAX`. While this can make the resolution fail if
-   * the executable is placed in a deep path, the usage of a buffer whose
-   * length depends on `PATH_MAX` is still memory safe. */
-  char buf[2*PATH_MAX], exe[PATH_MAX];
-
-  if (self != NULL)
-    return self;
-
-  if (rust_get_argv_zero(NULL, &sz) == -1)
-    return NULL;
-  if ((argv0 = calloc(sz, sizeof(char))) == NULL)
-    return NULL;
-  if (rust_get_argv_zero(argv0, &sz) == -1)
-  {
-    free(argv0);
-    return NULL;
-  }
-
-  /* if argv0 is a relative or absolute path, resolve it with realpath */
-  if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL))
-  {
-    self = realpath(argv0, NULL);
-    free(argv0);
-    return self;
-  }
-
-  /* get the path array */
-  if (rust_get_path_array(NULL, &sz) == -1)
-  {
-    free(argv0);
-    return NULL;
-  }
-  if ((paths = calloc(sz, sizeof(char))) == NULL)
-  {
-    free(argv0);
-    return NULL;
-  }
-  if (rust_get_path_array(paths, &sz) == -1)
-  {
-    free(argv0);
-    free(paths);
-    return NULL;
-  }
-
-  for(i = 0; paths[i] != NULL; i++)
-  {
-    snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0);
-    if (realpath(buf, exe) == NULL)
-      continue;
-
-    if (access(exe, F_OK | X_OK) == -1)
-      continue;
-
-    self = strdup(exe);
-    free(argv0);
-    free(paths);
-    return self;
-  }
-
-  free(argv0);
-  free(paths);
-  return NULL;
-}
-
-#elif defined(__OpenBSD__)
-
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <limits.h>
-
-const char * rust_current_exe() {
-    static char *self = NULL;
-
-    if (self == NULL) {
-        int mib[4];
-        char **argv = NULL;
-        size_t argv_len;
-
-        /* initialize mib */
-        mib[0] = CTL_KERN;
-        mib[1] = KERN_PROC_ARGS;
-        mib[2] = getpid();
-        mib[3] = KERN_PROC_ARGV;
-
-        /* request KERN_PROC_ARGV size */
-        argv_len = 0;
-        if (sysctl(mib, 4, NULL, &argv_len, NULL, 0) == -1)
-            return (NULL);
-
-        /* allocate size */
-        if ((argv = malloc(argv_len)) == NULL)
-            return (NULL);
-
-        /* request KERN_PROC_ARGV */
-        if (sysctl(mib, 4, argv, &argv_len, NULL, 0) == -1) {
-            free(argv);
-            return (NULL);
-        }
-
-        /* get realpath if possible */
-        if ((argv[0] != NULL) && ((*argv[0] == '.') || (*argv[0] == '/')
-                                || (strstr(argv[0], "/") != NULL)))
-
-            self = realpath(argv[0], NULL);
-        else
-            self = NULL;
-
-        /* cleanup */
-        free(argv);
-    }
-
-    return (self);
-}
-
-#endif
-
-#endif // !defined(_WIN32)
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//