about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorJonathan A. Kollasch <jakllsch@kollasch.net>2017-11-29 11:31:09 -0600
committerJonathan A. Kollasch <jakllsch@kollasch.net>2017-11-30 12:17:44 -0600
commitccef9696f13b39b619f7b12d770a2908cc2ecdd3 (patch)
tree978bfed05020e11d0de2be1108732b5edd28b42b /src/libstd/sys
parent4fa202d23b4c8c81b8ac6cf89cf843d35854d437 (diff)
downloadrust-ccef9696f13b39b619f7b12d770a2908cc2ecdd3.tar.gz
rust-ccef9696f13b39b619f7b12d770a2908cc2ecdd3.zip
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/libstd/sys')
-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"))]