1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
//! The libc backend.
//!
//! On most platforms, this uses the `libc` crate to make system calls. On
//! Windows, this uses the Winsock API in `windows-sys`, which can be adapted
//! to have a very `libc`-like interface.

// Every FFI call requires an unsafe block, and there are a lot of FFI
// calls. For now, set this to allow for the libc backend.
#![allow(clippy::undocumented_unsafe_blocks)]
// Lots of libc types vary between platforms, so we often need a `.into()` on
// one platform where it's redundant on another.
#![allow(clippy::useless_conversion)]

mod conv;

#[cfg(windows)]
pub(crate) mod fd {
    pub use crate::maybe_polyfill::os::windows::io::{
        AsRawSocket, AsSocket, BorrowedSocket as BorrowedFd, FromRawSocket, IntoRawSocket,
        OwnedSocket as OwnedFd, RawSocket as RawFd,
    };
    pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd;

    /// A version of [`AsRawFd`] for use with Winsock API.
    ///
    /// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html
    pub trait AsRawFd {
        /// A version of [`as_raw_fd`] for use with Winsock API.
        ///
        /// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.as_raw_fd
        fn as_raw_fd(&self) -> RawFd;
    }
    impl<T: AsRawSocket> AsRawFd for T {
        #[inline]
        fn as_raw_fd(&self) -> RawFd {
            self.as_raw_socket()
        }
    }

    /// A version of [`IntoRawFd`] for use with Winsock API.
    ///
    /// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html
    pub trait IntoRawFd {
        /// A version of [`into_raw_fd`] for use with Winsock API.
        ///
        /// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.into_raw_fd
        fn into_raw_fd(self) -> RawFd;
    }
    impl<T: IntoRawSocket> IntoRawFd for T {
        #[inline]
        fn into_raw_fd(self) -> RawFd {
            self.into_raw_socket()
        }
    }

    /// A version of [`FromRawFd`] for use with Winsock API.
    ///
    /// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html
    pub trait FromRawFd {
        /// A version of [`from_raw_fd`] for use with Winsock API.
        ///
        /// # Safety
        ///
        /// See the [safety requirements] for [`from_raw_fd`].
        ///
        /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd
        /// [safety requirements]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#safety
        unsafe fn from_raw_fd(raw_fd: RawFd) -> Self;
    }
    impl<T: FromRawSocket> FromRawFd for T {
        #[inline]
        unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
            Self::from_raw_socket(raw_fd)
        }
    }

    /// A version of [`AsFd`] for use with Winsock API.
    ///
    /// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
    pub trait AsFd {
        /// An `as_fd` function for Winsock, where a `Fd` is a `Socket`.
        fn as_fd(&self) -> BorrowedFd;
    }
    impl<T: AsSocket> AsFd for T {
        #[inline]
        fn as_fd(&self) -> BorrowedFd {
            self.as_socket()
        }
    }
}
#[cfg(not(windows))]
pub(crate) mod fd {
    pub use crate::maybe_polyfill::os::fd::{
        AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd,
    };
    #[allow(unused_imports)]
    pub(crate) use RawFd as LibcFd;
}

// On Windows we emulate selected libc-compatible interfaces. On non-Windows,
// we just use libc here, since this is the libc backend.
#[cfg_attr(windows, path = "winsock_c.rs")]
pub(crate) mod c;

#[cfg(feature = "event")]
pub(crate) mod event;
#[cfg(not(windows))]
#[cfg(feature = "fs")]
pub(crate) mod fs;
pub(crate) mod io;
#[cfg(linux_kernel)]
#[cfg(feature = "io_uring")]
pub(crate) mod io_uring;
#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
#[cfg(feature = "mm")]
pub(crate) mod mm;
#[cfg(linux_kernel)]
#[cfg(feature = "mount")]
pub(crate) mod mount;
#[cfg(linux_kernel)]
#[cfg(all(feature = "fs", not(feature = "mount")))]
pub(crate) mod mount; // for deprecated mount functions in "fs"
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
#[cfg(feature = "net")]
pub(crate) mod net;
#[cfg(not(any(windows, target_os = "espidf")))]
#[cfg(any(
    feature = "param",
    feature = "runtime",
    feature = "time",
    target_arch = "x86",
))]
pub(crate) mod param;
#[cfg(not(windows))]
#[cfg(feature = "pipe")]
pub(crate) mod pipe;
#[cfg(not(windows))]
#[cfg(feature = "process")]
pub(crate) mod process;
#[cfg(not(windows))]
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "pty")]
pub(crate) mod pty;
#[cfg(not(windows))]
#[cfg(feature = "rand")]
pub(crate) mod rand;
#[cfg(not(windows))]
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "system")]
pub(crate) mod system;
#[cfg(not(any(windows, target_os = "vita")))]
#[cfg(feature = "termios")]
pub(crate) mod termios;
#[cfg(not(windows))]
#[cfg(feature = "thread")]
pub(crate) mod thread;
#[cfg(not(any(windows, target_os = "espidf")))]
#[cfg(feature = "time")]
pub(crate) mod time;

/// If the host libc is glibc, return `true` if it is less than version 2.25.
///
/// To restate and clarify, this function returning true does not mean the libc
/// is glibc just that if it is glibc, it is less than version 2.25.
///
/// For now, this function is only available on Linux, but if it ends up being
/// used beyond that, this could be changed to e.g. `#[cfg(unix)]`.
#[cfg(all(unix, target_env = "gnu"))]
pub(crate) fn if_glibc_is_less_than_2_25() -> bool {
    // This is also defined inside `weak_or_syscall!` in
    // backend/libc/rand/syscalls.rs, but it's not convenient to re-export the
    // weak symbol from that macro, so we duplicate it at a small cost here.
    weak! { fn getrandom(*mut c::c_void, c::size_t, c::c_uint) -> c::ssize_t }

    // glibc 2.25 has `getrandom`, which is how we satisfy the API contract of
    // this function. But, there are likely other libc versions which have it.
    getrandom.get().is_none()
}

// Private modules used by multiple public modules.
#[cfg(any(feature = "procfs", feature = "process", feature = "runtime"))]
#[cfg(not(any(windows, target_os = "wasi")))]
pub(crate) mod pid;
#[cfg(any(feature = "process", feature = "thread"))]
#[cfg(linux_kernel)]
pub(crate) mod prctl;
#[cfg(not(any(
    windows,
    target_os = "android",
    target_os = "espidf",
    target_os = "vita",
    target_os = "wasi"
)))]
#[cfg(feature = "shm")]
pub(crate) mod shm;
#[cfg(any(feature = "fs", feature = "thread", feature = "process"))]
#[cfg(not(any(windows, target_os = "wasi")))]
pub(crate) mod ugid;

#[cfg(bsd)]
const MAX_IOV: usize = c::IOV_MAX as usize;

#[cfg(any(linux_kernel, target_os = "emscripten", target_os = "nto"))]
const MAX_IOV: usize = c::UIO_MAXIOV as usize;

#[cfg(not(any(
    bsd,
    linux_kernel,
    windows,
    target_os = "emscripten",
    target_os = "espidf",
    target_os = "nto",
    target_os = "horizon",
)))]
const MAX_IOV: usize = 16; // The minimum value required by POSIX.