rustix/backend/libc/
mod.rs

1//! The libc backend.
2//!
3//! On most platforms, this uses the `libc` crate to make system calls. On
4//! Windows, this uses the Winsock API in `windows-sys`, which can be adapted
5//! to have a very `libc`-like interface.
6
7// Every FFI call requires an unsafe block, and there are a lot of FFI
8// calls. For now, set this to allow for the libc backend.
9#![allow(clippy::undocumented_unsafe_blocks)]
10// Lots of libc types vary between platforms, so we often need a `.into()` on
11// one platform where it's redundant on another.
12#![allow(clippy::useless_conversion)]
13
14mod conv;
15
16#[cfg(windows)]
17pub(crate) mod fd {
18    // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on
19    // Windows due to them having blanket impls on Windows, so users must
20    // implement `AsSocket` etc.
21    pub use crate::maybe_polyfill::os::windows::io::{
22        AsRawSocket, AsSocket, BorrowedSocket as BorrowedFd, FromRawSocket, IntoRawSocket,
23        OwnedSocket as OwnedFd, RawSocket as RawFd,
24    };
25    pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd;
26
27    /// A version of [`AsRawFd`] for use with Winsock API.
28    ///
29    /// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html
30    pub trait AsRawFd {
31        /// A version of [`as_raw_fd`] for use with Winsock API.
32        ///
33        /// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html#tymethod.as_raw_fd
34        fn as_raw_fd(&self) -> RawFd;
35    }
36    impl<T: AsRawSocket> AsRawFd for T {
37        #[inline]
38        fn as_raw_fd(&self) -> RawFd {
39            self.as_raw_socket()
40        }
41    }
42
43    /// A version of [`IntoRawFd`] for use with Winsock API.
44    ///
45    /// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html
46    pub trait IntoRawFd {
47        /// A version of [`into_raw_fd`] for use with Winsock API.
48        ///
49        /// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html#tymethod.into_raw_fd
50        fn into_raw_fd(self) -> RawFd;
51    }
52    impl<T: IntoRawSocket> IntoRawFd for T {
53        #[inline]
54        fn into_raw_fd(self) -> RawFd {
55            self.into_raw_socket()
56        }
57    }
58
59    /// A version of [`FromRawFd`] for use with Winsock API.
60    ///
61    /// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html
62    pub trait FromRawFd {
63        /// A version of [`from_raw_fd`] for use with Winsock API.
64        ///
65        /// # Safety
66        ///
67        /// See the [safety requirements] for [`from_raw_fd`].
68        ///
69        /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd
70        /// [safety requirements]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#safety
71        unsafe fn from_raw_fd(raw_fd: RawFd) -> Self;
72    }
73    impl<T: FromRawSocket> FromRawFd for T {
74        #[inline]
75        unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
76            Self::from_raw_socket(raw_fd)
77        }
78    }
79
80    /// A version of [`AsFd`] for use with Winsock API.
81    ///
82    /// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
83    pub trait AsFd {
84        /// An `as_fd` function for Winsock, where an `Fd` is a `Socket`.
85        fn as_fd(&self) -> BorrowedFd<'_>;
86    }
87    impl<T: AsSocket> AsFd for T {
88        #[inline]
89        fn as_fd(&self) -> BorrowedFd<'_> {
90            self.as_socket()
91        }
92    }
93}
94#[cfg(not(windows))]
95pub(crate) mod fd {
96    pub use crate::maybe_polyfill::os::fd::*;
97    #[allow(unused_imports)]
98    pub(crate) use RawFd as LibcFd;
99}
100
101// On Windows we emulate selected libc-compatible interfaces. On non-Windows,
102// we just use libc here, since this is the libc backend.
103#[cfg_attr(windows, path = "winsock_c.rs")]
104pub(crate) mod c;
105
106#[cfg(feature = "event")]
107pub(crate) mod event;
108#[cfg(not(windows))]
109#[cfg(feature = "fs")]
110pub(crate) mod fs;
111pub(crate) mod io;
112#[cfg(linux_kernel)]
113#[cfg(feature = "io_uring")]
114pub(crate) mod io_uring;
115#[cfg(not(any(
116    windows,
117    target_os = "espidf",
118    target_os = "horizon",
119    target_os = "vita",
120    target_os = "wasi"
121)))]
122#[cfg(feature = "mm")]
123pub(crate) mod mm;
124#[cfg(linux_kernel)]
125#[cfg(feature = "mount")]
126pub(crate) mod mount;
127#[cfg(not(target_os = "wasi"))]
128#[cfg(feature = "net")]
129pub(crate) mod net;
130#[cfg(not(any(windows, target_os = "espidf")))]
131#[cfg(any(
132    feature = "param",
133    feature = "runtime",
134    feature = "time",
135    target_arch = "x86",
136))]
137pub(crate) mod param;
138#[cfg(not(windows))]
139#[cfg(feature = "pipe")]
140pub(crate) mod pipe;
141#[cfg(not(windows))]
142#[cfg(feature = "process")]
143pub(crate) mod process;
144#[cfg(not(windows))]
145#[cfg(not(target_os = "wasi"))]
146#[cfg(feature = "pty")]
147pub(crate) mod pty;
148#[cfg(not(windows))]
149#[cfg(feature = "rand")]
150pub(crate) mod rand;
151#[cfg(not(windows))]
152#[cfg(not(target_os = "wasi"))]
153#[cfg(feature = "system")]
154pub(crate) mod system;
155#[cfg(not(any(windows, target_os = "horizon", target_os = "vita")))]
156#[cfg(feature = "termios")]
157pub(crate) mod termios;
158#[cfg(not(windows))]
159#[cfg(feature = "thread")]
160pub(crate) mod thread;
161#[cfg(not(any(windows, target_os = "espidf")))]
162#[cfg(feature = "time")]
163pub(crate) mod time;
164
165/// If the host libc is glibc, return `true` if it is less than version 2.25.
166///
167/// To restate and clarify, this function returning true does not mean the libc
168/// is glibc just that if it is glibc, it is less than version 2.25.
169///
170/// For now, this function is only available on Linux, but if it ends up being
171/// used beyond that, this could be changed to e.g. `#[cfg(unix)]`.
172#[cfg(all(unix, target_env = "gnu"))]
173pub(crate) fn if_glibc_is_less_than_2_25() -> bool {
174    // This is also defined inside `weak_or_syscall!` in
175    // backend/libc/rand/syscalls.rs, but it's not convenient to re-export the
176    // weak symbol from that macro, so we duplicate it at a small cost here.
177    weak! { fn getrandom(*mut c::c_void, c::size_t, c::c_uint) -> c::ssize_t }
178
179    // glibc 2.25 has `getrandom`, which is how we satisfy the API contract of
180    // this function. But, there are likely other libc versions which have it.
181    getrandom.get().is_none()
182}
183
184// Private modules used by multiple public modules.
185#[cfg(any(feature = "process", feature = "runtime"))]
186#[cfg(not(any(windows, target_os = "wasi")))]
187pub(crate) mod pid;
188#[cfg(any(feature = "process", feature = "thread"))]
189#[cfg(linux_kernel)]
190pub(crate) mod prctl;
191#[cfg(not(any(
192    windows,
193    target_os = "android",
194    target_os = "espidf",
195    target_os = "horizon",
196    target_os = "vita",
197    target_os = "wasi"
198)))]
199#[cfg(feature = "shm")]
200pub(crate) mod shm;
201#[cfg(any(feature = "fs", feature = "thread", feature = "process"))]
202#[cfg(not(any(windows, target_os = "wasi")))]
203pub(crate) mod ugid;
204
205#[cfg(bsd)]
206const MAX_IOV: usize = c::IOV_MAX as usize;
207
208#[cfg(any(linux_kernel, target_os = "emscripten", target_os = "nto"))]
209const MAX_IOV: usize = c::UIO_MAXIOV as usize;
210
211#[cfg(not(any(
212    bsd,
213    linux_kernel,
214    windows,
215    target_os = "emscripten",
216    target_os = "espidf",
217    target_os = "nto",
218    target_os = "horizon",
219)))]
220const MAX_IOV: usize = 16; // The minimum value required by POSIX.