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: 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(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(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 = "rustc-dep-of-std", feature = "alloc"))]
131extern crate rustc_std_workspace_alloc as alloc;
132
133#[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))]
134extern crate alloc;
135
136// Use `static_assertions` macros if we have them, or a polyfill otherwise.
137#[cfg(all(test, static_assertions))]
138#[macro_use]
139#[allow(unused_imports)]
140extern crate static_assertions;
141#[cfg(all(test, not(static_assertions)))]
142#[macro_use]
143#[allow(unused_imports)]
144mod static_assertions;
145
146// Internal utilities.
147mod buffer;
148#[cfg(not(windows))]
149#[macro_use]
150pub(crate) mod cstr;
151#[macro_use]
152pub(crate) mod utils;
153// Polyfill for `std` in `no_std` builds.
154#[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")]
155#[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")]
156pub(crate) mod maybe_polyfill;
157#[cfg(test)]
158#[macro_use]
159pub(crate) mod check_types;
160#[macro_use]
161pub(crate) mod bitcast;
162
163// linux_raw: Weak symbols are used by the use-libc-auxv feature for
164// glibc 2.15 support.
165//
166// libc: Weak symbols are used to call various functions available in some
167// versions of libc and not others.
168#[cfg(any(
169    all(linux_raw, feature = "use-libc-auxv"),
170    all(libc, not(any(windows, target_os = "espidf", target_os = "wasi")))
171))]
172#[macro_use]
173mod weak;
174
175// Pick the backend implementation to use.
176#[cfg_attr(libc, path = "backend/libc/mod.rs")]
177#[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")]
178#[cfg_attr(wasi, path = "backend/wasi/mod.rs")]
179mod backend;
180
181/// Export the `*Fd` types and traits that are used in rustix's public API.
182///
183/// Users can use this to avoid needing to import anything else to use the same
184/// versions of these types and traits.
185pub mod fd {
186    use super::backend;
187
188    // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on
189    // Windows due to them having blanket impls on Windows, so users must
190    // implement `AsSocket` etc.
191    #[cfg(windows)]
192    pub use backend::fd::{AsRawSocket, AsSocket, FromRawSocket, IntoRawSocket};
193
194    pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
195}
196
197// The public API modules.
198#[cfg(feature = "event")]
199#[cfg_attr(docsrs, doc(cfg(feature = "event")))]
200pub mod event;
201pub mod ffi;
202#[cfg(not(windows))]
203#[cfg(feature = "fs")]
204#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
205pub mod fs;
206pub mod io;
207#[cfg(linux_kernel)]
208#[cfg(feature = "io_uring")]
209#[cfg_attr(docsrs, doc(cfg(feature = "io_uring")))]
210pub mod io_uring;
211pub mod ioctl;
212#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
213#[cfg(feature = "mm")]
214#[cfg_attr(docsrs, doc(cfg(feature = "mm")))]
215pub mod mm;
216#[cfg(linux_kernel)]
217#[cfg(feature = "mount")]
218#[cfg_attr(docsrs, doc(cfg(feature = "mount")))]
219pub mod mount;
220#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
221#[cfg(feature = "net")]
222#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
223pub mod net;
224#[cfg(not(any(windows, target_os = "espidf")))]
225#[cfg(feature = "param")]
226#[cfg_attr(docsrs, doc(cfg(feature = "param")))]
227pub mod param;
228#[cfg(not(windows))]
229#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
230#[cfg_attr(
231    docsrs,
232    doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
233)]
234pub mod path;
235#[cfg(feature = "pipe")]
236#[cfg_attr(docsrs, doc(cfg(feature = "pipe")))]
237#[cfg(not(any(windows, target_os = "wasi")))]
238pub mod pipe;
239#[cfg(not(windows))]
240#[cfg(feature = "process")]
241#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
242pub mod process;
243#[cfg(feature = "procfs")]
244#[cfg(linux_kernel)]
245#[cfg_attr(docsrs, doc(cfg(feature = "procfs")))]
246pub mod procfs;
247#[cfg(not(windows))]
248#[cfg(not(target_os = "wasi"))]
249#[cfg(feature = "pty")]
250#[cfg_attr(docsrs, doc(cfg(feature = "pty")))]
251pub mod pty;
252#[cfg(not(windows))]
253#[cfg(feature = "rand")]
254#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
255pub mod rand;
256#[cfg(not(any(
257    windows,
258    target_os = "android",
259    target_os = "espidf",
260    target_os = "vita",
261    target_os = "wasi"
262)))]
263#[cfg(feature = "shm")]
264#[cfg_attr(docsrs, doc(cfg(feature = "shm")))]
265pub mod shm;
266#[cfg(not(windows))]
267#[cfg(feature = "stdio")]
268#[cfg_attr(docsrs, doc(cfg(feature = "stdio")))]
269pub mod stdio;
270#[cfg(feature = "system")]
271#[cfg(not(any(windows, target_os = "wasi")))]
272#[cfg_attr(docsrs, doc(cfg(feature = "system")))]
273pub mod system;
274#[cfg(not(any(windows, target_os = "vita")))]
275#[cfg(feature = "termios")]
276#[cfg_attr(docsrs, doc(cfg(feature = "termios")))]
277pub mod termios;
278#[cfg(not(windows))]
279#[cfg(feature = "thread")]
280#[cfg_attr(docsrs, doc(cfg(feature = "thread")))]
281pub mod thread;
282#[cfg(not(any(windows, target_os = "espidf")))]
283#[cfg(feature = "time")]
284#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
285pub mod time;
286
287// "runtime" is also a public API module, but it's only for libc-like users.
288#[cfg(not(windows))]
289#[cfg(feature = "runtime")]
290#[cfg(linux_raw)]
291#[cfg_attr(not(document_experimental_runtime_api), doc(hidden))]
292#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
293pub mod runtime;
294
295// Temporarily provide some mount functions for use in the fs module for
296// backwards compatibility.
297#[cfg(linux_kernel)]
298#[cfg(all(feature = "fs", not(feature = "mount")))]
299pub(crate) mod mount;
300
301// Declare "fs" as a non-public module if "fs" isn't enabled but we need it for
302// reading procfs.
303#[cfg(not(windows))]
304#[cfg(not(feature = "fs"))]
305#[cfg(all(
306    linux_raw,
307    not(feature = "use-libc-auxv"),
308    not(feature = "use-explicitly-provided-auxv"),
309    any(
310        feature = "param",
311        feature = "process",
312        feature = "runtime",
313        feature = "time",
314        target_arch = "x86",
315    )
316))]
317#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
318pub(crate) mod fs;
319
320// Similarly, declare `path` as a non-public module if needed.
321#[cfg(not(windows))]
322#[cfg(not(any(feature = "fs", feature = "mount", feature = "net")))]
323#[cfg(all(
324    linux_raw,
325    not(feature = "use-libc-auxv"),
326    not(feature = "use-explicitly-provided-auxv"),
327    any(
328        feature = "param",
329        feature = "process",
330        feature = "runtime",
331        feature = "time",
332        target_arch = "x86",
333    )
334))]
335pub(crate) mod path;
336
337// Private modules used by multiple public modules.
338#[cfg(not(any(windows, target_os = "espidf")))]
339#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
340mod clockid;
341#[cfg(not(any(windows, target_os = "wasi")))]
342#[cfg(any(
343    feature = "procfs",
344    feature = "process",
345    feature = "runtime",
346    feature = "termios",
347    feature = "thread",
348    all(bsd, feature = "event"),
349    all(linux_kernel, feature = "net")
350))]
351mod pid;
352#[cfg(any(feature = "process", feature = "thread"))]
353#[cfg(linux_kernel)]
354mod prctl;
355#[cfg(not(any(windows, target_os = "espidf", target_os = "wasi")))]
356#[cfg(any(feature = "process", feature = "runtime", all(bsd, feature = "event")))]
357mod signal;
358#[cfg(not(windows))]
359#[cfg(any(
360    feature = "fs",
361    feature = "process",
362    feature = "runtime",
363    feature = "thread",
364    feature = "time",
365    all(
366        linux_raw,
367        not(feature = "use-libc-auxv"),
368        not(feature = "use-explicitly-provided-auxv"),
369        any(
370            feature = "param",
371            feature = "process",
372            feature = "runtime",
373            feature = "time",
374            target_arch = "x86",
375        )
376    )
377))]
378mod timespec;
379#[cfg(not(any(windows, target_os = "wasi")))]
380#[cfg(any(
381    feature = "fs",
382    feature = "process",
383    feature = "thread",
384    all(
385        linux_raw,
386        not(feature = "use-libc-auxv"),
387        not(feature = "use-explicitly-provided-auxv"),
388        any(
389            feature = "param",
390            feature = "runtime",
391            feature = "time",
392            target_arch = "x86",
393        )
394    ),
395    all(linux_kernel, feature = "net")
396))]
397mod ugid;