about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2017-12-02 01:38:54 +0800
committerGitHub <noreply@github.com>2017-12-02 01:38:54 +0800
commit9493d4b95c55a4ed502751170a0d86f9b5e305d8 (patch)
treea497deded4ebcae8e3697af1f6d076df96b9976f /src
parent263eb4d7ef221e075102c76d85bd7b0d874457b2 (diff)
parentccef9696f13b39b619f7b12d770a2908cc2ecdd3 (diff)
downloadrust-9493d4b95c55a4ed502751170a0d86f9b5e305d8.tar.gz
rust-9493d4b95c55a4ed502751170a0d86f9b5e305d8.zip
Rollup merge of #46373 - jakllsch:netbsd-kern_proc_pathname, r=kennytm
NetBSD: add sysctl backend for std::env::current_exe

Use the CTL_KERN.KERN_PROC_ARGS.-1.KERN_PROC_PATHNAME sysctl in
preference over the /proc/curproc/exe symlink.

Additionally, perform more validation of aformentioned symlink.
Particularly on pre-8.x NetBSD this symlink will point to '/' when
accurate information is unavailable.
Diffstat (limited to 'src')
-rw-r--r--src/libstd/sys/unix/os.rs29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 7e965b4b4c5..4f33a2b12fe 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -223,7 +223,34 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(target_os = "netbsd")]
 pub fn current_exe() -> io::Result<PathBuf> {
-    ::fs::read_link("/proc/curproc/exe")
+    fn sysctl() -> io::Result<PathBuf> {
+        unsafe {
+            let mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, -1, libc::KERN_PROC_PATHNAME];
+            let mut path_len: usize = 0;
+            cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+                             ptr::null_mut(), &mut path_len,
+                             ptr::null(), 0))?;
+            if path_len <= 1 {
+                return Err(io::Error::new(io::ErrorKind::Other,
+                           "KERN_PROC_PATHNAME sysctl returned zero-length string"))
+            }
+            let mut path: Vec<u8> = Vec::with_capacity(path_len);
+            cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+                             path.as_ptr() as *mut libc::c_void, &mut path_len,
+                             ptr::null(), 0))?;
+            path.set_len(path_len - 1); // chop off NUL
+            Ok(PathBuf::from(OsString::from_vec(path)))
+        }
+    }
+    fn procfs() -> io::Result<PathBuf> {
+        let curproc_exe = path::Path::new("/proc/curproc/exe");
+        if curproc_exe.is_file() {
+            return ::fs::read_link(curproc_exe);
+        }
+        Err(io::Error::new(io::ErrorKind::Other,
+                           "/proc/curproc/exe doesn't point to regular file."))
+    }
+    sysctl().or_else(|_| procfs())
 }
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]