rustix/
lib.rs

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, _received) = 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 = 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//!  - Use `timespec` for timestamps and timeouts instead of `timeval` and
75//!    `c_int` milliseconds.
76//!
77//! Things they don't do include:
78//!  - Detecting whether functions are supported at runtime, except in specific
79//!    cases where new interfaces need to be detected to support y2038 and LFS.
80//!  - Hiding significant differences between platforms.
81//!  - Restricting ambient authorities.
82//!  - Imposing sandboxing features such as filesystem path or network address
83//!    sandboxing.
84//!
85//! See [`cap-std`], [`system-interface`], and [`io-streams`] for libraries
86//! which do hide significant differences between platforms, and [`cap-std`]
87//! which does perform sandboxing and restricts ambient authorities.
88//!
89//! [`cap-std`]: https://crates.io/crates/cap-std
90//! [`system-interface`]: https://crates.io/crates/system-interface
91//! [`io-streams`]: https://crates.io/crates/io-streams
92//! [`bitflags`]: bitflags
93//! [`AsFd`]: crate::fd::AsFd
94//! [`OwnedFd`]: crate::fd::OwnedFd
95//! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
96//! [`Arg`]: path::Arg
97//! [support for externally defined flags]: 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(docsrs, 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(error_in_core, feature(error_in_core))]
108#![cfg_attr(all(feature = "alloc", alloc_c_string), feature(alloc_c_string))]
109#![cfg_attr(all(feature = "alloc", alloc_ffi), feature(alloc_ffi))]
110#![cfg_attr(not(feature = "std"), no_std)]
111#![cfg_attr(feature = "rustc-dep-of-std", feature(ip))]
112#![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))]
113#![cfg_attr(
114    any(feature = "rustc-dep-of-std", core_intrinsics),
115    feature(core_intrinsics)
116)]
117#![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))]
118#![cfg_attr(not(feature = "all-apis"), allow(dead_code))]
119// It is common in Linux and libc APIs for types to vary between platforms.
120#![allow(clippy::unnecessary_cast)]
121// It is common in Linux and libc APIs for types to vary between platforms.
122#![allow(clippy::useless_conversion)]
123// This clippy lint gets too many false positives.
124#![allow(clippy::needless_lifetimes)]
125// Redox and WASI have enough differences that it isn't worth precisely
126// conditionalizing all the `use`s for them. Similar for if we don't have
127// "all-apis".
128#![cfg_attr(
129    any(target_os = "redox", target_os = "wasi", not(feature = "all-apis")),
130    allow(unused_imports)
131)]
132// wasip2 conditionally gates stdlib APIs such as `OsStrExt`.
133// <https://github.com/rust-lang/rust/issues/130323>
134#![cfg_attr(
135    all(
136        target_os = "wasi",
137        target_env = "p2",
138        any(feature = "fs", feature = "mount", feature = "net"),
139        wasip2,
140    ),
141    feature(wasip2)
142)]
143
144#[cfg(all(feature = "alloc", feature = "rustc-dep-of-std"))]
145extern crate rustc_std_workspace_alloc as alloc;
146
147#[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))]
148extern crate alloc;
149
150// Use `static_assertions` macros if we have them, or a polyfill otherwise.
151#[cfg(all(test, static_assertions))]
152#[macro_use]
153#[allow(unused_imports)]
154extern crate static_assertions;
155#[cfg(all(test, not(static_assertions)))]
156#[macro_use]
157#[allow(unused_imports)]
158mod static_assertions;
159
160pub mod buffer;
161#[cfg(not(windows))]
162#[macro_use]
163pub(crate) mod cstr;
164#[macro_use]
165pub(crate) mod utils;
166// Polyfill for `std` in `no_std` builds.
167#[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")]
168#[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")]
169pub(crate) mod maybe_polyfill;
170#[cfg(test)]
171#[macro_use]
172pub(crate) mod check_types;
173#[macro_use]
174pub(crate) mod bitcast;
175
176// linux_raw: Weak symbols are used by the use-libc-auxv feature for
177// glibc 2.15 support.
178//
179// libc: Weak symbols are used to call various functions available in some
180// versions of libc and not others.
181#[cfg(any(
182    all(linux_raw, feature = "use-libc-auxv"),
183    all(libc, not(any(windows, target_os = "espidf", target_os = "wasi")))
184))]
185#[macro_use]
186mod weak;
187
188// Pick the backend implementation to use.
189#[cfg_attr(libc, path = "backend/libc/mod.rs")]
190#[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")]
191#[cfg_attr(wasi, path = "backend/wasi/mod.rs")]
192mod backend;
193
194/// Export the `*Fd` types and traits that are used in rustix's public API.
195///
196/// Users can use this to avoid needing to import anything else to use the same
197/// versions of these types and traits.
198pub mod fd {
199    use super::backend;
200
201    // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on
202    // Windows due to them having blanket impls on Windows, so users must
203    // implement `AsSocket` etc.
204    #[cfg(windows)]
205    pub use backend::fd::{AsRawSocket, AsSocket, FromRawSocket, IntoRawSocket};
206
207    pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
208}
209
210// The public API modules.
211#[cfg(feature = "event")]
212#[cfg_attr(docsrs, doc(cfg(feature = "event")))]
213pub mod event;
214pub mod ffi;
215#[cfg(not(windows))]
216#[cfg(feature = "fs")]
217#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
218pub mod fs;
219pub mod io;
220#[cfg(linux_kernel)]
221#[cfg(feature = "io_uring")]
222#[cfg_attr(docsrs, doc(cfg(feature = "io_uring")))]
223pub mod io_uring;
224pub mod ioctl;
225#[cfg(not(any(
226    windows,
227    target_os = "espidf",
228    target_os = "horizon",
229    target_os = "vita",
230    target_os = "wasi"
231)))]
232#[cfg(feature = "mm")]
233#[cfg_attr(docsrs, doc(cfg(feature = "mm")))]
234pub mod mm;
235#[cfg(linux_kernel)]
236#[cfg(feature = "mount")]
237#[cfg_attr(docsrs, doc(cfg(feature = "mount")))]
238pub mod mount;
239#[cfg(not(target_os = "wasi"))]
240#[cfg(feature = "net")]
241#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
242pub mod net;
243#[cfg(not(any(windows, target_os = "espidf")))]
244#[cfg(feature = "param")]
245#[cfg_attr(docsrs, doc(cfg(feature = "param")))]
246pub mod param;
247#[cfg(not(windows))]
248#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
249#[cfg_attr(
250    docsrs,
251    doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
252)]
253pub mod path;
254#[cfg(feature = "pipe")]
255#[cfg_attr(docsrs, doc(cfg(feature = "pipe")))]
256#[cfg(not(any(windows, target_os = "wasi")))]
257pub mod pipe;
258#[cfg(not(windows))]
259#[cfg(feature = "process")]
260#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
261pub mod process;
262#[cfg(not(windows))]
263#[cfg(not(target_os = "wasi"))]
264#[cfg(feature = "pty")]
265#[cfg_attr(docsrs, doc(cfg(feature = "pty")))]
266pub mod pty;
267#[cfg(not(windows))]
268#[cfg(feature = "rand")]
269#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
270pub mod rand;
271#[cfg(not(any(
272    windows,
273    target_os = "android",
274    target_os = "espidf",
275    target_os = "horizon",
276    target_os = "vita",
277    target_os = "wasi"
278)))]
279#[cfg(feature = "shm")]
280#[cfg_attr(docsrs, doc(cfg(feature = "shm")))]
281pub mod shm;
282#[cfg(not(windows))]
283#[cfg(feature = "stdio")]
284#[cfg_attr(docsrs, doc(cfg(feature = "stdio")))]
285pub mod stdio;
286#[cfg(feature = "system")]
287#[cfg(not(any(windows, target_os = "wasi")))]
288#[cfg_attr(docsrs, doc(cfg(feature = "system")))]
289pub mod system;
290#[cfg(not(any(windows, target_os = "horizon", target_os = "vita")))]
291#[cfg(feature = "termios")]
292#[cfg_attr(docsrs, doc(cfg(feature = "termios")))]
293pub mod termios;
294#[cfg(not(windows))]
295#[cfg(feature = "thread")]
296#[cfg_attr(docsrs, doc(cfg(feature = "thread")))]
297pub mod thread;
298#[cfg(not(any(windows, target_os = "espidf")))]
299#[cfg(feature = "time")]
300#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
301pub mod time;
302
303// "runtime" is also a public API module, but it's only for libc-like users.
304#[cfg(not(windows))]
305#[cfg(feature = "runtime")]
306#[cfg(linux_raw)]
307#[cfg_attr(not(document_experimental_runtime_api), doc(hidden))]
308#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
309pub mod runtime;
310
311// Declare "fs" as a non-public module if "fs" isn't enabled but we need it for
312// reading procfs.
313#[cfg(not(windows))]
314#[cfg(not(feature = "fs"))]
315#[cfg(all(
316    linux_raw,
317    not(feature = "use-libc-auxv"),
318    not(feature = "use-explicitly-provided-auxv"),
319    any(
320        feature = "param",
321        feature = "runtime",
322        feature = "thread",
323        feature = "time",
324        target_arch = "x86",
325    )
326))]
327#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
328pub(crate) mod fs;
329
330// Similarly, declare `path` as a non-public module if needed.
331#[cfg(not(windows))]
332#[cfg(not(any(feature = "fs", feature = "mount", feature = "net")))]
333#[cfg(all(
334    linux_raw,
335    not(feature = "use-libc-auxv"),
336    not(feature = "use-explicitly-provided-auxv"),
337    any(
338        feature = "param",
339        feature = "runtime",
340        feature = "thread",
341        feature = "time",
342        target_arch = "x86",
343    )
344))]
345pub(crate) mod path;
346
347// Private modules used by multiple public modules.
348#[cfg(not(any(windows, target_os = "espidf")))]
349#[cfg(any(feature = "thread", feature = "time"))]
350mod clockid;
351#[cfg(linux_kernel)]
352#[cfg(any(feature = "io_uring", feature = "runtime"))]
353mod kernel_sigset;
354#[cfg(not(any(windows, target_os = "wasi")))]
355#[cfg(any(
356    feature = "process",
357    feature = "runtime",
358    feature = "termios",
359    feature = "thread",
360    all(bsd, feature = "event"),
361    all(linux_kernel, feature = "net")
362))]
363mod pid;
364#[cfg(any(feature = "process", feature = "thread"))]
365#[cfg(linux_kernel)]
366mod prctl;
367#[cfg(not(any(windows, target_os = "espidf", target_os = "wasi")))]
368#[cfg(any(
369    feature = "io_uring",
370    feature = "process",
371    feature = "runtime",
372    all(bsd, feature = "event")
373))]
374mod signal;
375#[cfg(any(
376    feature = "fs",
377    feature = "event",
378    feature = "process",
379    feature = "runtime",
380    feature = "thread",
381    feature = "time",
382    all(feature = "event", any(bsd, linux_kernel, windows, target_os = "wasi")),
383    all(
384        linux_raw,
385        not(feature = "use-libc-auxv"),
386        not(feature = "use-explicitly-provided-auxv"),
387        any(
388            feature = "param",
389            feature = "process",
390            feature = "runtime",
391            feature = "time",
392            target_arch = "x86",
393        )
394    )
395))]
396mod timespec;
397#[cfg(not(any(windows, target_os = "wasi")))]
398#[cfg(any(
399    feature = "fs",
400    feature = "process",
401    feature = "thread",
402    all(
403        linux_raw,
404        not(feature = "use-libc-auxv"),
405        not(feature = "use-explicitly-provided-auxv"),
406        any(
407            feature = "param",
408            feature = "runtime",
409            feature = "time",
410            target_arch = "x86",
411        )
412    ),
413    all(linux_kernel, feature = "net")
414))]
415mod ugid;
416
417#[cfg(doc)]
418#[cfg_attr(docsrs, doc(cfg(doc)))]
419pub mod not_implemented;