1//! `rustix` provides efficient memory-safe and [I/O-safe] wrappers to
2//! POSIX-like, Unix-like, Linux, and Winsock syscall-like APIs, with
3//! configurable backends.
4//!
5//! With rustix, you can write code like this:
6//!
7//! ```
8//! # #[cfg(feature = "net")]
9//! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> {
10//! # use rustix::net::RecvFlags;
11//! let nread: usize = rustix::net::recv(&sock, buf, RecvFlags::PEEK)?;
12//! # let _ = nread;
13//! # Ok(())
14//! # }
15//! ```
16//!
17//! instead of like this:
18//!
19//! ```
20//! # #[cfg(feature = "net")]
21//! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> {
22//! # #[cfg(unix)]
23//! # use std::os::unix::io::AsRawFd;
24//! # #[cfg(target_os = "wasi")]
25//! # use std::os::wasi::io::AsRawFd;
26//! # #[cfg(windows)]
27//! # use windows_sys::Win32::Networking::WinSock as libc;
28//! # #[cfg(windows)]
29//! # use std::os::windows::io::AsRawSocket;
30//! # const MSG_PEEK: i32 = libc::MSG_PEEK;
31//! let nread: usize = unsafe {
32//! #[cfg(any(unix, target_os = "wasi"))]
33//! let raw = sock.as_raw_fd();
34//! #[cfg(windows)]
35//! let raw = sock.as_raw_socket();
36//! match libc::recv(
37//! raw as _,
38//! buf.as_mut_ptr().cast(),
39//! buf.len().try_into().unwrap_or(i32::MAX as _),
40//! MSG_PEEK,
41//! ) {
42//! -1 => return Err(std::io::Error::last_os_error()),
43//! nread => nread as usize,
44//! }
45//! };
46//! # let _ = nread;
47//! # Ok(())
48//! # }
49//! ```
50//!
51//! rustix's APIs perform the following tasks:
52//! - Error values are translated to [`Result`]s.
53//! - Buffers are passed as Rust slices.
54//! - Out-parameters are presented as return values.
55//! - Path arguments use [`Arg`], so they accept any string type.
56//! - File descriptors are passed and returned via [`AsFd`] and [`OwnedFd`]
57//! instead of bare integers, ensuring I/O safety.
58//! - Constants use `enum`s and [`bitflags`] types, and enable [support for
59//! externally defined flags].
60//! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed.
61//! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic.
62//! - Functions that return strings automatically allocate sufficient memory
63//! and retry the syscall as needed to determine the needed length.
64//! - Functions and types which need `l` prefixes or `64` suffixes to enable
65//! large-file support (LFS) are used automatically. File sizes and offsets
66//! are always presented as `u64` and `i64`.
67//! - Behaviors that depend on the sizes of C types like `long` are hidden.
68//! - In some places, more human-friendly and less historical-accident names
69//! are used (and documentation aliases are used so that the original names
70//! can still be searched for).
71//! - Provide y2038 compatibility, on platforms which support this.
72//! - Correct selected platform bugs, such as behavioral differences when
73//! running under seccomp.
74//!
75//! Things they don't do include:
76//! - Detecting whether functions are supported at runtime, except in specific
77//! cases where new interfaces need to be detected to support y2038 and LFS.
78//! - Hiding significant differences between platforms.
79//! - Restricting ambient authorities.
80//! - Imposing sandboxing features such as filesystem path or network address
81//! sandboxing.
82//!
83//! See [`cap-std`], [`system-interface`], and [`io-streams`] for libraries
84//! which do hide significant differences between platforms, and [`cap-std`]
85//! which does perform sandboxing and restricts ambient authorities.
86//!
87//! [`cap-std`]: https://crates.io/crates/cap-std
88//! [`system-interface`]: https://crates.io/crates/system-interface
89//! [`io-streams`]: https://crates.io/crates/io-streams
90//! [`getrandom`]: https://crates.io/crates/getrandom
91//! [`bitflags`]: https://crates.io/crates/bitflags
92//! [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
93//! [`OwnedFd`]: https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html
94//! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
95//! [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html
96//! [`Arg`]: https://docs.rs/rustix/*/rustix/path/trait.Arg.html
97//! [support for externally defined flags]: https://docs.rs/bitflags/*/bitflags/#externally-defined-flags
98
99#![deny(missing_docs)]
100#![allow(stable_features)]
101#![cfg_attr(linux_raw, deny(unsafe_code))]
102#![cfg_attr(rustc_attrs, feature(rustc_attrs))]
103#![cfg_attr(doc_cfg, feature(doc_cfg))]
104#![cfg_attr(all(wasi_ext, target_os = "wasi", feature = "std"), feature(wasi_ext))]
105#![cfg_attr(core_ffi_c, feature(core_ffi_c))]
106#![cfg_attr(core_c_str, feature(core_c_str))]
107#![cfg_attr(all(feature = "alloc", alloc_c_string), feature(alloc_c_string))]
108#![cfg_attr(all(feature = "alloc", alloc_ffi), feature(alloc_ffi))]
109#![cfg_attr(not(feature = "std"), no_std)]
110#![cfg_attr(feature = "rustc-dep-of-std", feature(ip))]
111#![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))]
112#![cfg_attr(
113 any(feature = "rustc-dep-of-std", core_intrinsics),
114 feature(core_intrinsics)
115)]
116#![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))]
117#![cfg_attr(not(feature = "all-apis"), allow(dead_code))]
118// It is common in Linux and libc APIs for types to vary between platforms.
119#![allow(clippy::unnecessary_cast)]
120// It is common in Linux and libc APIs for types to vary between platforms.
121#![allow(clippy::useless_conversion)]
122// Redox and WASI have enough differences that it isn't worth precisely
123// conditionalizing all the `use`s for them. Similar for if we don't have
124// "all-apis".
125#![cfg_attr(
126 any(target_os = "redox", target_os = "wasi", not(feature = "all-apis")),
127 allow(unused_imports)
128)]
129
130#[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))]
131extern crate alloc;
132
133// Use `static_assertions` macros if we have them, or a polyfill otherwise.
134#[cfg(all(test, static_assertions))]
135#[macro_use]
136#[allow(unused_imports)]
137extern crate static_assertions;
138#[cfg(all(test, not(static_assertions)))]
139#[macro_use]
140#[allow(unused_imports)]
141mod static_assertions;
142
143// Internal utilities.
144mod buffer;
145#[cfg(not(windows))]
146#[macro_use]
147pub(crate) mod cstr;
148#[macro_use]
149pub(crate) mod utils;
150// Polyfill for `std` in `no_std` builds.
151#[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")]
152#[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")]
153pub(crate) mod maybe_polyfill;
154#[cfg(test)]
155#[macro_use]
156pub(crate) mod check_types;
157#[macro_use]
158pub(crate) mod bitcast;
159
160// linux_raw: Weak symbols are used by the use-libc-auxv feature for
161// glibc 2.15 support.
162//
163// libc: Weak symbols are used to call various functions available in some
164// versions of libc and not others.
165#[cfg(any(
166 all(linux_raw, feature = "use-libc-auxv"),
167 all(libc, not(any(windows, target_os = "espidf", target_os = "wasi")))
168))]
169#[macro_use]
170mod weak;
171
172// Pick the backend implementation to use.
173#[cfg_attr(libc, path = "backend/libc/mod.rs")]
174#[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")]
175#[cfg_attr(wasi, path = "backend/wasi/mod.rs")]
176mod backend;
177
178/// Export the `*Fd` types and traits that are used in rustix's public API.
179///
180/// Users can use this to avoid needing to import anything else to use the same
181/// versions of these types and traits.
182pub mod fd {
183 use super::backend;
184
185 // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on
186 // Windows due to them having blanket impls on Windows, so users must
187 // implement `AsSocket` etc.
188 #[cfg(windows)]
189 pub use backend::fd::{AsRawSocket, AsSocket, FromRawSocket, IntoRawSocket};
190
191 pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
192}
193
194// The public API modules.
195#[cfg(feature = "event")]
196#[cfg_attr(doc_cfg, doc(cfg(feature = "event")))]
197pub mod event;
198#[cfg(not(windows))]
199pub mod ffi;
200#[cfg(not(windows))]
201#[cfg(feature = "fs")]
202#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
203pub mod fs;
204pub mod io;
205#[cfg(linux_kernel)]
206#[cfg(feature = "io_uring")]
207#[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))]
208pub mod io_uring;
209pub mod ioctl;
210#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
211#[cfg(feature = "mm")]
212#[cfg_attr(doc_cfg, doc(cfg(feature = "mm")))]
213pub mod mm;
214#[cfg(linux_kernel)]
215#[cfg(feature = "mount")]
216#[cfg_attr(doc_cfg, doc(cfg(feature = "mount")))]
217pub mod mount;
218#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
219#[cfg(feature = "net")]
220#[cfg_attr(doc_cfg, doc(cfg(feature = "net")))]
221pub mod net;
222#[cfg(not(any(windows, target_os = "espidf")))]
223#[cfg(feature = "param")]
224#[cfg_attr(doc_cfg, doc(cfg(feature = "param")))]
225pub mod param;
226#[cfg(not(windows))]
227#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
228#[cfg_attr(
229 doc_cfg,
230 doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
231)]
232pub mod path;
233#[cfg(feature = "pipe")]
234#[cfg_attr(doc_cfg, doc(cfg(feature = "pipe")))]
235#[cfg(not(any(windows, target_os = "wasi")))]
236pub mod pipe;
237#[cfg(not(windows))]
238#[cfg(feature = "process")]
239#[cfg_attr(doc_cfg, doc(cfg(feature = "process")))]
240pub mod process;
241#[cfg(feature = "procfs")]
242#[cfg(linux_kernel)]
243#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
244pub mod procfs;
245#[cfg(not(windows))]
246#[cfg(not(target_os = "wasi"))]
247#[cfg(feature = "pty")]
248#[cfg_attr(doc_cfg, doc(cfg(feature = "pty")))]
249pub mod pty;
250#[cfg(not(windows))]
251#[cfg(feature = "rand")]
252#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
253pub mod rand;
254#[cfg(not(any(
255 windows,
256 target_os = "android",
257 target_os = "espidf",
258 target_os = "vita",
259 target_os = "wasi"
260)))]
261#[cfg(feature = "shm")]
262#[cfg_attr(doc_cfg, doc(cfg(feature = "shm")))]
263pub mod shm;
264#[cfg(not(windows))]
265#[cfg(feature = "stdio")]
266#[cfg_attr(doc_cfg, doc(cfg(feature = "stdio")))]
267pub mod stdio;
268#[cfg(feature = "system")]
269#[cfg(not(any(windows, target_os = "wasi")))]
270#[cfg_attr(doc_cfg, doc(cfg(feature = "system")))]
271pub mod system;
272#[cfg(not(any(windows, target_os = "vita")))]
273#[cfg(feature = "termios")]
274#[cfg_attr(doc_cfg, doc(cfg(feature = "termios")))]
275pub mod termios;
276#[cfg(not(windows))]
277#[cfg(feature = "thread")]
278#[cfg_attr(doc_cfg, doc(cfg(feature = "thread")))]
279pub mod thread;
280#[cfg(not(any(windows, target_os = "espidf")))]
281#[cfg(feature = "time")]
282#[cfg_attr(doc_cfg, doc(cfg(feature = "time")))]
283pub mod time;
284
285// "runtime" is also a public API module, but it's only for libc-like users.
286#[cfg(not(windows))]
287#[cfg(feature = "runtime")]
288#[cfg(linux_raw)]
289#[cfg_attr(not(document_experimental_runtime_api), doc(hidden))]
290#[cfg_attr(doc_cfg, doc(cfg(feature = "runtime")))]
291pub mod runtime;
292
293// Temporarily provide some mount functions for use in the fs module for
294// backwards compatibility.
295#[cfg(linux_kernel)]
296#[cfg(all(feature = "fs", not(feature = "mount")))]
297pub(crate) mod mount;
298
299// Declare "fs" as a non-public module if "fs" isn't enabled but we need it for
300// reading procfs.
301#[cfg(not(windows))]
302#[cfg(not(feature = "fs"))]
303#[cfg(all(
304 linux_raw,
305 not(feature = "use-libc-auxv"),
306 not(feature = "use-explicitly-provided-auxv"),
307 any(
308 feature = "param",
309 feature = "process",
310 feature = "runtime",
311 feature = "time",
312 target_arch = "x86",
313 )
314))]
315#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
316pub(crate) mod fs;
317
318// Similarly, declare `path` as a non-public module if needed.
319#[cfg(not(windows))]
320#[cfg(not(any(feature = "fs", feature = "mount", feature = "net")))]
321#[cfg(all(
322 linux_raw,
323 not(feature = "use-libc-auxv"),
324 not(feature = "use-explicitly-provided-auxv"),
325 any(
326 feature = "param",
327 feature = "process",
328 feature = "runtime",
329 feature = "time",
330 target_arch = "x86",
331 )
332))]
333pub(crate) mod path;
334
335// Private modules used by multiple public modules.
336#[cfg(not(any(windows, target_os = "espidf")))]
337#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
338mod clockid;
339#[cfg(not(any(windows, target_os = "wasi")))]
340#[cfg(any(
341 feature = "procfs",
342 feature = "process",
343 feature = "runtime",
344 feature = "termios",
345 feature = "thread",
346 all(bsd, feature = "event"),
347 all(linux_kernel, feature = "net")
348))]
349mod pid;
350#[cfg(any(feature = "process", feature = "thread"))]
351#[cfg(linux_kernel)]
352mod prctl;
353#[cfg(not(any(windows, target_os = "espidf", target_os = "wasi")))]
354#[cfg(any(feature = "process", feature = "runtime", all(bsd, feature = "event")))]
355mod signal;
356#[cfg(not(windows))]
357#[cfg(any(
358 feature = "fs",
359 feature = "process",
360 feature = "runtime",
361 feature = "thread",
362 feature = "time",
363 all(
364 linux_raw,
365 not(feature = "use-libc-auxv"),
366 not(feature = "use-explicitly-provided-auxv"),
367 any(
368 feature = "param",
369 feature = "process",
370 feature = "runtime",
371 feature = "time",
372 target_arch = "x86",
373 )
374 )
375))]
376mod timespec;
377#[cfg(not(any(windows, target_os = "wasi")))]
378#[cfg(any(
379 feature = "fs",
380 feature = "process",
381 feature = "thread",
382 all(
383 linux_raw,
384 not(feature = "use-libc-auxv"),
385 not(feature = "use-explicitly-provided-auxv"),
386 any(
387 feature = "param",
388 feature = "runtime",
389 feature = "time",
390 target_arch = "x86",
391 )
392 ),
393 all(linux_kernel, feature = "net")
394))]
395mod ugid;
396