Skip to main content

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        mod 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")] {
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}