Skip to content

Commit

Permalink
Remove use of locale-specific strerror_r (#440)
Browse files Browse the repository at this point in the history
strerror_r doesn't necessarily return UTF-8 but we assume it does.

strerror_r is locale-sensitive but we are better off not being
locale-sensitive.

strerror_r requires us to use libc but increasingly we want to avoid
libc, e.g. to support x86_64-unknown-linux-none.

Just remove the use of the function.
  • Loading branch information
briansmith authored May 31, 2024
1 parent b2bca0f commit 40e873d
Showing 1 changed file with 11 additions and 28 deletions.
39 changes: 11 additions & 28 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(feature = "std")]
extern crate std;

use core::{fmt, num::NonZeroU32};

/// A small and `no_std` compatible error type
Expand Down Expand Up @@ -98,35 +101,13 @@ impl Error {
}
}

cfg_if! {
if #[cfg(unix)] {
fn os_err(errno: i32, buf: &mut [u8]) -> Option<&str> {
let buf_ptr = buf.as_mut_ptr().cast::<libc::c_char>();
if unsafe { libc::strerror_r(errno, buf_ptr, buf.len()) } != 0 {
return None;
}

// Take up to trailing null byte
let n = buf.len();
let idx = buf.iter().position(|&b| b == 0).unwrap_or(n);
core::str::from_utf8(&buf[..idx]).ok()
}
} else {
fn os_err(_errno: i32, _buf: &mut [u8]) -> Option<&str> {
None
}
}
}

impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut dbg = f.debug_struct("Error");
if let Some(errno) = self.raw_os_error() {
dbg.field("os_error", &errno);
let mut buf = [0u8; 128];
if let Some(err) = os_err(errno, &mut buf) {
dbg.field("description", &err);
}
#[cfg(feature = "std")]
dbg.field("description", &std::io::Error::from_raw_os_error(errno));
} else if let Some(desc) = internal_desc(*self) {
dbg.field("internal_code", &self.0.get());
dbg.field("description", &desc);
Expand All @@ -140,10 +121,12 @@ impl fmt::Debug for Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(errno) = self.raw_os_error() {
let mut buf = [0u8; 128];
match os_err(errno, &mut buf) {
Some(err) => err.fmt(f),
None => write!(f, "OS Error: {}", errno),
cfg_if! {
if #[cfg(feature = "std")] {
std::io::Error::from_raw_os_error(errno).fmt(f)
} else {
write!(f, "OS Error: {}", errno)
}
}
} else if let Some(desc) = internal_desc(*self) {
f.write_str(desc)
Expand Down

0 comments on commit 40e873d

Please sign in to comment.