libc/lib.rs
1//! Raw FFI bindings to platform system libraries.
2//!
3//! # Usage Guidelines
4//!
5//! `libc` exposes non-Rust interfaces in Rust, which makes for some caveats to its use that are
6//! not present in most Rust libraries. Observing the following guidelines are recommended to help
7//! avoid soundness and stability pitfalls.
8//!
9//! 1. *Never* construct a `libc` struct with `MaybeUninit::uninit()`, initialize it, then call
10//! `assume_init`. Many structures have padding fields or may gain fields in the future, and
11//! it is far too easy to end up calling `assume_init` on partially initialized data.
12//!
13//! Instead, use `MaybeUninit::zeroed()` or the `Default` implementations that are slowly being
14//! added. Alternatively, access fields only via raw pointer without ever using `assume_init`.
15//!
16//! 2. Avoid relying on the exact value of constants, the exact length of arrays, or the exact
17//! types of type aliases, as they may change across `libc` versions. That is, if `libc`
18//! contains code like:
19//!
20//! <!-- relevant for how rustdoc displays these structs:
21//! https://github.com/rust-lang/rust/issues/102456 -->
22//! ```ignore
23//! const IFNAMSIZ: usize = 16;
24//!
25//! pub struct ifreq {
26//! pub ifr_name: [c_char; IFNAMSIZ],
27//! // ...
28//! }
29//!
30//! extern "C" {
31//! pub fn time(time: *mut time_t) -> time_t;
32//! }
33//! ```
34//!
35//! Then avoid writing code like:
36//!
37//! ```ignore
38//! // Bad assumption that the length will always be 16.
39//! fn takes_ifr_name(ifr_name: [c_char; 16]) { /* ... */ }
40//!
41//! fn process_ifr(ifr: ifreq) {
42//! takes_ifr_name(ifr.ifr_name);
43//! }
44//!
45//! // Bad assumption that `time_t` will always be an `i64`. Use `-> time_t` instead, or
46//! // explicitly cast to an `i64`.`
47//! fn get_time() -> i64 {
48//! unsafe { time(ptr::null_mut()) }
49//! }
50//!
51//! ```
52//!
53//! For `takes_ifr_name`, use `[c_char; IFNAMSIZ]` or just `&[c_char]` instead. For `get_time`,
54//! return a `time_t` or explicitly cast to an `i64`.
55//!
56//! Along the same lines, if you write code along the lines of `assert_eq!(libc::ELAST, 97)`,
57//! expect that there may be a release where this starts to fail.
58//!
59//! 3. Do not name `__c_anonymous_*` types anywhere, which exist to represent anonymous fields in
60//! C. For example, FreeBSD defines:
61//!
62//! ```c
63//! struct filestat {
64//! int fs_type;
65//! // ...
66//! struct { struct filestat stqe_next; } next;
67//! };
68//! ```
69//!
70//! Which is represented in `libc` as:
71//!
72//! ```ignore
73//! struct filestat {
74//! fs_type: c_int,
75//! // ...
76//! next: __c_anonymous_filestat,
77//! }
78//!
79//! struct __c_anonymous_filestat { stqe_next: *mut filestat }
80//! ```
81//!
82//! Accessing `some_filestat.next.stqe_next` is completely fine, but `__c_anonymous_filestat`
83//! should not be used anywhere (e.g. in a function signature). This is done to permit `libc` to
84//! switch to anonymous fields if the feature is ever added to Rust.
85//!
86//! 4. Avoid accessing fields with names such as `__reserved`, `_pad`, or `_spare`. Usually the
87//! platform libraries use these to allow adding new fields without changing the size of a
88//! struct, but this means their types change frequently.
89//!
90//! 5. Be aware of deprecation warnings. These are used as a way to migrate necessary API changes.
91//!
92//! # Cargo Features
93//!
94//! - `std`: by default `libc` assumes that the standard library contains link directives necessary
95//! to use the APIs in this crate. If `std` is disabled, `libc` will emit the directives instead.
96//!
97//! This feature is slated for removal in `libc` 1.0. The intention is that no-std users of
98//! `libc` should use their own `#[link]` attributes, `rustc-link-lib` build script directives,
99//! or `-l` arguments for only the system libraries they need to link, rather than `libc`
100//! possibly linking more than is needed or available. If you are using `libc` without the `std`
101//! feature, consider starting to add link directives now for a smoother 1.0 transition.
102//!
103//! - `extra_traits`: all types in `libc` implement `Clone`, `Copy`, and `Debug`. The
104//! `extra_traits` feature adds `Eq`, `Hash`, and `PartialEq`.
105//!
106//! This feature is expected to be removed in libc 1.0. Libraries should instead hash or check
107//! equality of only needed fields.
108//!
109//! - The features `const-extern-fn`, `align`, and `use_std` are all deprecated and do nothing.
110//!
111//! # Stability Expectations
112//!
113//! Due to `libc`'s position in the ecosystem, it can effectively never publish semver-breaking
114//! releases. However, the API that `libc` binds changes _all the time_; sometimes in ways that
115//! are harmless, sometimes in ways that are technically API-breaking for all users but unlikely
116//! to be noticed (e.g. removing deprecated API), and sometimes in ways that are nonbreaking in
117//! C but translate to breaking changes in Rust (e.g. changing the type of an integer). `libc`
118//! tries to strike a balance but all of this means that unfortunately, `libc` must occasionally
119//! ship changes within a semver-compatible release that are technically semver-breaking.
120//!
121//! The following are examples of changes that fall into this category:
122//!
123//! - Fields are added to a struct that is otherwise exhaustive.
124//! - Fields with names such as `padding` or `reserved` change type or are removed.
125//! - The length of an array type changes.
126//! - A struct field (with available padding) is changed from `int` to `long`.
127//!
128//! In general, `libc` aims to follow platform API changes, even when this means changes that are
129//! user-visible in Rust. There are a few guidelines used here:
130//!
131//! - Adding struct fields is not considered breaking, nor is changing fields named `reserved`,
132//! `padding`, or similar. This is because users are expected to use field-by-field
133//! initialization.
134//! - Changing type aliases, values of constants, or array lengths is not considered breaking.
135//! - If the platform libc has accepted breakage on the C side (typically in the form of removing
136//! old API), the `libc` crate will follow suit.
137//! - Where possible, `#[deprecated(...)]` will be used to warn about changes before applying them.
138//! Alternative mitigations may be considered.
139//! - Potentially breaking changes will be well-identified in release notes.
140//! - Beyond this, public API is not expected to change on Tier 1 targets. Tier 2 targets have
141//! relaxed API stability requirements, and API stability is not enforced on tier 3 targets.
142//!
143//! While this section seems scary, keep in mind that it is meant to cover worst-case scenarios. In
144//! practice, breakage is rare and following the above-discussed [Usage Guidelines](#usage-guidelines)
145//! means that most `libc` users will never encounter a problem.
146
147// Make it a bit easier to build without Cargo
148#![crate_name = "libc"]
149#![crate_type = "rlib"]
150// Pretty much all C API doesn't match Rust conventions.
151#![allow(nonstandard_style)]
152// Not all macros and all patterns are used on all targets.
153#![allow(unused_macros)]
154#![allow(unused_macro_rules)]
155// All traits should be `Copy` and `Debug`.
156#![warn(missing_copy_implementations)]
157#![warn(missing_debug_implementations)]
158// Downgrade deny to a warning.
159#![warn(overflowing_literals)]
160// Prepare for a future upgrade.
161#![warn(rust_2024_compatibility)]
162// Things missing for 2024 that are blocked on MSRV or breakage.
163#![allow(missing_unsafe_on_extern)]
164#![allow(edition_2024_expr_fragment_specifier)]
165// Allowed globally, the warning is enabled in individual modules as we work through them
166#![allow(unsafe_op_in_unsafe_fn)]
167#![cfg_attr(libc_deny_warnings, deny(warnings))]
168// Attributes needed when building as part of the standard library
169#![cfg_attr(feature = "rustc-dep-of-std", feature(link_cfg, no_core))]
170#![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))]
171// Some targets don't need `link_cfg` and emit a warning.
172#![cfg_attr(feature = "rustc-dep-of-std", allow(unused_features))]
173// DIFF(1.0): The thread local references that raise this lint were removed in 1.0
174#![cfg_attr(feature = "rustc-dep-of-std", allow(static_mut_refs))]
175#![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)]
176#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
177
178#[macro_use]
179mod macros;
180mod new;
181
182cfg_if! {
183 if #[cfg(feature = "rustc-dep-of-std")] {
184 extern crate rustc_std_workspace_core as core;
185 }
186}
187
188pub use core::ffi::c_void;
189
190#[allow(unused_imports)] // needed while the module is empty on some platforms
191pub use new::*;
192
193cfg_if! {
194 if #[cfg(windows)] {
195 mod primitives;
196 pub use crate::primitives::*;
197
198 mod windows;
199 pub use crate::windows::*;
200
201 prelude!();
202 } else if #[cfg(target_os = "fuchsia")] {
203 mod primitives;
204 pub use crate::primitives::*;
205
206 mod fuchsia;
207 pub use crate::fuchsia::*;
208
209 prelude!();
210 } else if #[cfg(target_os = "switch")] {
211 mod primitives;
212 pub use primitives::*;
213
214 mod switch;
215 pub use switch::*;
216
217 prelude!();
218 } else if #[cfg(target_os = "psp")] {
219 mod primitives;
220 pub use primitives::*;
221
222 mod psp;
223 pub use crate::psp::*;
224
225 prelude!();
226 } else if #[cfg(target_os = "vxworks")] {
227 mod primitives;
228 pub use crate::primitives::*;
229
230 mod vxworks;
231 pub use crate::vxworks::*;
232
233 prelude!();
234 } else if #[cfg(target_os = "qurt")] {
235 mod primitives;
236 pub use crate::primitives::*;
237
238 mod qurt;
239 pub use crate::qurt::*;
240
241 prelude!();
242 } else if #[cfg(target_os = "solid_asp3")] {
243 mod primitives;
244 pub use crate::primitives::*;
245
246 mod solid;
247 pub use crate::solid::*;
248
249 prelude!();
250 } else if #[cfg(unix)] {
251 mod primitives;
252 pub use crate::primitives::*;
253
254 mod unix;
255 pub use crate::unix::*;
256
257 prelude!();
258 } else if #[cfg(target_os = "hermit")] {
259 mod primitives;
260 pub use crate::primitives::*;
261
262 mod hermit;
263 pub use crate::hermit::*;
264
265 prelude!();
266 } else if #[cfg(target_os = "teeos")] {
267 mod primitives;
268 pub use primitives::*;
269
270 mod teeos;
271 pub use teeos::*;
272
273 prelude!();
274 } else if #[cfg(target_os = "trusty")] {
275 mod primitives;
276 pub use crate::primitives::*;
277
278 mod trusty;
279 pub use crate::trusty::*;
280
281 prelude!();
282 } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
283 mod primitives;
284 pub use crate::primitives::*;
285
286 mod sgx;
287 pub use crate::sgx::*;
288
289 prelude!();
290 } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
291 mod primitives;
292 pub use crate::primitives::*;
293
294 mod wasi;
295 pub use crate::wasi::*;
296
297 prelude!();
298 } else if #[cfg(target_os = "xous")] {
299 mod primitives;
300 pub use crate::primitives::*;
301
302 mod xous;
303 pub use crate::xous::*;
304
305 prelude!();
306 } else {
307 // non-supported targets: empty...
308 }
309}