summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..51fbdba
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,395 @@
+//! `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: usize = 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: usize = 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.
+//!
+//! 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
+//! [`getrandom`]: https://crates.io/crates/getrandom
+//! [`bitflags`]: https://crates.io/crates/bitflags
+//! [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
+//! [`OwnedFd`]: https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html
+//! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
+//! [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html
+//! [`Arg`]: https://docs.rs/rustix/*/rustix/path/trait.Arg.html
+//! [support for externally defined flags]: https://docs.rs/bitflags/*/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(doc_cfg, 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(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)]
+// 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)
+)]
+
+#[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;
+
+// Internal utilities.
+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.
+///
+/// Users can use this to avoid needing to import anything else to use the same
+/// versions of these types and traits.
+pub mod fd {
+ use super::backend;
+
+ // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on
+ // Windows due to them having blanket impls on Windows, so users must
+ // implement `AsSocket` etc.
+ #[cfg(windows)]
+ pub use backend::fd::{AsRawSocket, AsSocket, FromRawSocket, IntoRawSocket};
+
+ pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+}
+
+// The public API modules.
+#[cfg(feature = "event")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "event")))]
+pub mod event;
+#[cfg(not(windows))]
+pub mod ffi;
+#[cfg(not(windows))]
+#[cfg(feature = "fs")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
+pub mod fs;
+pub mod io;
+#[cfg(linux_kernel)]
+#[cfg(feature = "io_uring")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))]
+pub mod io_uring;
+pub mod ioctl;
+#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
+#[cfg(feature = "mm")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "mm")))]
+pub mod mm;
+#[cfg(linux_kernel)]
+#[cfg(feature = "mount")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "mount")))]
+pub mod mount;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[cfg(feature = "net")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "net")))]
+pub mod net;
+#[cfg(not(any(windows, target_os = "espidf")))]
+#[cfg(feature = "param")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "param")))]
+pub mod param;
+#[cfg(not(windows))]
+#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
+#[cfg_attr(
+ doc_cfg,
+ doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
+)]
+pub mod path;
+#[cfg(feature = "pipe")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "pipe")))]
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub mod pipe;
+#[cfg(not(windows))]
+#[cfg(feature = "process")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "process")))]
+pub mod process;
+#[cfg(feature = "procfs")]
+#[cfg(linux_kernel)]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub mod procfs;
+#[cfg(not(windows))]
+#[cfg(not(target_os = "wasi"))]
+#[cfg(feature = "pty")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "pty")))]
+pub mod pty;
+#[cfg(not(windows))]
+#[cfg(feature = "rand")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
+pub mod rand;
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "espidf",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+#[cfg(feature = "shm")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "shm")))]
+pub mod shm;
+#[cfg(not(windows))]
+#[cfg(feature = "stdio")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "stdio")))]
+pub mod stdio;
+#[cfg(feature = "system")]
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "system")))]
+pub mod system;
+#[cfg(not(any(windows, target_os = "vita")))]
+#[cfg(feature = "termios")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "termios")))]
+pub mod termios;
+#[cfg(not(windows))]
+#[cfg(feature = "thread")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "thread")))]
+pub mod thread;
+#[cfg(not(any(windows, target_os = "espidf")))]
+#[cfg(feature = "time")]
+#[cfg_attr(doc_cfg, 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(doc_cfg, doc(cfg(feature = "runtime")))]
+pub mod runtime;
+
+// Temporarily provide some mount functions for use in the fs module for
+// backwards compatibility.
+#[cfg(linux_kernel)]
+#[cfg(all(feature = "fs", not(feature = "mount")))]
+pub(crate) mod mount;
+
+// 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 = "process",
+ feature = "runtime",
+ feature = "time",
+ target_arch = "x86",
+ )
+))]
+#[cfg_attr(doc_cfg, 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 = "process",
+ feature = "runtime",
+ 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", target_arch = "x86"))]
+mod clockid;
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg(any(
+ feature = "procfs",
+ 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 = "process", feature = "runtime", all(bsd, feature = "event")))]
+mod signal;
+#[cfg(not(windows))]
+#[cfg(any(
+ feature = "fs",
+ feature = "process",
+ feature = "runtime",
+ feature = "thread",
+ feature = "time",
+ 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;