(bytes: &[u8], f: F)
| 989 | #[allow(unsafe_code, clippy::int_plus_one)] |
| 990 | #[cold] |
| 991 | fn with_c_str_slow_path<T, F>(bytes: &[u8], f: F) -> io::Result<T> |
| 992 | where |
| 993 | F: FnOnce(&CStr) -> io::Result<T>, |
| 994 | { |
| 995 | #[cfg(feature = "alloc")] |
| 996 | { |
| 997 | f(&CString::new(bytes).map_err(|_cstr_err| io::Errno::INVAL)?) |
| 998 | } |
| 999 | |
| 1000 | #[cfg(not(feature = "alloc"))] |
| 1001 | { |
| 1002 | #[cfg(all( |
| 1003 | libc, |
| 1004 | not(any( |
| 1005 | target_os = "espidf", |
| 1006 | target_os = "horizon", |
| 1007 | target_os = "hurd", |
| 1008 | target_os = "vita", |
| 1009 | target_os = "wasi" |
| 1010 | )) |
| 1011 | ))] |
| 1012 | const LARGE_PATH_BUFFER_SIZE: usize = libc::PATH_MAX as usize; |
| 1013 | #[cfg(linux_raw)] |
| 1014 | const LARGE_PATH_BUFFER_SIZE: usize = linux_raw_sys::general::PATH_MAX as usize; |
| 1015 | #[cfg(any( |
| 1016 | target_os = "espidf", |
| 1017 | target_os = "horizon", |
| 1018 | target_os = "hurd", |
| 1019 | target_os = "vita", |
| 1020 | target_os = "wasi" |
| 1021 | ))] |
| 1022 | const LARGE_PATH_BUFFER_SIZE: usize = 4096 as usize; // TODO: upstream this |
| 1023 | |
| 1024 | // Taken from |
| 1025 | // <https://github.com/rust-lang/rust/blob/a00f8ba7fcac1b27341679c51bf5a3271fa82df3/library/std/src/sys/common/small_c_string.rs> |
| 1026 | let mut buf = MaybeUninit::<[u8; LARGE_PATH_BUFFER_SIZE]>::uninit(); |
| 1027 | let buf_ptr = buf.as_mut_ptr().cast::<u8>(); |
| 1028 | |
| 1029 | // This helps test our safety condition below. |
| 1030 | if bytes.len() + 1 > LARGE_PATH_BUFFER_SIZE { |
| 1031 | return Err(io::Errno::NAMETOOLONG); |
| 1032 | } |
| 1033 | |
| 1034 | // SAFETY: `bytes.len() < LARGE_PATH_BUFFER_SIZE` which means we have |
| 1035 | // space for `bytes.len() + 1` `u8`s: |
| 1036 | unsafe { |
| 1037 | ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len()); |
| 1038 | buf_ptr.add(bytes.len()).write(b'\0'); |
| 1039 | } |
| 1040 | |
| 1041 | // SAFETY: We just wrote the bytes above and they will remain valid for |
| 1042 | // the duration of `f` because `buf` doesn't get dropped until the end |
| 1043 | // of the function. |
| 1044 | match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) |
| 1045 | { |
| 1046 | Ok(s) => f(s), |
| 1047 | Err(_) => Err(io::Errno::INVAL), |
| 1048 | } |
no test coverage detected