rustix/
lib.rs

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