Auto merge of #121101 - GnomedDev:dyn-small-c-string, r=Nilstrieb

Reduce monomorphisation bloat in small_c_string

This is a code path usually next to an FFI call, so taking the `dyn` slowdown for the 1159 llvm-line (fat lto, codegen-units 1, release build) drop in my testing program [t2fanrd](https://github.com/GnomedDev/t2fanrd) is worth it imo.
This commit is contained in:
bors 2024-02-18 22:54:22 +00:00
commit 61223975d4
10 changed files with 64 additions and 60 deletions

View File

@ -15,22 +15,28 @@ const NUL_ERR: io::Error =
io::const_io_error!(io::ErrorKind::InvalidInput, "file name contained an unexpected NUL byte"); io::const_io_error!(io::ErrorKind::InvalidInput, "file name contained an unexpected NUL byte");
#[inline] #[inline]
pub fn run_path_with_cstr<T, F>(path: &Path, f: F) -> io::Result<T> pub fn run_path_with_cstr<T>(path: &Path, f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
where
F: FnOnce(&CStr) -> io::Result<T>,
{
run_with_cstr(path.as_os_str().as_encoded_bytes(), f) run_with_cstr(path.as_os_str().as_encoded_bytes(), f)
} }
#[inline] #[inline]
pub fn run_with_cstr<T, F>(bytes: &[u8], f: F) -> io::Result<T> pub fn run_with_cstr<T>(bytes: &[u8], f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
where // Dispatch and dyn erase the closure type to prevent mono bloat.
F: FnOnce(&CStr) -> io::Result<T>, // See https://github.com/rust-lang/rust/pull/121101.
{
if bytes.len() >= MAX_STACK_ALLOCATION { if bytes.len() >= MAX_STACK_ALLOCATION {
return run_with_cstr_allocating(bytes, f); run_with_cstr_allocating(bytes, f)
} else {
unsafe { run_with_cstr_stack(bytes, f) }
} }
}
/// # Safety
///
/// `bytes` must have a length less than `MAX_STACK_ALLOCATION`.
unsafe fn run_with_cstr_stack<T>(
bytes: &[u8],
f: &dyn Fn(&CStr) -> io::Result<T>,
) -> io::Result<T> {
let mut buf = MaybeUninit::<[u8; MAX_STACK_ALLOCATION]>::uninit(); let mut buf = MaybeUninit::<[u8; MAX_STACK_ALLOCATION]>::uninit();
let buf_ptr = buf.as_mut_ptr() as *mut u8; let buf_ptr = buf.as_mut_ptr() as *mut u8;
@ -47,10 +53,7 @@ where
#[cold] #[cold]
#[inline(never)] #[inline(never)]
fn run_with_cstr_allocating<T, F>(bytes: &[u8], f: F) -> io::Result<T> fn run_with_cstr_allocating<T>(bytes: &[u8], f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
where
F: FnOnce(&CStr) -> io::Result<T>,
{
match CString::new(bytes) { match CString::new(bytes) {
Ok(s) => f(&s), Ok(s) => f(&s),
Err(_) => Err(NUL_ERR), Err(_) => Err(NUL_ERR),

View File

@ -7,7 +7,7 @@ use core::iter::repeat;
#[test] #[test]
fn stack_allocation_works() { fn stack_allocation_works() {
let path = Path::new("abc"); let path = Path::new("abc");
let result = run_path_with_cstr(path, |p| { let result = run_path_with_cstr(path, &|p| {
assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap()); assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap());
Ok(42) Ok(42)
}); });
@ -17,14 +17,14 @@ fn stack_allocation_works() {
#[test] #[test]
fn stack_allocation_fails() { fn stack_allocation_fails() {
let path = Path::new("ab\0"); let path = Path::new("ab\0");
assert!(run_path_with_cstr::<(), _>(path, |_| unreachable!()).is_err()); assert!(run_path_with_cstr::<()>(path, &|_| unreachable!()).is_err());
} }
#[test] #[test]
fn heap_allocation_works() { fn heap_allocation_works() {
let path = repeat("a").take(384).collect::<String>(); let path = repeat("a").take(384).collect::<String>();
let path = Path::new(&path); let path = Path::new(&path);
let result = run_path_with_cstr(path, |p| { let result = run_path_with_cstr(path, &|p| {
assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap()); assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap());
Ok(42) Ok(42)
}); });
@ -36,7 +36,7 @@ fn heap_allocation_fails() {
let mut path = repeat("a").take(384).collect::<String>(); let mut path = repeat("a").take(384).collect::<String>();
path.push('\0'); path.push('\0');
let path = Path::new(&path); let path = Path::new(&path);
assert!(run_path_with_cstr::<(), _>(path, |_| unreachable!()).is_err()); assert!(run_path_with_cstr::<()>(path, &|_| unreachable!()).is_err());
} }
#[bench] #[bench]
@ -44,7 +44,7 @@ fn bench_stack_path_alloc(b: &mut test::Bencher) {
let path = repeat("a").take(383).collect::<String>(); let path = repeat("a").take(383).collect::<String>();
let p = Path::new(&path); let p = Path::new(&path);
b.iter(|| { b.iter(|| {
run_path_with_cstr(p, |cstr| { run_path_with_cstr(p, &|cstr| {
black_box(cstr); black_box(cstr);
Ok(()) Ok(())
}) })
@ -57,7 +57,7 @@ fn bench_heap_path_alloc(b: &mut test::Bencher) {
let path = repeat("a").take(384).collect::<String>(); let path = repeat("a").take(384).collect::<String>();
let p = Path::new(&path); let p = Path::new(&path);
b.iter(|| { b.iter(|| {
run_path_with_cstr(p, |cstr| { run_path_with_cstr(p, &|cstr| {
black_box(cstr); black_box(cstr);
Ok(()) Ok(())
}) })

View File

@ -269,7 +269,7 @@ impl OpenOptions {
impl File { impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
run_path_with_cstr(path, |path| File::open_c(&path, opts)) run_path_with_cstr(path, &|path| File::open_c(&path, opts))
} }
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> { pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
@ -421,7 +421,7 @@ pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
} }
pub fn unlink(path: &Path) -> io::Result<()> { pub fn unlink(path: &Path) -> io::Result<()> {
run_path_with_cstr(path, |path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ())) run_path_with_cstr(path, &|path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ()))
} }
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {

View File

@ -172,7 +172,7 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> { pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is // environment variables with a nul byte can't be set, so their value is
// always None as well // always None as well
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
let _guard = env_read_lock(); let _guard = env_read_lock();
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
@ -190,8 +190,8 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
} }
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
run_with_cstr(v.as_bytes(), |v| { run_with_cstr(v.as_bytes(), &|v| {
let _guard = ENV_LOCK.write(); let _guard = ENV_LOCK.write();
cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
}) })
@ -199,7 +199,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
} }
pub fn unsetenv(n: &OsStr) -> io::Result<()> { pub fn unsetenv(n: &OsStr) -> io::Result<()> {
run_with_cstr(n.as_bytes(), |nbuf| { run_with_cstr(n.as_bytes(), &|nbuf| {
let _guard = ENV_LOCK.write(); let _guard = ENV_LOCK.write();
cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
}) })

View File

@ -1118,7 +1118,7 @@ impl OpenOptions {
impl File { impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
run_path_with_cstr(path, |path| File::open_c(path, opts)) run_path_with_cstr(path, &|path| File::open_c(path, opts))
} }
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> { pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
@ -1394,7 +1394,7 @@ impl DirBuilder {
} }
pub fn mkdir(&self, p: &Path) -> io::Result<()> { pub fn mkdir(&self, p: &Path) -> io::Result<()> {
run_path_with_cstr(p, |p| cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) }).map(|_| ())) run_path_with_cstr(p, &|p| cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) }).map(|_| ()))
} }
pub fn set_mode(&mut self, mode: u32) { pub fn set_mode(&mut self, mode: u32) {
@ -1575,7 +1575,7 @@ impl fmt::Debug for File {
} }
pub fn readdir(path: &Path) -> io::Result<ReadDir> { pub fn readdir(path: &Path) -> io::Result<ReadDir> {
let ptr = run_path_with_cstr(path, |p| unsafe { Ok(libc::opendir(p.as_ptr())) })?; let ptr = run_path_with_cstr(path, &|p| unsafe { Ok(libc::opendir(p.as_ptr())) })?;
if ptr.is_null() { if ptr.is_null() {
Err(Error::last_os_error()) Err(Error::last_os_error())
} else { } else {
@ -1586,27 +1586,27 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
} }
pub fn unlink(p: &Path) -> io::Result<()> { pub fn unlink(p: &Path) -> io::Result<()> {
run_path_with_cstr(p, |p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())) run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()))
} }
pub fn rename(old: &Path, new: &Path) -> io::Result<()> { pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
run_path_with_cstr(old, |old| { run_path_with_cstr(old, &|old| {
run_path_with_cstr(new, |new| { run_path_with_cstr(new, &|new| {
cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
}) })
}) })
} }
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
run_path_with_cstr(p, |p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())) run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()))
} }
pub fn rmdir(p: &Path) -> io::Result<()> { pub fn rmdir(p: &Path) -> io::Result<()> {
run_path_with_cstr(p, |p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())) run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()))
} }
pub fn readlink(p: &Path) -> io::Result<PathBuf> { pub fn readlink(p: &Path) -> io::Result<PathBuf> {
run_path_with_cstr(p, |c_path| { run_path_with_cstr(p, &|c_path| {
let p = c_path.as_ptr(); let p = c_path.as_ptr();
let mut buf = Vec::with_capacity(256); let mut buf = Vec::with_capacity(256);
@ -1635,16 +1635,16 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
} }
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
run_path_with_cstr(original, |original| { run_path_with_cstr(original, &|original| {
run_path_with_cstr(link, |link| { run_path_with_cstr(link, &|link| {
cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
}) })
}) })
} }
pub fn link(original: &Path, link: &Path) -> io::Result<()> { pub fn link(original: &Path, link: &Path) -> io::Result<()> {
run_path_with_cstr(original, |original| { run_path_with_cstr(original, &|original| {
run_path_with_cstr(link, |link| { run_path_with_cstr(link, &|link| {
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] { if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
// VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
@ -1678,7 +1678,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
} }
pub fn stat(p: &Path) -> io::Result<FileAttr> { pub fn stat(p: &Path) -> io::Result<FileAttr> {
run_path_with_cstr(p, |p| { run_path_with_cstr(p, &|p| {
cfg_has_statx! { cfg_has_statx! {
if let Some(ret) = unsafe { try_statx( if let Some(ret) = unsafe { try_statx(
libc::AT_FDCWD, libc::AT_FDCWD,
@ -1697,7 +1697,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
} }
pub fn lstat(p: &Path) -> io::Result<FileAttr> { pub fn lstat(p: &Path) -> io::Result<FileAttr> {
run_path_with_cstr(p, |p| { run_path_with_cstr(p, &|p| {
cfg_has_statx! { cfg_has_statx! {
if let Some(ret) = unsafe { try_statx( if let Some(ret) = unsafe { try_statx(
libc::AT_FDCWD, libc::AT_FDCWD,
@ -1716,7 +1716,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
} }
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> { pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
let r = run_path_with_cstr(p, |path| unsafe { let r = run_path_with_cstr(p, &|path| unsafe {
Ok(libc::realpath(path.as_ptr(), ptr::null_mut())) Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
})?; })?;
if r.is_null() { if r.is_null() {
@ -1879,7 +1879,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
// Opportunistically attempt to create a copy-on-write clone of `from` // Opportunistically attempt to create a copy-on-write clone of `from`
// using `fclonefileat`. // using `fclonefileat`.
if HAS_FCLONEFILEAT.load(Ordering::Relaxed) { if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {
let clonefile_result = run_path_with_cstr(to, |to| { let clonefile_result = run_path_with_cstr(to, &|to| {
cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) }) cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
}); });
match clonefile_result { match clonefile_result {
@ -1925,7 +1925,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
} }
pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
run_path_with_cstr(path, |path| { run_path_with_cstr(path, &|path| {
cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) }) cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })
.map(|_| ()) .map(|_| ())
}) })
@ -1937,7 +1937,7 @@ pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
} }
pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
run_path_with_cstr(path, |path| { run_path_with_cstr(path, &|path| {
cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) }) cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })
.map(|_| ()) .map(|_| ())
}) })
@ -1945,7 +1945,7 @@ pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))] #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
pub fn chroot(dir: &Path) -> io::Result<()> { pub fn chroot(dir: &Path) -> io::Result<()> {
run_path_with_cstr(dir, |dir| cvt(unsafe { libc::chroot(dir.as_ptr()) }).map(|_| ())) run_path_with_cstr(dir, &|dir| cvt(unsafe { libc::chroot(dir.as_ptr()) }).map(|_| ()))
} }
pub use remove_dir_impl::remove_dir_all; pub use remove_dir_impl::remove_dir_all;
@ -2140,7 +2140,7 @@ mod remove_dir_impl {
if attr.file_type().is_symlink() { if attr.file_type().is_symlink() {
crate::fs::remove_file(p) crate::fs::remove_file(p)
} else { } else {
run_path_with_cstr(p, |p| remove_dir_all_recursive(None, &p)) run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p))
} }
} }

View File

@ -186,7 +186,7 @@ pub fn chdir(_p: &path::Path) -> io::Result<()> {
#[cfg(not(target_os = "espidf"))] #[cfg(not(target_os = "espidf"))]
pub fn chdir(p: &path::Path) -> io::Result<()> { pub fn chdir(p: &path::Path) -> io::Result<()> {
let result = run_path_with_cstr(p, |p| unsafe { Ok(libc::chdir(p.as_ptr())) })?; let result = run_path_with_cstr(p, &|p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }
} }
@ -643,7 +643,7 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> { pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is // environment variables with a nul byte can't be set, so their value is
// always None as well // always None as well
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
let _guard = env_read_lock(); let _guard = env_read_lock();
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
@ -661,8 +661,8 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
} }
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
run_with_cstr(v.as_bytes(), |v| { run_with_cstr(v.as_bytes(), &|v| {
let _guard = ENV_LOCK.write(); let _guard = ENV_LOCK.write();
cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
}) })
@ -670,7 +670,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
} }
pub fn unsetenv(n: &OsStr) -> io::Result<()> { pub fn unsetenv(n: &OsStr) -> io::Result<()> {
run_with_cstr(n.as_bytes(), |nbuf| { run_with_cstr(n.as_bytes(), &|nbuf| {
let _guard = ENV_LOCK.write(); let _guard = ENV_LOCK.write();
cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
}) })

View File

@ -698,7 +698,7 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
/// Note that this can fail if `p` doesn't look like it can be opened relative /// Note that this can fail if `p` doesn't look like it can be opened relative
/// to any pre-opened file descriptor. /// to any pre-opened file descriptor.
fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> { fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
run_path_with_cstr(p, |p| { run_path_with_cstr(p, &|p| {
let mut buf = Vec::<u8>::with_capacity(512); let mut buf = Vec::<u8>::with_capacity(512);
loop { loop {
unsafe { unsafe {

View File

@ -95,7 +95,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
} }
pub fn chdir(p: &path::Path) -> io::Result<()> { pub fn chdir(p: &path::Path) -> io::Result<()> {
let result = run_path_with_cstr(p, |p| unsafe { Ok(libc::chdir(p.as_ptr())) })?; let result = run_path_with_cstr(p, &|p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
match result == (0 as libc::c_int) { match result == (0 as libc::c_int) {
true => Ok(()), true => Ok(()),
false => Err(io::Error::last_os_error()), false => Err(io::Error::last_os_error()),
@ -227,7 +227,7 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> { pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is // environment variables with a nul byte can't be set, so their value is
// always None as well // always None as well
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
let _guard = env_read_lock(); let _guard = env_read_lock();
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
@ -245,8 +245,8 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
} }
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
run_with_cstr(k.as_bytes(), |k| { run_with_cstr(k.as_bytes(), &|k| {
run_with_cstr(v.as_bytes(), |v| unsafe { run_with_cstr(v.as_bytes(), &|v| unsafe {
let _guard = env_write_lock(); let _guard = env_write_lock();
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
}) })
@ -254,7 +254,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
} }
pub fn unsetenv(n: &OsStr) -> io::Result<()> { pub fn unsetenv(n: &OsStr) -> io::Result<()> {
run_with_cstr(n.as_bytes(), |nbuf| unsafe { run_with_cstr(n.as_bytes(), &|nbuf| unsafe {
let _guard = env_write_lock(); let _guard = env_write_lock();
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
}) })

View File

@ -199,7 +199,7 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> { fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
init(); init();
run_with_cstr(host.as_bytes(), |c_host| { run_with_cstr(host.as_bytes(), &|c_host| {
let mut hints: c::addrinfo = unsafe { mem::zeroed() }; let mut hints: c::addrinfo = unsafe { mem::zeroed() };
hints.ai_socktype = c::SOCK_STREAM; hints.ai_socktype = c::SOCK_STREAM;
let mut res = ptr::null_mut(); let mut res = ptr::null_mut();

View File

@ -11,8 +11,9 @@ LL | let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode a
= note: inside `std::sys::pal::PLATFORM::cvt_r::<i32, {closure@std::sys::pal::PLATFORM::fs::File::open_c::{closure#0}}>` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::sys::pal::PLATFORM::cvt_r::<i32, {closure@std::sys::pal::PLATFORM::fs::File::open_c::{closure#0}}>` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
= note: inside `std::sys::pal::PLATFORM::fs::File::open_c` at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC = note: inside `std::sys::pal::PLATFORM::fs::File::open_c` at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC = note: inside closure at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC
= note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr::<std::sys::pal::PLATFORM::fs::File, {closure@std::sys::pal::PLATFORM::fs::File::open::{closure#0}}>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr_stack::<std::sys::pal::PLATFORM::fs::File>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC
= note: inside `std::sys::pal::PLATFORM::small_c_string::run_path_with_cstr::<std::sys::pal::PLATFORM::fs::File, {closure@std::sys::pal::PLATFORM::fs::File::open::{closure#0}}>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr::<std::sys::pal::PLATFORM::fs::File>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC
= note: inside `std::sys::pal::PLATFORM::small_c_string::run_path_with_cstr::<std::sys::pal::PLATFORM::fs::File>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC
= note: inside `std::sys::pal::PLATFORM::fs::File::open` at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC = note: inside `std::sys::pal::PLATFORM::fs::File::open` at RUSTLIB/std/src/sys/pal/PLATFORM/fs.rs:LL:CC
= note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC = note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC
= note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC = note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC