rustld 0.1.55

A modern ELF loader (static & dynamic linker + compatible glibc & musl) written in Rust
Documentation
use std::io::Write;
use std::{cell::Cell, fmt::Display};

#[repr(transparent)]
#[doc(alias = "errno")]
#[derive(PartialEq, Eq)]
pub struct Errno(pub(crate) u32);

#[thread_local]
#[allow(non_upper_case_globals)]
pub static errno: Cell<Errno> = Cell::new(Errno(0));

pub fn set_errno(new_errno: Errno) {
    errno.set(new_errno);
}

impl Errno {
    pub const BADF: Self = Self(9);
    pub const INVAL: Self = Self(22);
}

impl Into<u32> for &Errno {
    fn into(self) -> u32 {
        self.0
    }
}

impl Display for Errno {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // Recognize errors documented in POSIX and use the documented strings.
        // <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html>
        let message = match *self {
            Errno::BADF => "Bad file descriptor",
            ref unknown_errno => {
                return write!(f, "Unknown error: {}", Into::<u32>::into(unknown_errno))
            }
        };
        f.write_str(message)
    }
}

pub(crate) unsafe fn __errno_location() -> *mut Errno {
    errno.as_ptr()
}

pub(crate) unsafe fn __xpg_strerror_r(errnum: Errno, buffer: *mut u8, length: usize) -> i32 {
    const ERANGE: i32 = 34;

    let mut cursor = std::io::Cursor::new(std::slice::from_raw_parts_mut(buffer, length));

    if write!(cursor, "{errnum}\0").is_err() {
        ERANGE
    } else {
        0
    }
}