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.
146147// 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)]
177178#[macro_use]
179mod macros;
180mod new;
181182cfg_if! {
183if #[cfg(feature = "rustc-dep-of-std")] {
184extern crate rustc_std_workspace_core as core;
185 }
186}
187188pub use core::ffi::c_void;
189190#[allow(unused_imports)] // needed while the module is empty on some platforms
191pub use new::*;
192193cfg_if! {
194if #[cfg(windows)] {
195mod primitives;
196pub use crate::primitives::*;
197198mod windows;
199pub use crate::windows::*;
200201prelude!();
202 } else if #[cfg(target_os = "fuchsia")] {
203mod primitives;
204pub use crate::primitives::*;
205206mod fuchsia;
207pub use crate::fuchsia::*;
208209prelude!();
210 } else if #[cfg(target_os = "switch")] {
211mod primitives;
212pub use primitives::*;
213214mod switch;
215pub use switch::*;
216217prelude!();
218 } else if #[cfg(target_os = "psp")] {
219mod primitives;
220pub use primitives::*;
221222mod psp;
223pub use crate::psp::*;
224225prelude!();
226 } else if #[cfg(target_os = "vxworks")] {
227mod primitives;
228pub use crate::primitives::*;
229230mod vxworks;
231pub use crate::vxworks::*;
232233prelude!();
234 } else if #[cfg(target_os = "qurt")] {
235mod primitives;
236pub use crate::primitives::*;
237238mod qurt;
239pub use crate::qurt::*;
240241prelude!();
242 } else if #[cfg(target_os = "solid_asp3")] {
243mod primitives;
244pub use crate::primitives::*;
245246mod solid;
247pub use crate::solid::*;
248249prelude!();
250 } else if #[cfg(unix)] {
251mod primitives;
252pub use crate::primitives::*;
253254mod unix;
255pub use crate::unix::*;
256257mod types {
//! Platform-agnostic support types.
use core::mem::MaybeUninit;
use crate::prelude::*;
/// A transparent wrapper over `MaybeUninit<T>` to represent uninitialized padding
/// while providing `Default`.
#[allow(dead_code)]
#[repr(transparent)]
pub(crate) struct Padding<T: Copy>(MaybeUninit<T>);
#[automatically_derived]
#[allow(dead_code)]
impl<T: ::core::clone::Clone + Copy> ::core::clone::Clone for Padding<T> {
#[inline]
fn clone(&self) -> Padding<T> {
Padding(::core::clone::Clone::clone(&self.0))
}
}
#[automatically_derived]
#[allow(dead_code)]
impl<T: ::core::marker::Copy + Copy> ::core::marker::Copy for Padding<T> {
}
impl<T: Copy> Default for Padding<T> {
fn default() -> Self { Self(MaybeUninit::zeroed()) }
}
impl<T: Copy> Padding<T> {
/// Create a `Padding` initialized with the given value.
#[allow(dead_code)]
pub(crate) const fn new(val: T) -> Self {
Self(MaybeUninit::new(val))
}
}
impl<T: Copy> fmt::Debug for Padding<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let full_name = core::any::type_name::<Self>();
let prefix_len = full_name.find("Padding").unwrap();
f.pad(&full_name[prefix_len..])
}
}
#[allow(unused)]
pub(crate) type CEnumRepr = c_uint;
/// Used to avoid `overflowing_literals` when the value is in-range for the unsigned number but
/// out-of-range for signed.
#[allow(unused)]
pub(crate) const fn u16_cast_short(x: u16) -> c_short {
if !(size_of::<u16>() <= size_of::<c_short>()) {
::core::panicking::panic("assertion failed: size_of::<u16>() <= size_of::<c_short>()")
};
x as i16
}
/// Used to avoid `overflowing_literals` when the value is in-range for the unsigned number but
/// out-of-range for signed.
#[allow(unused)]
pub(crate) const fn u32_cast_int(x: u32) -> c_int {
if !(size_of::<u32>() <= size_of::<c_int>()) {
::core::panicking::panic("assertion failed: size_of::<u32>() <= size_of::<c_int>()")
};
x as i32
}
/// Used to avoid `overflowing_literals` when the value is in-range for the unsigned number but
/// out-of-range for signed.
#[allow(unused)]
pub(crate) const fn u32_cast_long(x: u32) -> c_long {
if !(size_of::<u32>() <= size_of::<c_long>()) {
::core::panicking::panic("assertion failed: size_of::<u32>() <= size_of::<c_long>()")
};
x as c_long
}
/// Checked casting from `unsigned long` to `int`.
#[allow(unused)]
pub(crate) const fn ulong_cast_int(x: c_ulong) -> c_int {
if !(x <= (c_int::MAX as c_ulong)) {
::core::panicking::panic("assertion failed: x <= (c_int::MAX as c_ulong)")
};
x as c_int
}
/// Checked casting from `unsigned long` to `unsigned int`.
#[allow(unused)]
pub(crate) const fn ulong_cast_uint(x: c_ulong) -> c_uint {
if !(x <= (c_uint::MAX as c_ulong)) {
::core::panicking::panic("assertion failed: x <= (c_uint::MAX as c_ulong)")
};
x as c_uint
}
/// Used to avoid `overflowing_literals` when the value is in-range for the unsigned number but
/// out-of-range for signed.
#[allow(unused)]
pub(crate) const fn u32_cast_ioctl(x: u32) -> crate::Ioctl {
if !(size_of::<u32>() <= size_of::<crate::Ioctl>()) {
::core::panicking::panic("assertion failed: size_of::<u32>() <= size_of::<crate::Ioctl>()")
};
x as crate::Ioctl
}
#[allow(unused)]
pub(crate) const fn u8_slice_cast_char_slice(x: &[u8]) -> &[c_char] {
if !(size_of::<u8>() == size_of::<c_char>()) {
::core::panicking::panic("assertion failed: size_of::<u8>() == size_of::<c_char>()")
};
unsafe { mem::transmute::<&[u8], &[c_char]>(x) }
}
/// Replace bytes in an array with those from a slice. This is a polyfill for `[T]::copy_from_slice`
/// in `const`.
#[must_use]
#[allow(dead_code)]
pub const fn replace_array_items<T: Copy, const N :
usize>(mut dst: [T; N], src: &[T], start: usize) -> [T; N] {
let mut i = 0;
while i < src.len() { dst[i + start] = src[i]; i += 1; }
dst
}
}
/// Frequently-used types that are available on all platforms
///
/// We need to reexport the core types so this works with `rust-dep-of-std`.
mod prelude {
#[allow(unused_imports)]
pub(crate) use core::clone::Clone;
#[allow(unused_imports)]
pub(crate) use core::default::Default;
#[allow(unused_imports)]
pub(crate) use core::marker::{Copy, Send, Sync};
#[allow(unused_imports)]
pub(crate) use core::option::Option;
#[allow(unused_imports)]
pub(crate) use core::prelude::v1::derive;
#[allow(unused_imports)]
pub(crate) use core::{
assert, cfg, debug_assert, fmt, hash, iter, mem, ptr,
};
#[allow(unused_imports)]
pub(crate) use fmt::Debug;
#[allow(unused_imports)]
pub(crate) use mem::{align_of, align_of_val, size_of, size_of_val};
#[allow(unused_imports)]
pub(crate) use crate::types::u32_cast_ioctl;
#[allow(unused_imports)]
pub(crate) use crate::types::{
replace_array_items, u16_cast_short, u32_cast_int, u32_cast_long,
u8_slice_cast_char_slice, ulong_cast_int, ulong_cast_uint, CEnumRepr,
Padding,
};
#[allow(unused_imports)]
pub(crate) use crate::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_short,
c_uchar, c_uint, c_ulong, c_ulonglong, c_ushort, c_void, intptr_t,
size_t, ssize_t, uintptr_t,
};
}prelude!();
258 } else if #[cfg(target_os = "hermit")] {
259mod primitives;
260pub use crate::primitives::*;
261262mod hermit;
263pub use crate::hermit::*;
264265prelude!();
266 } else if #[cfg(target_os = "teeos")] {
267mod primitives;
268pub use primitives::*;
269270mod teeos;
271pub use teeos::*;
272273prelude!();
274 } else if #[cfg(target_os = "trusty")] {
275mod primitives;
276pub use crate::primitives::*;
277278mod trusty;
279pub use crate::trusty::*;
280281prelude!();
282 } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
283mod primitives;
284pub use crate::primitives::*;
285286mod sgx;
287pub use crate::sgx::*;
288289prelude!();
290 } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
291mod primitives;
292pub use crate::primitives::*;
293294mod wasi;
295pub use crate::wasi::*;
296297prelude!();
298 } else if #[cfg(target_os = "xous")] {
299mod primitives;
300pub use crate::primitives::*;
301302mod xous;
303pub use crate::xous::*;
304305prelude!();
306 } else {
307// non-supported targets: empty...
308}
309}