Skip to main content

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(docsrs, feature(doc_cfg))]
103#![cfg_attr(all(wasi_ext, target_os = "wasi", feature = "std"), feature(wasi_ext))]
104#![cfg_attr(core_ffi_c, feature(core_ffi_c))]
105#![cfg_attr(core_c_str, feature(core_c_str))]
106#![cfg_attr(error_in_core, feature(error_in_core))]
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(
117    all(
118        asm_experimental_arch,
119        not(target_arch = "s390x"),
120        not(target_arch = "powerpc"),
121        not(target_arch = "powerpc64")
122    ),
123    feature(asm_experimental_arch)
124)]
125#![cfg_attr(not(feature = "all-apis"), allow(dead_code))]
126// It is common in Linux and libc APIs for types to vary between platforms.
127#![allow(clippy::unnecessary_cast)]
128// It is common in Linux and libc APIs for types to vary between platforms.
129#![allow(clippy::useless_conversion)]
130// This clippy lint gets too many false positives.
131#![allow(clippy::needless_lifetimes)]
132// Until `unnecessary_transmutes` is recognized by our MSRV, don't warn about
133// it being unrecognized.
134#![allow(unknown_lints)]
135// Until `cast_signed` and `cast_unsigned` are supported by our MSRV, don't
136// warn about transmutes that could be changed to them.
137#![allow(unnecessary_transmutes)]
138// Redox and WASI have enough differences that it isn't worth precisely
139// conditionalizing all the `use`s for them. Similar for if we don't have
140// "all-apis".
141#![cfg_attr(
142    any(target_os = "redox", target_os = "wasi", not(feature = "all-apis")),
143    allow(unused_imports)
144)]
145// wasip2 conditionally gates stdlib APIs such as `OsStrExt`.
146// <https://github.com/rust-lang/rust/issues/130323>
147#![cfg_attr(
148    all(
149        target_os = "wasi",
150        target_env = "p2",
151        any(feature = "fs", feature = "mount", feature = "net"),
152        wasip2,
153    ),
154    feature(wasip2)
155)]
156
157#[cfg(all(feature = "alloc", feature = "rustc-dep-of-std"))]
158extern crate rustc_std_workspace_alloc as alloc;
159
160#[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))]
161extern crate alloc;
162
163pub mod buffer;
164#[cfg(not(windows))]
165#[macro_use]
166pub(crate) mod cstr;
167#[macro_use]
168pub(crate) mod utils;
169// Polyfill for `std` in `no_std` builds.
170#[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")]
171#[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")]
172pub(crate) mod maybe_polyfill;
173#[cfg(test)]
174#[macro_use]
175pub(crate) mod check_types;
176#[macro_use]
177pub(crate) mod bitcast;
178#[cfg(sanitize_memory)]
179pub(crate) mod msan;
180
181// linux_raw: Weak symbols are used by the use-libc-auxv feature for
182// glibc 2.15 support.
183//
184// libc: Weak symbols are used to call various functions available in some
185// versions of libc and not others.
186#[cfg(any(
187    all(linux_raw, feature = "use-libc-auxv"),
188    all(libc, not(any(windows, target_os = "espidf", target_os = "wasi")))
189))]
190#[macro_use]
191mod weak;
192
193// Pick the backend implementation to use.
194#[cfg_attr(libc, path = "backend/libc/mod.rs")]
195#[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")]
196mod backend;
197
198/// Export the `*Fd` types and traits that are used in rustix's public API.
199///
200/// This module exports the types and traits from [`std::os::fd`], or polyills
201/// on Rust < 1.66 or on Windows.
202///
203/// On Windows, the polyfill consists of aliases of the socket types and
204/// traits, For example, [`OwnedSocket`] is aliased to `OwnedFd`, and so on,
205/// and there are blanket impls for `AsFd` etc. that map to `AsSocket` impls.
206/// These blanket impls suffice for using the traits, however not for
207/// implementing them, so this module also exports `AsSocket` and the other
208/// traits as-is so that users can implement them if needed.
209///
210/// [`OwnedSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedSocket.html
211pub mod fd {
212    pub use super::backend::fd::*;
213}
214
215// The public API modules.
216#[cfg(feature = "event")]
217#[cfg_attr(docsrs, doc(cfg(feature = "event")))]
218pub mod event;
219pub mod ffi;
220#[cfg(not(windows))]
221#[cfg(feature = "fs")]
222#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
223pub mod fs;
224pub mod io;
225#[cfg(all(linux_kernel, not(target_os = "android")))]
226#[cfg(feature = "io_uring")]
227#[cfg_attr(docsrs, doc(cfg(feature = "io_uring")))]
228pub mod io_uring;
229pub mod ioctl;
230#[cfg(not(any(
231    windows,
232    target_os = "espidf",
233    target_os = "horizon",
234    target_os = "vita",
235    target_os = "wasi"
236)))]
237#[cfg(feature = "mm")]
238#[cfg_attr(docsrs, doc(cfg(feature = "mm")))]
239pub mod mm;
240#[cfg(linux_kernel)]
241#[cfg(feature = "mount")]
242#[cfg_attr(docsrs, doc(cfg(feature = "mount")))]
243pub mod mount;
244#[cfg(not(target_os = "wasi"))]
245#[cfg(feature = "net")]
246#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
247pub mod net;
248#[cfg(not(any(windows, target_os = "espidf")))]
249#[cfg(feature = "param")]
250#[cfg_attr(docsrs, doc(cfg(feature = "param")))]
251pub mod param;
252#[cfg(not(windows))]
253#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
254#[cfg_attr(
255    docsrs,
256    doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
257)]
258pub mod path;
259#[cfg(feature = "pipe")]
260#[cfg_attr(docsrs, doc(cfg(feature = "pipe")))]
261#[cfg(not(any(windows, target_os = "wasi")))]
262pub mod pipe;
263#[cfg(not(windows))]
264#[cfg(feature = "process")]
265#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
266pub mod process;
267#[cfg(not(windows))]
268#[cfg(not(target_os = "wasi"))]
269#[cfg(feature = "pty")]
270#[cfg_attr(docsrs, doc(cfg(feature = "pty")))]
271pub mod pty;
272#[cfg(not(windows))]
273#[cfg(feature = "rand")]
274#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
275pub mod rand;
276#[cfg(not(any(
277    windows,
278    target_os = "android",
279    target_os = "espidf",
280    target_os = "horizon",
281    target_os = "vita",
282    target_os = "wasi"
283)))]
284#[cfg(feature = "shm")]
285#[cfg_attr(docsrs, doc(cfg(feature = "shm")))]
286pub mod shm;
287#[cfg(not(windows))]
288#[cfg(feature = "stdio")]
289#[cfg_attr(docsrs, doc(cfg(feature = "stdio")))]
290pub mod stdio;
291#[cfg(feature = "system")]
292#[cfg(not(any(windows, target_os = "wasi")))]
293#[cfg_attr(docsrs, doc(cfg(feature = "system")))]
294pub mod system;
295#[cfg(not(any(windows, target_os = "horizon", target_os = "vita")))]
296#[cfg(feature = "termios")]
297#[cfg_attr(docsrs, doc(cfg(feature = "termios")))]
298pub mod termios;
299#[cfg(not(windows))]
300#[cfg(feature = "thread")]
301#[cfg_attr(docsrs, doc(cfg(feature = "thread")))]
302pub mod thread;
303#[cfg(not(any(windows, target_os = "espidf")))]
304#[cfg(feature = "time")]
305#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
306pub mod time;
307
308// "runtime" is also a public API module, but it's only for libc-like users.
309//
310// People have been observed using it in the wild, so as a counter-measure,
311// it now has a name mangled with a random string that will rotate periodically.
312#[cfg(not(windows))]
313#[cfg(feature = "runtime")]
314#[cfg(linux_raw)]
315#[cfg_attr(not(document_experimental_runtime_api), doc(hidden))]
316#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
317pub mod runtime_448b8ad740e2a26f;
318#[cfg(not(windows))]
319#[cfg(feature = "runtime")]
320#[cfg(linux_raw)]
321#[cfg_attr(not(document_experimental_runtime_api), doc(hidden))]
322#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
323pub(crate) use runtime_448b8ad740e2a26f as runtime;
324
325// Declare "fs" as a non-public module if "fs" isn't enabled but we need it for
326// reading procfs.
327#[cfg(not(windows))]
328#[cfg(not(feature = "fs"))]
329#[cfg(all(
330    linux_raw,
331    not(feature = "use-libc-auxv"),
332    not(feature = "use-explicitly-provided-auxv"),
333    any(
334        feature = "param",
335        feature = "runtime",
336        feature = "thread",
337        feature = "time",
338        target_arch = "x86",
339    )
340))]
341#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
342pub(crate) mod fs;
343
344// Similarly, declare `path` as a non-public module if needed.
345#[cfg(not(windows))]
346#[cfg(not(any(feature = "fs", feature = "mount", feature = "net")))]
347#[cfg(all(
348    linux_raw,
349    not(feature = "use-libc-auxv"),
350    not(feature = "use-explicitly-provided-auxv"),
351    any(
352        feature = "param",
353        feature = "runtime",
354        feature = "thread",
355        feature = "time",
356        target_arch = "x86",
357    )
358))]
359pub(crate) mod path;
360
361// Private modules used by multiple public modules.
362#[cfg(not(any(windows, target_os = "espidf")))]
363#[cfg(any(feature = "thread", feature = "time"))]
364mod clockid;
365#[cfg(linux_kernel)]
366#[cfg(any(feature = "io_uring", feature = "runtime"))]
367mod kernel_sigset;
368#[cfg(not(any(windows, target_os = "wasi")))]
369#[cfg(any(
370    feature = "process",
371    feature = "runtime",
372    feature = "termios",
373    feature = "thread",
374    all(bsd, feature = "event"),
375    all(linux_kernel, feature = "net")
376))]
377mod pid;
378#[cfg(any(feature = "process", feature = "thread"))]
379#[cfg(linux_kernel)]
380mod prctl;
381#[cfg(not(any(windows, target_os = "espidf", target_os = "wasi")))]
382#[cfg(any(
383    feature = "io_uring",
384    feature = "process",
385    feature = "runtime",
386    all(bsd, feature = "event")
387))]
388mod signal;
389#[cfg(any(
390    feature = "fs",
391    feature = "event",
392    feature = "process",
393    feature = "runtime",
394    feature = "thread",
395    feature = "time",
396    all(feature = "event", any(bsd, linux_kernel, windows, target_os = "wasi")),
397    all(
398        linux_raw,
399        not(feature = "use-libc-auxv"),
400        not(feature = "use-explicitly-provided-auxv"),
401        any(
402            feature = "param",
403            feature = "process",
404            feature = "runtime",
405            feature = "time",
406            target_arch = "x86",
407        )
408    )
409))]
410mod timespec;
411#[cfg(not(any(windows, target_os = "wasi")))]
412#[cfg(any(
413    feature = "fs",
414    feature = "process",
415    feature = "thread",
416    all(
417        linux_raw,
418        not(feature = "use-libc-auxv"),
419        not(feature = "use-explicitly-provided-auxv"),
420        any(
421            feature = "param",
422            feature = "runtime",
423            feature = "time",
424            target_arch = "x86",
425        )
426    ),
427    all(linux_kernel, feature = "net")
428))]
429mod ugid;
430
431#[cfg(doc)]
432#[cfg_attr(docsrs, doc(cfg(doc)))]
433pub mod not_implemented;