Skip to content
Merged
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: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@
#![feature(doc_masked)]
#![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)]
#![feature(exact_div)]
#![feature(f16)]
#![feature(f128)]
#![feature(ffi_const)]
Expand Down
25 changes: 19 additions & 6 deletions library/std/src/sys/paths/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,18 +234,31 @@ pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let mut mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, libc::getpid(), libc::KERN_PROC_ARGV];

@workingjubilee workingjubilee Jun 20, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Studying https://man.openbsd.org/sysctl.2#KERN_PROC_ARGS

...So uh is there a reason, since we have to make two sysctl calls, that we don't just ask for KERN_PROC_NARGV the first time?

...though "KERN_PROC_NARGV and KERN_PROC_NENV return the number of elements as an int in the argv or env array." has got to be the most curious phrasing possible for that.

View changes since the review

let mib = mib.as_mut_ptr();
let mut argv_len = 0;
cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_len, ptr::null_mut(), 0))?;
let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize);
cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?;
argv.set_len(argv_len as usize);

// 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[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
if argv0.iter().any(|b| *b == b'/') {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess technically we should FCP this breakage, let me nominate for libs-api to decide.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We discussed this in the @rust-lang/libs-api meeting and consider this a bug fix, not something that needs an FCP. There's no reason to check for a leading ., this doesn't determine whether a string represents a relative or absolute path.

// 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)))
}
}
Expand Down
Loading