Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@
#![feature(doc_masked)]
#![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)]
#![feature(exact_div)]
#![feature(f16)]
#![feature(f128)]
#![feature(ffi_const)]
Expand Down
35 changes: 6 additions & 29 deletions library/std/src/sys/paths/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,37 +253,14 @@ pub fn current_exe() -> io::Result<PathBuf> {

#[cfg(target_os = "openbsd")]
pub fn current_exe() -> io::Result<PathBuf> {
let mut path = vec![0u8; libc::PATH_MAX as usize];
unsafe {
let mut mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, libc::getpid(), libc::KERN_PROC_ARGV];
let mib = mib.as_mut_ptr();

// Determine the required size (in bytes) for the argument array ...
let mut argv_size = 0;
cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_size, ptr::null_mut(), 0))?;

// ... allocate a buffer for it ...
let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap();
let mut argv = Vec::<*const libc::c_char>::with_capacity(argc);

// ... and retrieve the argument array.
cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_size, ptr::null_mut(), 0))?;
let argc = argv_size.div_exact(size_of::<*const libc::c_char>()).unwrap();
argv.set_len(argc);

if argv[0].is_null() {
return Err(io::const_error!(io::ErrorKind::Uncategorized, "no current exe available"));
}
let argv0 = CStr::from_ptr(argv[0]).to_bytes();
if argv0.iter().any(|b| *b == b'/') {
// The program name is path-like, so try to canonicalize it.
crate::fs::canonicalize(OsStr::from_bytes(argv0))
} else {
// The program was probably found in the PATH. Instead of trying to
// find it again (which might not succeed if PATH has changed), just
// return the program name – this function is best-effort anyway.
Ok(PathBuf::from(OsStr::from_bytes(argv0)))
}
cvt(libc::getexecpath(path.as_mut_ptr().cast(), path.len()))?;
// SAFETY: getexecpath(3) NUL-terminates the buffer on success.
let len = CStr::from_ptr(path.as_ptr().cast()).count_bytes();
path.truncate(len);
}
Ok(PathBuf::from(OsString::from_vec(path)))

@catap catap Oct 19, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably I've missed why do we need truncate here. I think it should be as simple as:

    let mut path = vec![0; libc::PATH_MAX as usize];
    unsafe {
        cvt(getexecpath(path.as_mut_ptr(), path.len()))?;
        let path = CStr::from_ptr(path.as_ptr()).to_bytes();
        Ok(PathBuf::from(OsStr::from_bytes(path)))
    }

View changes since the review

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code does two heap allocations instead of just one, see this comment: #163393 (comment)

}

#[cfg(any(
Expand Down
Loading