open_coroutine_hooks/unix/
mod.rs

1// check https://www.rustwiki.org.cn/en/reference/introduction.html for help information
2macro_rules! init_hook {
3    ( $symbol:literal ) => {
4        once_cell::sync::Lazy::new(|| unsafe {
5            let syscall = $symbol;
6            let symbol = std::ffi::CString::new(String::from(syscall))
7                .unwrap_or_else(|_| panic!("can not transfer \"{syscall}\" to CString"));
8            let ptr = libc::dlsym(libc::RTLD_NEXT, symbol.as_ptr());
9            assert!(!ptr.is_null(), "system call \"{syscall}\" not found !");
10            std::mem::transmute(ptr)
11        })
12    };
13}
14
15pub mod common;
16
17pub mod sleep;
18
19pub mod socket;
20
21pub mod read;
22
23pub mod write;
24
25#[cfg(any(
26    target_os = "linux",
27    target_os = "l4re",
28    target_os = "android",
29    target_os = "emscripten"
30))]
31mod linux_like;
32
33extern "C" {
34    #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))]
35    #[cfg_attr(
36        any(
37            target_os = "linux",
38            target_os = "emscripten",
39            target_os = "fuchsia",
40            target_os = "l4re"
41        ),
42        link_name = "__errno_location"
43    )]
44    #[cfg_attr(
45        any(
46            target_os = "netbsd",
47            target_os = "openbsd",
48            target_os = "android",
49            target_os = "redox",
50            target_env = "newlib"
51        ),
52        link_name = "__errno"
53    )]
54    #[cfg_attr(
55        any(target_os = "solaris", target_os = "illumos"),
56        link_name = "___errno"
57    )]
58    #[cfg_attr(
59        any(
60            target_os = "macos",
61            target_os = "ios",
62            target_os = "freebsd",
63            target_os = "watchos"
64        ),
65        link_name = "__error"
66    )]
67    #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
68    fn errno_location() -> *mut libc::c_int;
69}
70
71pub extern "C" fn reset_errno() {
72    set_errno(0);
73}
74
75pub extern "C" fn set_errno(errno: libc::c_int) {
76    unsafe { errno_location().write(errno) }
77}
78
79extern "C" fn set_non_blocking(socket: libc::c_int) {
80    assert!(
81        set_non_blocking_flag(socket, true),
82        "set_non_blocking failed !"
83    );
84}
85
86extern "C" fn set_blocking(socket: libc::c_int) {
87    assert!(
88        set_non_blocking_flag(socket, false),
89        "set_blocking failed !"
90    );
91}
92
93extern "C" fn set_non_blocking_flag(socket: libc::c_int, on: bool) -> bool {
94    let flags = unsafe { libc::fcntl(socket, libc::F_GETFL) };
95    if flags < 0 {
96        return false;
97    }
98    unsafe {
99        libc::fcntl(
100            socket,
101            libc::F_SETFL,
102            if on {
103                flags | libc::O_NONBLOCK
104            } else {
105                flags & !libc::O_NONBLOCK
106            },
107        ) == 0
108    }
109}
110
111#[must_use]
112pub extern "C" fn is_blocking(socket: libc::c_int) -> bool {
113    !is_non_blocking(socket)
114}
115
116#[must_use]
117pub extern "C" fn is_non_blocking(socket: libc::c_int) -> bool {
118    let flags = unsafe { libc::fcntl(socket, libc::F_GETFL) };
119    if flags < 0 {
120        return false;
121    }
122    (flags & libc::O_NONBLOCK) != 0
123}