Skip to content

Commit e360f70

Browse files
committed
Fix current_exe() on DragonFly
The method using procfs did only work in case procfs is mounted, which we cannot expect, especially as procfs is deprecated on DragonFly. Starting with DragonFly 4.6.1 the sysctl method works correctly, so try sysctl first, and if it returns a path including a ":" (which is an invalid path), try to read from procfs before giving up.
1 parent 8a4641b commit e360f70

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

src/libstd/sys/unix/os.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,44 @@ pub fn current_exe() -> io::Result<PathBuf> {
218218
}
219219
}
220220

221+
// Since DragonFly 4.6.1 (commit [1]), the "kern.proc.pathname" sysctl works "correctly", i.e. it
222+
// does not return paths including a ":" (see [2]). The sysctl has now the same output as reading
223+
// from "/proc/curproc/file". As procfs is deprecated on DragonFly and not guaranteed to be
224+
// mounted, the sysctl is the preferred method. For older versions of DragonFly, we fall back to
225+
// the procfs method. We determine an older version by inspecting the returned path. If it contains
226+
// an ":", we try the procfs method.
227+
//
228+
// [1]: https://gitweb.dragonflybsd.org/dragonfly.git/commit/726f7ca07e193db73635e9c4e24e40c96087d6d9
229+
// [2]: https://gist.github.com/mneumann/a2f6b6a0a03935b561d6185872a4b222
221230
#[cfg(target_os = "dragonfly")]
222231
pub fn current_exe() -> io::Result<PathBuf> {
232+
unsafe {
233+
let mut mib = [libc::CTL_KERN as c_int,
234+
libc::KERN_PROC as c_int,
235+
libc::KERN_PROC_PATHNAME as c_int,
236+
-1 as c_int];
237+
let mut sz: libc::size_t = 0;
238+
cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
239+
ptr::null_mut(), &mut sz, ptr::null_mut(),
240+
0 as libc::size_t))?;
241+
if sz == 0 {
242+
return Err(io::Error::last_os_error())
243+
}
244+
let mut v: Vec<u8> = Vec::with_capacity(sz as usize);
245+
cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
246+
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
247+
ptr::null_mut(), 0 as libc::size_t))?;
248+
if sz == 0 {
249+
return Err(io::Error::last_os_error());
250+
}
251+
v.set_len(sz as usize - 1); // chop off trailing NUL
252+
if !v.contains(&b':') {
253+
// This is a valid path without a ":"
254+
return Ok(PathBuf::from(OsString::from_vec(v)));
255+
}
256+
}
257+
258+
// Fall back to procfs
223259
::fs::read_link("/proc/curproc/file")
224260
}
225261

0 commit comments

Comments
 (0)