| //! `rustix` provides efficient memory-safe and [I/O-safe] wrappers to |
| //! POSIX-like, Unix-like, Linux, and Winsock syscall-like APIs, with |
| //! configurable backends. |
| //! |
| //! With rustix, you can write code like this: |
| //! |
| //! ``` |
| //! # #[cfg(feature = "net")] |
| //! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> { |
| //! # use rustix::net::RecvFlags; |
| //! let (nread, _received) = rustix::net::recv(&sock, buf, RecvFlags::PEEK)?; |
| //! # let _ = nread; |
| //! # Ok(()) |
| //! # } |
| //! ``` |
| //! |
| //! instead of like this: |
| //! |
| //! ``` |
| //! # #[cfg(feature = "net")] |
| //! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> { |
| //! # #[cfg(unix)] |
| //! # use std::os::unix::io::AsRawFd; |
| //! # #[cfg(target_os = "wasi")] |
| //! # use std::os::wasi::io::AsRawFd; |
| //! # #[cfg(windows)] |
| //! # use windows_sys::Win32::Networking::WinSock as libc; |
| //! # #[cfg(windows)] |
| //! # use std::os::windows::io::AsRawSocket; |
| //! # const MSG_PEEK: i32 = libc::MSG_PEEK; |
| //! let nread = unsafe { |
| //! #[cfg(any(unix, target_os = "wasi"))] |
| //! let raw = sock.as_raw_fd(); |
| //! #[cfg(windows)] |
| //! let raw = sock.as_raw_socket(); |
| //! match libc::recv( |
| //! raw as _, |
| //! buf.as_mut_ptr().cast(), |
| //! buf.len().try_into().unwrap_or(i32::MAX as _), |
| //! MSG_PEEK, |
| //! ) { |
| //! -1 => return Err(std::io::Error::last_os_error()), |
| //! nread => nread as usize, |
| //! } |
| //! }; |
| //! # let _ = nread; |
| //! # Ok(()) |
| //! # } |
| //! ``` |
| //! |
| //! rustix's APIs perform the following tasks: |
| //! - Error values are translated to [`Result`]s. |
| //! - Buffers are passed as Rust slices. |
| //! - Out-parameters are presented as return values. |
| //! - Path arguments use [`Arg`], so they accept any string type. |
| //! - File descriptors are passed and returned via [`AsFd`] and [`OwnedFd`] |
| //! instead of bare integers, ensuring I/O safety. |
| //! - Constants use `enum`s and [`bitflags`] types, and enable [support for |
| //! externally defined flags]. |
| //! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed. |
| //! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic. |
| //! - Functions that return strings automatically allocate sufficient memory |
| //! and retry the syscall as needed to determine the needed length. |
| //! - Functions and types which need `l` prefixes or `64` suffixes to enable |
| //! large-file support (LFS) are used automatically. File sizes and offsets |
| //! are always presented as `u64` and `i64`. |
| //! - Behaviors that depend on the sizes of C types like `long` are hidden. |
| //! - In some places, more human-friendly and less historical-accident names |
| //! are used (and documentation aliases are used so that the original names |
| //! can still be searched for). |
| //! - Provide y2038 compatibility, on platforms which support this. |
| //! - Correct selected platform bugs, such as behavioral differences when |
| //! running under seccomp. |
| //! - Use `timespec` for timestamps and timeouts instead of `timeval` and |
| //! `c_int` milliseconds. |
| //! |
| //! Things they don't do include: |
| //! - Detecting whether functions are supported at runtime, except in specific |
| //! cases where new interfaces need to be detected to support y2038 and LFS. |
| //! - Hiding significant differences between platforms. |
| //! - Restricting ambient authorities. |
| //! - Imposing sandboxing features such as filesystem path or network address |
| //! sandboxing. |
| //! |
| //! See [`cap-std`], [`system-interface`], and [`io-streams`] for libraries |
| //! which do hide significant differences between platforms, and [`cap-std`] |
| //! which does perform sandboxing and restricts ambient authorities. |
| //! |
| //! [`cap-std`]: https://crates.io/crates/cap-std |
| //! [`system-interface`]: https://crates.io/crates/system-interface |
| //! [`io-streams`]: https://crates.io/crates/io-streams |
| //! [`bitflags`]: bitflags |
| //! [`AsFd`]: crate::fd::AsFd |
| //! [`OwnedFd`]: crate::fd::OwnedFd |
| //! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md |
| //! [`Arg`]: path::Arg |
| //! [support for externally defined flags]: bitflags#externally-defined-flags |
| |
| #![deny(missing_docs)] |
| #![allow(stable_features)] |
| #![cfg_attr(linux_raw, deny(unsafe_code))] |
| #![cfg_attr(rustc_attrs, feature(rustc_attrs))] |
| #![cfg_attr(docsrs, feature(doc_cfg))] |
| #![cfg_attr(all(wasi_ext, target_os = "wasi", feature = "std"), feature(wasi_ext))] |
| #![cfg_attr(core_ffi_c, feature(core_ffi_c))] |
| #![cfg_attr(core_c_str, feature(core_c_str))] |
| #![cfg_attr(error_in_core, feature(error_in_core))] |
| #![cfg_attr(all(feature = "alloc", alloc_c_string), feature(alloc_c_string))] |
| #![cfg_attr(all(feature = "alloc", alloc_ffi), feature(alloc_ffi))] |
| #![cfg_attr(not(feature = "std"), no_std)] |
| #![cfg_attr(feature = "rustc-dep-of-std", feature(ip))] |
| #![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))] |
| #![cfg_attr( |
| any(feature = "rustc-dep-of-std", core_intrinsics), |
| feature(core_intrinsics) |
| )] |
| #![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))] |
| #![cfg_attr(not(feature = "all-apis"), allow(dead_code))] |
| // It is common in Linux and libc APIs for types to vary between platforms. |
| #![allow(clippy::unnecessary_cast)] |
| // It is common in Linux and libc APIs for types to vary between platforms. |
| #![allow(clippy::useless_conversion)] |
| // This clippy lint gets too many false positives. |
| #![allow(clippy::needless_lifetimes)] |
| // Until `unnecessary_transmutes` is recognized by our MSRV, don't warn about |
| // it being unrecognized. |
| #![allow(unknown_lints)] |
| // Until `cast_signed` and `cast_unsigned` are supported by our MSRV, don't |
| // warn about transmutes that could be changed to them. |
| #![allow(unnecessary_transmutes)] |
| // Redox and WASI have enough differences that it isn't worth precisely |
| // conditionalizing all the `use`s for them. Similar for if we don't have |
| // "all-apis". |
| #![cfg_attr( |
| any(target_os = "redox", target_os = "wasi", not(feature = "all-apis")), |
| allow(unused_imports) |
| )] |
| // wasip2 conditionally gates stdlib APIs such as `OsStrExt`. |
| // <https://github.com/rust-lang/rust/issues/130323> |
| #![cfg_attr( |
| all( |
| target_os = "wasi", |
| target_env = "p2", |
| any(feature = "fs", feature = "mount", feature = "net"), |
| wasip2, |
| ), |
| feature(wasip2) |
| )] |
| |
| #[cfg(all(feature = "alloc", feature = "rustc-dep-of-std"))] |
| extern crate rustc_std_workspace_alloc as alloc; |
| |
| #[cfg(all(feature = "alloc", not(feature = "rustc-dep-of-std")))] |
| extern crate alloc; |
| |
| // Use `static_assertions` macros if we have them, or a polyfill otherwise. |
| #[cfg(all(test, static_assertions))] |
| #[macro_use] |
| #[allow(unused_imports)] |
| extern crate static_assertions; |
| #[cfg(all(test, not(static_assertions)))] |
| #[macro_use] |
| #[allow(unused_imports)] |
| mod static_assertions; |
| |
| pub mod buffer; |
| #[cfg(not(windows))] |
| #[macro_use] |
| pub(crate) mod cstr; |
| #[macro_use] |
| pub(crate) mod utils; |
| // Polyfill for `std` in `no_std` builds. |
| #[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")] |
| #[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")] |
| pub(crate) mod maybe_polyfill; |
| #[cfg(test)] |
| #[macro_use] |
| pub(crate) mod check_types; |
| #[macro_use] |
| pub(crate) mod bitcast; |
| |
| // linux_raw: Weak symbols are used by the use-libc-auxv feature for |
| // glibc 2.15 support. |
| // |
| // libc: Weak symbols are used to call various functions available in some |
| // versions of libc and not others. |
| #[cfg(any( |
| all(linux_raw, feature = "use-libc-auxv"), |
| all(libc, not(any(windows, target_os = "espidf", target_os = "wasi"))) |
| ))] |
| #[macro_use] |
| mod weak; |
| |
| // Pick the backend implementation to use. |
| #[cfg_attr(libc, path = "backend/libc/mod.rs")] |
| #[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")] |
| #[cfg_attr(wasi, path = "backend/wasi/mod.rs")] |
| mod backend; |
| |
| /// Export the `*Fd` types and traits that are used in rustix's public API. |
| /// |
| /// This module exports the types and traits from [`std::os::fd`], or polyills |
| /// on Rust < 1.66 or on Windows. |
| /// |
| /// On Windows, the polyfill consists of aliases of the socket types and |
| /// traits, For example, [`OwnedSocket`] is aliased to `OwnedFd`, and so on, |
| /// and there are blanket impls for `AsFd` etc. that map to `AsSocket` impls. |
| /// These blanket impls suffice for using the traits, however not for |
| /// implementing them, so this module also exports `AsSocket` and the other |
| /// traits as-is so that users can implement them if needed. |
| /// |
| /// [`OwnedSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedSocket.html |
| pub mod fd { |
| pub use super::backend::fd::*; |
| } |
| |
| // The public API modules. |
| #[cfg(feature = "event")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "event")))] |
| pub mod event; |
| pub mod ffi; |
| #[cfg(not(windows))] |
| #[cfg(feature = "fs")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] |
| pub mod fs; |
| pub mod io; |
| #[cfg(linux_kernel)] |
| #[cfg(feature = "io_uring")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "io_uring")))] |
| pub mod io_uring; |
| pub mod ioctl; |
| #[cfg(not(any( |
| windows, |
| target_os = "espidf", |
| target_os = "horizon", |
| target_os = "vita", |
| target_os = "wasi" |
| )))] |
| #[cfg(feature = "mm")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "mm")))] |
| pub mod mm; |
| #[cfg(linux_kernel)] |
| #[cfg(feature = "mount")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "mount")))] |
| pub mod mount; |
| #[cfg(not(target_os = "wasi"))] |
| #[cfg(feature = "net")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "net")))] |
| pub mod net; |
| #[cfg(not(any(windows, target_os = "espidf")))] |
| #[cfg(feature = "param")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "param")))] |
| pub mod param; |
| #[cfg(not(windows))] |
| #[cfg(any(feature = "fs", feature = "mount", feature = "net"))] |
| #[cfg_attr( |
| docsrs, |
| doc(cfg(any(feature = "fs", feature = "mount", feature = "net"))) |
| )] |
| pub mod path; |
| #[cfg(feature = "pipe")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "pipe")))] |
| #[cfg(not(any(windows, target_os = "wasi")))] |
| pub mod pipe; |
| #[cfg(not(windows))] |
| #[cfg(feature = "process")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "process")))] |
| pub mod process; |
| #[cfg(not(windows))] |
| #[cfg(not(target_os = "wasi"))] |
| #[cfg(feature = "pty")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "pty")))] |
| pub mod pty; |
| #[cfg(not(windows))] |
| #[cfg(feature = "rand")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "rand")))] |
| pub mod rand; |
| #[cfg(not(any( |
| windows, |
| target_os = "android", |
| target_os = "espidf", |
| target_os = "horizon", |
| target_os = "vita", |
| target_os = "wasi" |
| )))] |
| #[cfg(feature = "shm")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "shm")))] |
| pub mod shm; |
| #[cfg(not(windows))] |
| #[cfg(feature = "stdio")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "stdio")))] |
| pub mod stdio; |
| #[cfg(feature = "system")] |
| #[cfg(not(any(windows, target_os = "wasi")))] |
| #[cfg_attr(docsrs, doc(cfg(feature = "system")))] |
| pub mod system; |
| #[cfg(not(any(windows, target_os = "horizon", target_os = "vita")))] |
| #[cfg(feature = "termios")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "termios")))] |
| pub mod termios; |
| #[cfg(not(windows))] |
| #[cfg(feature = "thread")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "thread")))] |
| pub mod thread; |
| #[cfg(not(any(windows, target_os = "espidf")))] |
| #[cfg(feature = "time")] |
| #[cfg_attr(docsrs, doc(cfg(feature = "time")))] |
| pub mod time; |
| |
| // "runtime" is also a public API module, but it's only for libc-like users. |
| #[cfg(not(windows))] |
| #[cfg(feature = "runtime")] |
| #[cfg(linux_raw)] |
| #[cfg_attr(not(document_experimental_runtime_api), doc(hidden))] |
| #[cfg_attr(docsrs, doc(cfg(feature = "runtime")))] |
| pub mod runtime; |
| |
| // Declare "fs" as a non-public module if "fs" isn't enabled but we need it for |
| // reading procfs. |
| #[cfg(not(windows))] |
| #[cfg(not(feature = "fs"))] |
| #[cfg(all( |
| linux_raw, |
| not(feature = "use-libc-auxv"), |
| not(feature = "use-explicitly-provided-auxv"), |
| any( |
| feature = "param", |
| feature = "runtime", |
| feature = "thread", |
| feature = "time", |
| target_arch = "x86", |
| ) |
| ))] |
| #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] |
| pub(crate) mod fs; |
| |
| // Similarly, declare `path` as a non-public module if needed. |
| #[cfg(not(windows))] |
| #[cfg(not(any(feature = "fs", feature = "mount", feature = "net")))] |
| #[cfg(all( |
| linux_raw, |
| not(feature = "use-libc-auxv"), |
| not(feature = "use-explicitly-provided-auxv"), |
| any( |
| feature = "param", |
| feature = "runtime", |
| feature = "thread", |
| feature = "time", |
| target_arch = "x86", |
| ) |
| ))] |
| pub(crate) mod path; |
| |
| // Private modules used by multiple public modules. |
| #[cfg(not(any(windows, target_os = "espidf")))] |
| #[cfg(any(feature = "thread", feature = "time"))] |
| mod clockid; |
| #[cfg(linux_kernel)] |
| #[cfg(any(feature = "io_uring", feature = "runtime"))] |
| mod kernel_sigset; |
| #[cfg(not(any(windows, target_os = "wasi")))] |
| #[cfg(any( |
| feature = "process", |
| feature = "runtime", |
| feature = "termios", |
| feature = "thread", |
| all(bsd, feature = "event"), |
| all(linux_kernel, feature = "net") |
| ))] |
| mod pid; |
| #[cfg(any(feature = "process", feature = "thread"))] |
| #[cfg(linux_kernel)] |
| mod prctl; |
| #[cfg(not(any(windows, target_os = "espidf", target_os = "wasi")))] |
| #[cfg(any( |
| feature = "io_uring", |
| feature = "process", |
| feature = "runtime", |
| all(bsd, feature = "event") |
| ))] |
| mod signal; |
| #[cfg(any( |
| feature = "fs", |
| feature = "event", |
| feature = "process", |
| feature = "runtime", |
| feature = "thread", |
| feature = "time", |
| all(feature = "event", any(bsd, linux_kernel, windows, target_os = "wasi")), |
| all( |
| linux_raw, |
| not(feature = "use-libc-auxv"), |
| not(feature = "use-explicitly-provided-auxv"), |
| any( |
| feature = "param", |
| feature = "process", |
| feature = "runtime", |
| feature = "time", |
| target_arch = "x86", |
| ) |
| ) |
| ))] |
| mod timespec; |
| #[cfg(not(any(windows, target_os = "wasi")))] |
| #[cfg(any( |
| feature = "fs", |
| feature = "process", |
| feature = "thread", |
| all( |
| linux_raw, |
| not(feature = "use-libc-auxv"), |
| not(feature = "use-explicitly-provided-auxv"), |
| any( |
| feature = "param", |
| feature = "runtime", |
| feature = "time", |
| target_arch = "x86", |
| ) |
| ), |
| all(linux_kernel, feature = "net") |
| ))] |
| mod ugid; |
| |
| #[cfg(doc)] |
| #[cfg_attr(docsrs, doc(cfg(doc)))] |
| pub mod not_implemented; |