1 //! `rustix` provides efficient memory-safe and [I/O-safe] wrappers to 2 //! POSIX-like, Unix-like, Linux, and Winsock2 syscall-like APIs, with 3 //! configurable backends. 4 //! 5 //! With rustix, you can write code like this: 6 //! 7 //! ```rust 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 //! ```rust 20 //! # #[cfg(feature = "net")] 21 //! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> { 22 //! # use std::convert::TryInto; 23 //! # #[cfg(unix)] 24 //! # use std::os::unix::io::AsRawFd; 25 //! # #[cfg(target_os = "wasi")] 26 //! # use std::os::wasi::io::AsRawFd; 27 //! # #[cfg(windows)] 28 //! # use windows_sys::Win32::Networking::WinSock as libc; 29 //! # #[cfg(windows)] 30 //! # use std::os::windows::io::AsRawSocket; 31 //! # const MSG_PEEK: i32 = libc::MSG_PEEK; 32 //! let nread: usize = unsafe { 33 //! #[cfg(any(unix, target_os = "wasi"))] 34 //! let raw = sock.as_raw_fd(); 35 //! #[cfg(windows)] 36 //! let raw = sock.as_raw_socket(); 37 //! match libc::recv( 38 //! raw as _, 39 //! buf.as_mut_ptr().cast(), 40 //! buf.len().try_into().unwrap_or(i32::MAX as _), 41 //! MSG_PEEK, 42 //! ) { 43 //! -1 => return Err(std::io::Error::last_os_error()), 44 //! nread => nread as usize, 45 //! } 46 //! }; 47 //! # let _ = nread; 48 //! # Ok(()) 49 //! # } 50 //! ``` 51 //! 52 //! rustix's APIs perform the following tasks: 53 //! - Error values are translated to [`Result`]s. 54 //! - Buffers are passed as Rust slices. 55 //! - Out-parameters are presented as return values. 56 //! - Path arguments use [`Arg`], so they accept any string type. 57 //! - File descriptors are passed and returned via [`AsFd`] and [`OwnedFd`] 58 //! instead of bare integers, ensuring I/O safety. 59 //! - Constants use `enum`s and [`bitflags`] types. 60 //! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed. 61 //! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic. 62 //! - Functions and types which need `l` prefixes or `64` suffixes to enable 63 //! large-file support are used automatically, and file sizes and offsets 64 //! are presented as `u64` and `i64`. 65 //! - Behaviors that depend on the sizes of C types like `long` are hidden. 66 //! - In some places, more human-friendly and less historical-accident names 67 //! are used (and documentation aliases are used so that the original names 68 //! can still be searched for). 69 //! - Provide y2038 compatibility, on platforms which support this. 70 //! - Correct selected platform bugs, such as behavioral differences when 71 //! running under seccomp. 72 //! 73 //! Things they don't do include: 74 //! - Detecting whether functions are supported at runtime. 75 //! - Hiding significant differences between platforms. 76 //! - Restricting ambient authorities. 77 //! - Imposing sandboxing features such as filesystem path or network address 78 //! sandboxing. 79 //! 80 //! See [`cap-std`], [`system-interface`], and [`io-streams`] for libraries 81 //! which do hide significant differences between platforms, and [`cap-std`] 82 //! which does perform sandboxing and restricts ambient authorities. 83 //! 84 //! [`cap-std`]: https://crates.io/crates/cap-std 85 //! [`system-interface`]: https://crates.io/crates/system-interface 86 //! [`io-streams`]: https://crates.io/crates/io-streams 87 //! [`getrandom`]: https://crates.io/crates/getrandom 88 //! [`bitflags`]: https://crates.io/crates/bitflags 89 //! [`AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html 90 //! [`OwnedFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/struct.OwnedFd.html 91 //! [io-lifetimes crate]: https://crates.io/crates/io-lifetimes 92 //! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md 93 //! [`Result`]: https://docs.rs/rustix/latest/rustix/io/type.Result.html 94 //! [`Arg`]: https://docs.rs/rustix/latest/rustix/path/trait.Arg.html 95 96 #![deny(missing_docs)] 97 #![allow(stable_features)] 98 #![cfg_attr(linux_raw, deny(unsafe_code))] 99 #![cfg_attr(rustc_attrs, feature(rustc_attrs))] 100 #![cfg_attr(doc_cfg, feature(doc_cfg))] 101 #![cfg_attr(all(wasi_ext, target_os = "wasi", feature = "std"), feature(wasi_ext))] 102 #![cfg_attr( 103 all(linux_raw, naked_functions, target_arch = "x86"), 104 feature(naked_functions) 105 )] 106 #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] 107 #![cfg_attr(core_ffi_c, feature(core_ffi_c))] 108 #![cfg_attr(core_c_str, feature(core_c_str))] 109 #![cfg_attr(alloc_c_string, feature(alloc_ffi))] 110 #![cfg_attr(alloc_c_string, feature(alloc_c_string))] 111 #![cfg_attr(not(feature = "std"), no_std)] 112 #![cfg_attr(feature = "rustc-dep-of-std", feature(core_intrinsics))] 113 #![cfg_attr(feature = "rustc-dep-of-std", feature(ip))] 114 #![cfg_attr( 115 all(not(feature = "rustc-dep-of-std"), core_intrinsics), 116 feature(core_intrinsics) 117 )] 118 #![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))] 119 #![cfg_attr(not(feature = "all-apis"), allow(dead_code))] 120 // Clamp depends on Rust 1.50 which is newer than our MSRV. 121 #![allow(clippy::manual_clamp)] 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 127 // precisely conditionallizing all the `use`s for them. 128 #![cfg_attr(any(target_os = "redox", target_os = "wasi"), allow(unused_imports))] 129 130 #[cfg(not(feature = "rustc-dep-of-std"))] 131 extern crate alloc; 132 133 // Internal utilities. 134 #[cfg(not(windows))] 135 #[macro_use] 136 pub(crate) mod cstr; 137 #[macro_use] 138 pub(crate) mod const_assert; 139 pub(crate) mod utils; 140 141 // Pick the backend implementation to use. 142 #[cfg_attr(libc, path = "backend/libc/mod.rs")] 143 #[cfg_attr(linux_raw, path = "backend/linux_raw/mod.rs")] 144 #[cfg_attr(wasi, path = "backend/wasi/mod.rs")] 145 mod backend; 146 147 /// Export the `*Fd` types and traits that are used in rustix's public API. 148 /// 149 /// Users can use this to avoid needing to import anything else to use the same 150 /// versions of these types and traits. 151 pub mod fd { 152 use super::backend; 153 #[cfg(windows)] 154 pub use backend::fd::AsSocket; 155 pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; 156 } 157 158 // The public API modules. 159 #[cfg(not(windows))] 160 pub mod ffi; 161 #[cfg(not(windows))] 162 #[cfg(feature = "fs")] 163 #[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] 164 pub mod fs; 165 pub mod io; 166 #[cfg(any(target_os = "android", target_os = "linux"))] 167 #[cfg(feature = "io_uring")] 168 #[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))] 169 pub mod io_uring; 170 #[cfg(not(any(windows, target_os = "wasi")))] 171 #[cfg(feature = "mm")] 172 #[cfg_attr(doc_cfg, doc(cfg(feature = "mm")))] 173 pub mod mm; 174 #[cfg(not(any(target_os = "redox", target_os = "wasi")))] 175 #[cfg(feature = "net")] 176 #[cfg_attr(doc_cfg, doc(cfg(feature = "net")))] 177 pub mod net; 178 #[cfg(not(windows))] 179 #[cfg(feature = "param")] 180 #[cfg_attr(doc_cfg, doc(cfg(feature = "param")))] 181 pub mod param; 182 #[cfg(not(windows))] 183 #[cfg(any(feature = "fs", feature = "net"))] 184 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "fs", feature = "net"))))] 185 pub mod path; 186 #[cfg(not(windows))] 187 #[cfg(feature = "process")] 188 #[cfg_attr(doc_cfg, doc(cfg(feature = "process")))] 189 pub mod process; 190 #[cfg(not(windows))] 191 #[cfg(feature = "rand")] 192 #[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))] 193 pub mod rand; 194 #[cfg(not(windows))] 195 #[cfg(feature = "termios")] 196 #[cfg_attr(doc_cfg, doc(cfg(feature = "termios")))] 197 pub mod termios; 198 #[cfg(not(windows))] 199 #[cfg(feature = "thread")] 200 #[cfg_attr(doc_cfg, doc(cfg(feature = "thread")))] 201 pub mod thread; 202 #[cfg(not(windows))] 203 #[cfg(feature = "time")] 204 #[cfg_attr(doc_cfg, doc(cfg(feature = "time")))] 205 pub mod time; 206 207 // "runtime" is also a public API module, but it's only for libc-like users. 208 #[cfg(not(windows))] 209 #[cfg(feature = "runtime")] 210 #[doc(hidden)] 211 #[cfg_attr(doc_cfg, doc(cfg(feature = "runtime")))] 212 pub mod runtime; 213 214 // We have some internal interdependencies in the API features, so for now, 215 // for API features that aren't enabled, declare them as `pub(crate)` so 216 // that they're not public, but still available for internal use. 217 218 #[cfg(not(windows))] 219 #[cfg(all( 220 not(feature = "param"), 221 any(feature = "runtime", feature = "time", target_arch = "x86"), 222 ))] 223 pub(crate) mod param; 224 #[cfg(not(windows))] 225 #[cfg(not(any(feature = "fs", feature = "net")))] 226 pub(crate) mod path; 227 #[cfg(not(windows))] 228 #[cfg(not(feature = "process"))] 229 pub(crate) mod process; 230