open-coroutine-hooks 0.5.0

The syscall hook for open-coroutine
Documentation
// check https://www.rustwiki.org.cn/en/reference/introduction.html for help information
macro_rules! init_hook {
    ( $symbol:literal ) => {
        once_cell::sync::Lazy::new(|| unsafe {
            let syscall = $symbol;
            let symbol = std::ffi::CString::new(String::from(syscall))
                .unwrap_or_else(|_| panic!("can not transfer \"{syscall}\" to CString"));
            let ptr = libc::dlsym(libc::RTLD_NEXT, symbol.as_ptr());
            assert!(!ptr.is_null(), "system call \"{syscall}\" not found !");
            std::mem::transmute(ptr)
        })
    };
}

pub mod common;

pub mod sleep;

pub mod socket;

pub mod read;

pub mod write;

#[cfg(any(
    target_os = "linux",
    target_os = "l4re",
    target_os = "android",
    target_os = "emscripten"
))]
mod linux_like;

extern "C" {
    #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))]
    #[cfg_attr(
        any(
            target_os = "linux",
            target_os = "emscripten",
            target_os = "fuchsia",
            target_os = "l4re"
        ),
        link_name = "__errno_location"
    )]
    #[cfg_attr(
        any(
            target_os = "netbsd",
            target_os = "openbsd",
            target_os = "android",
            target_os = "redox",
            target_env = "newlib"
        ),
        link_name = "__errno"
    )]
    #[cfg_attr(
        any(target_os = "solaris", target_os = "illumos"),
        link_name = "___errno"
    )]
    #[cfg_attr(
        any(
            target_os = "macos",
            target_os = "ios",
            target_os = "freebsd",
            target_os = "watchos"
        ),
        link_name = "__error"
    )]
    #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
    fn errno_location() -> *mut libc::c_int;
}

pub extern "C" fn reset_errno() {
    set_errno(0);
}

pub extern "C" fn set_errno(errno: libc::c_int) {
    unsafe { errno_location().write(errno) }
}

extern "C" fn set_non_blocking(socket: libc::c_int) {
    assert!(
        set_non_blocking_flag(socket, true),
        "set_non_blocking failed !"
    );
}

extern "C" fn set_blocking(socket: libc::c_int) {
    assert!(
        set_non_blocking_flag(socket, false),
        "set_blocking failed !"
    );
}

extern "C" fn set_non_blocking_flag(socket: libc::c_int, on: bool) -> bool {
    let flags = unsafe { libc::fcntl(socket, libc::F_GETFL) };
    if flags < 0 {
        return false;
    }
    unsafe {
        libc::fcntl(
            socket,
            libc::F_SETFL,
            if on {
                flags | libc::O_NONBLOCK
            } else {
                flags & !libc::O_NONBLOCK
            },
        ) == 0
    }
}

#[must_use]
pub extern "C" fn is_blocking(socket: libc::c_int) -> bool {
    !is_non_blocking(socket)
}

#[must_use]
pub extern "C" fn is_non_blocking(socket: libc::c_int) -> bool {
    let flags = unsafe { libc::fcntl(socket, libc::F_GETFL) };
    if flags < 0 {
        return false;
    }
    (flags & libc::O_NONBLOCK) != 0
}