Skip to main content

libc/
lib.rs

1//! Raw FFI bindings to platform system libraries.
2//!
3//! # Documentation
4//!
5//! `libc` only provides the bindings, not instructions on how to use them. For this, please refer
6//! to the relevant C documentation.
7//!
8//! POSIX provides OS-agnostic API definitions, which most platforms aim to comply with. Its
9//! specifications are often the best place to look:
10//!
11//! * POSIX Base Definitions: <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/toc.html>.
12//!   Types and structures are defined within the _Headers_ section.
13//! * POSIX System Interfaces: <https://pubs.opengroup.org/onlinepubs/9799919799/functions/toc.html>.
14//!   Functions are defined under the _System Interfaces_ section.
15//!
16//! For platform-specific API and caveats to the standard API, platform-specific manual pages are
17//! usually the place to look. Locally you can run commands like `man 2 stat` or `man 3 printf`
18//! (2 for kernel interfaces, 3 for standard library) to get documentation, but there are also
19//! a number of platforms with manual pages available online:
20//!
21//! * Apple: Official manpages exist at <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man5/manpages.5.html>
22//!   but are severly outdated. <https://developer.apple.com/documentation/kernel> exists but
23//!   only provides API signatures without documenttion. <https://manp.gs/mac/> or
24//!   <https://ss64.com/mac/> are better options.
25//! * DragonFlyBSD: <https://www.dragonflybsd.org/cgi/web-man>
26//! * FreeBSD: <https://man.freebsd.org/cgi/man.cgi>
27//! * IBM AIX: <https://www.ibm.com/docs/en/aix/7.3.0>
28//! * Illumos: <https://illumos.org/man/>
29//! * Linux:
30//!   * <https://man7.org/linux/man-pages/index.html> or <https://linux.die.net/man/> provide
31//!     documentation of Linux API as well as the C library, with a focus on glibc.
32//!   * Glibc-specific documentation is available at
33//!     <https://sourceware.org/glibc/manual/latest/html_mono/libc.html>.
34//!   * Musl documentation states to refer to POSIX, linked above, and the C standard, available at
35//!     <https://www.open-std.org/JTC1/SC22/WG14/www/projects#9899> (published versions must be
36//!     purchased but the drafts are free).
37//! * NetBSD: <https://man.netbsd.org/>
38//! * OpenBSD: <https://man.openbsd.org/>
39//! * Solaris: <https://docs.oracle.com/cd/E88353_01/>
40//! * Windows MSVC: <https://learn.microsoft.com/en-us/cpp/c-runtime-library/c-run-time-library-reference?view=msvc-180>
41//!
42//! # Usage Guidelines
43//!
44//! `libc` exposes non-Rust interfaces in Rust, which makes for some caveats to its use that are
45//! not present in most Rust libraries. Observing the following guidelines are recommended to help
46//! avoid soundness and stability pitfalls.
47//!
48//! 1. *Never* construct a `libc` struct with `MaybeUninit::uninit()`, call a `libc` function with
49//!    it, then call `assume_init`. Library functions do not always initialize all fields; this
50//!    includes obvious cases like padding fields, but also less obvious cases like fields present
51//!    in the `libc` struct but not on older versions of the platform's C library. It is far too
52//!    easy to end up with a bogus `assume_init` because not all fields have been written.
53//!
54//!    Instead, use `MaybeUninit::zeroed()` or the `Default` implementations that are slowly being
55//!    added. Alternatively, access fields only via raw pointer without ever using `assume_init`.
56//!
57//!    See also the safety docs for `MaybeUninit::assume_init`
58//!    <https://doc.rust-lang.org/beta/std/mem/union.MaybeUninit.html#method.assume_init>.
59//!
60//! 2. Avoid relying on the exact value of constants, the exact length of arrays, or the exact
61//!    types of type aliases, as they may change across `libc` versions. That is, if `libc`
62//!    contains code like:
63//!
64//!    <!-- relevant for how rustdoc displays these structs:
65//!         https://github.com/rust-lang/rust/issues/102456 -->
66//!    ```ignore
67//!    const IFNAMSIZ: usize = 16;
68//!
69//!    pub struct ifreq {
70//!        pub ifr_name: [c_char; IFNAMSIZ],
71//!        // ...
72//!    }
73//!
74//!    extern "C" {
75//!        pub fn time(time: *mut time_t) -> time_t;
76//!    }
77//!    ```
78//!
79//!    Then avoid writing code like:
80//!
81//!    ```ignore
82//!    // Bad assumption that the length will always be 16.
83//!    fn takes_ifr_name(ifr_name: [c_char; 16]) { /* ... */ }
84//!
85//!    fn process_ifr(ifr: ifreq) {
86//!        takes_ifr_name(ifr.ifr_name);
87//!    }
88//!
89//!    // Bad assumption that `time_t` will always be an `i64`. Use `-> time_t` instead, or
90//!    // explicitly cast to an `i64`.`
91//!    fn get_time() -> i64 {
92//!        unsafe { time(ptr::null_mut()) }
93//!    }
94//!
95//!    ```
96//!
97//!    For `takes_ifr_name`, use `[c_char; IFNAMSIZ]` or just `&[c_char]` instead. For `get_time`,
98//!    return a `time_t` or explicitly cast to an `i64`.
99//!
100//!    Along the same lines, if you write code along the lines of `assert_eq!(libc::ELAST, 97)`,
101//!    expect that there may be a release where this starts to fail.
102//!
103//! 3. Do not name `__c_anonymous_*` types anywhere, which exist to represent anonymous fields in
104//!    C. For example, FreeBSD defines:
105//!
106//!    ```c
107//!    struct filestat {
108//!        int fs_type;
109//!        // ...
110//!        struct { struct filestat stqe_next; } next;
111//!    };
112//!    ```
113//!
114//!    Which is represented in `libc`  as:
115//!
116//!    ```ignore
117//!    struct filestat {
118//!        fs_type: c_int,
119//!        // ...
120//!        next: __c_anonymous_filestat,
121//!    }
122//!
123//!    struct __c_anonymous_filestat { stqe_next: *mut filestat }
124//!    ```
125//!
126//!    Accessing `some_filestat.next.stqe_next` is completely fine, but `__c_anonymous_filestat`
127//!    should not be used anywhere (e.g. in a function signature). This is done to permit `libc` to
128//!    switch to anonymous fields if the feature is ever added to Rust.
129//!
130//! 4. Avoid accessing fields with names such as `__reserved`, `_pad`, or `_spare`. Usually the
131//!    platform libraries use these to allow adding new fields without changing the size of a
132//!    struct, but this means their types change frequently.
133//!
134//! 5. Be aware of deprecation warnings. These are used as a way to migrate necessary API changes.
135//!
136//! # Cargo Features
137//!
138//! - `std`: by default `libc` assumes that the standard library contains link directives necessary
139//!   to use the APIs in this crate. If `std` is disabled, `libc` will emit the directives instead.
140//!
141//!   This feature is slated for removal in `libc` 1.0. The intention is that no-std users of
142//!   `libc` should use their own `#[link]` attributes, `rustc-link-lib` build script directives,
143//!   or `-l` arguments for only the system libraries they need to link, rather than `libc`
144//!   possibly linking more than is needed or available. If you are using `libc` without the `std`
145//!   feature, consider starting to add link directives now for a smoother 1.0 transition.
146//!
147//! - `extra_traits`: all types in `libc` implement `Clone`, `Copy`, and `Debug`. The
148//!   `extra_traits` feature adds `Eq`, `Hash`, and `PartialEq`.
149//!
150//!   This feature is expected to be removed in libc 1.0. Libraries should instead hash or check
151//!   equality of only needed fields.
152//!
153//! - The features `const-extern-fn`, `align`, and `use_std` are all deprecated and do nothing.
154//!
155//! # Stability Expectations
156//!
157//! Due to `libc`'s position in the ecosystem, it can effectively never publish semver-breaking
158//! releases. However, the API that `libc` binds changes _all the time_; sometimes in ways that
159//! are harmless, sometimes in ways that are technically API-breaking for all users but unlikely
160//! to be noticed (e.g. removing deprecated API), and sometimes in ways that are nonbreaking in
161//! C but translate to breaking changes in Rust (e.g. changing the type of an integer). `libc`
162//! tries to strike a balance but all of this means that unfortunately, `libc` must occasionally
163//! ship changes within a semver-compatible release that are technically semver-breaking.
164//!
165//! The following are examples of changes that fall into this category:
166//!
167//! - Fields are added to a struct that is otherwise exhaustive.
168//! - Fields with names such as `padding` or `reserved` change type or are removed.
169//! - The length of an array type changes.
170//! - A struct field (with available padding) is changed from `int` to `long`.
171//!
172//! In general, `libc` aims to follow platform API changes, even when this means changes that are
173//! user-visible in Rust. There are a few guidelines used here:
174//!
175//! - Adding struct fields is not considered breaking, nor is changing fields named `reserved`,
176//!   `padding`, or similar. This is because users are expected to use field-by-field
177//!   initialization.
178//! - Changing type aliases, values of constants, or array lengths is not considered breaking.
179//! - If the platform libc has accepted breakage on the C side (typically in the form of removing
180//!   old API), the `libc` crate will follow suit.
181//! - Where possible, `#[deprecated(...)]` will be used to warn about changes before applying them.
182//!   Alternative mitigations may be considered.
183//! - Potentially breaking changes will be well-identified in release notes.
184//! - Beyond this, public API is not expected to change on Tier 1 targets. Tier 2 targets have
185//!   relaxed API stability requirements, and API stability is not enforced on tier 3 targets.
186//!
187//! While this section seems scary, keep in mind that it is meant to cover worst-case scenarios. In
188//! practice, breakage is rare and following the above-discussed [Usage Guidelines](#usage-guidelines)
189//! means that most `libc` users will never encounter a problem.
190
191// Make it a bit easier to build without Cargo
192#![crate_name = "libc"]
193#![crate_type = "rlib"]
194// Pretty much all C API doesn't match Rust conventions.
195#![allow(nonstandard_style)]
196// Not all macros and all patterns are used on all targets.
197#![allow(unused_macros)]
198#![allow(unused_macro_rules)]
199// All traits should be `Copy` and `Debug`.
200#![warn(missing_copy_implementations)]
201#![warn(missing_debug_implementations)]
202// Downgrade deny to a warning.
203#![warn(overflowing_literals)]
204// Prepare for a future upgrade.
205#![warn(rust_2024_compatibility)]
206// Things missing for 2024 that are blocked on MSRV or breakage.
207#![allow(missing_unsafe_on_extern)]
208#![allow(edition_2024_expr_fragment_specifier)]
209// Allowed globally, the warning is enabled in individual modules as we work through them
210#![allow(unsafe_op_in_unsafe_fn)]
211#![cfg_attr(libc_deny_warnings, deny(warnings))]
212// Attributes needed when building as part of the standard library
213#![cfg_attr(feature = "rustc-dep-of-std", feature(link_cfg, no_core))]
214#![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))]
215// Some targets don't need `link_cfg` and emit a warning.
216#![cfg_attr(feature = "rustc-dep-of-std", allow(unused_features))]
217// DIFF(1.0): The thread local references that raise this lint were removed in 1.0
218#![cfg_attr(feature = "rustc-dep-of-std", allow(static_mut_refs))]
219#![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)]
220#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
221
222#[macro_use]
223mod macros;
224mod new;
225
226cfg_if! {
227    if #[cfg(feature = "rustc-dep-of-std")] {
228        extern crate rustc_std_workspace_core as core;
229    }
230}
231
232pub use core::ffi::c_void;
233
234#[allow(unused_imports)] // needed while the module is empty on some platforms
235pub use new::*;
236
237cfg_if! {
238    if #[cfg(windows)] {
239        mod primitives;
240        pub use crate::primitives::*;
241
242        mod windows;
243        pub use crate::windows::*;
244
245        prelude!();
246    } else if #[cfg(target_os = "fuchsia")] {
247        mod primitives;
248        pub use crate::primitives::*;
249
250        mod fuchsia;
251        pub use crate::fuchsia::*;
252
253        prelude!();
254    } else if #[cfg(target_os = "switch")] {
255        mod primitives;
256        pub use primitives::*;
257
258        mod switch;
259        pub use switch::*;
260
261        prelude!();
262    } else if #[cfg(target_os = "psp")] {
263        mod primitives;
264        pub use primitives::*;
265
266        mod psp;
267        pub use crate::psp::*;
268
269        prelude!();
270    } else if #[cfg(target_os = "vxworks")] {
271        mod primitives;
272        pub use crate::primitives::*;
273
274        mod vxworks;
275        pub use crate::vxworks::*;
276
277        prelude!();
278    } else if #[cfg(target_os = "qurt")] {
279        mod primitives;
280        pub use crate::primitives::*;
281
282        mod qurt;
283        pub use crate::qurt::*;
284
285        prelude!();
286    } else if #[cfg(target_os = "solid_asp3")] {
287        mod primitives;
288        pub use crate::primitives::*;
289
290        mod solid;
291        pub use crate::solid::*;
292
293        prelude!();
294    } else if #[cfg(unix)] {
295        mod primitives;
296        pub use crate::primitives::*;
297
298        mod unix;
299        pub use crate::unix::*;
300
301        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) -> Self { Self(::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>()")
        };
        let len = x.len();
        let ptr = x.as_ptr();
        unsafe { core::slice::from_raw_parts(ptr.cast::<c_char>(), len) }
    }
    /// 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
    }
    /// Constructs a compile time cstring literal from a byte array
    #[allow(dead_code)]
    pub(crate) const fn cstr(bytes: &[u8]) -> *const c_char {
        if !(!bytes.is_empty() && bytes[bytes.len() - 1] == 0) {
            ::core::panicking::panic("assertion failed: !bytes.is_empty() && bytes[bytes.len() - 1] == 0")
        };
        bytes.as_ptr().cast::<c_char>()
    }
}
/// 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::cmp::{Eq, PartialEq};
    #[allow(unused_imports)]
    pub(crate) use core::default::Default;
    #[allow(unused_imports)]
    pub(crate) use core::iter::Iterator;
    #[allow(unused_imports)]
    pub(crate) use core::marker::{Copy, Send, Sync};
    #[allow(unused_imports)]
    pub(crate) use core::option::Option::{self, None, Some};
    #[allow(unused_imports)]
    pub(crate) use core::prelude::v1::derive;
    #[allow(unused_imports)]
    pub(crate) use core::{
        assert, cfg, compile_error, debug_assert, fmt, hash, iter, mem, panic,
        ptr, unimplemented,
    };
    #[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::{
        cstr, 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!();
302    } else if #[cfg(target_os = "helenos")] {
303        mod primitives;
304        pub use primitives::*;
305
306        mod helenos;
307        pub use self::helenos::*;
308
309        prelude!();
310    } else if #[cfg(target_os = "hermit")] {
311        mod primitives;
312        pub use crate::primitives::*;
313
314        mod hermit;
315        pub use crate::hermit::*;
316
317        prelude!();
318    } else if #[cfg(target_os = "teeos")] {
319        mod primitives;
320        pub use primitives::*;
321
322        mod teeos;
323        pub use teeos::*;
324
325        prelude!();
326    } else if #[cfg(target_os = "trusty")] {
327        mod primitives;
328        pub use crate::primitives::*;
329
330        mod trusty;
331        pub use crate::trusty::*;
332
333        prelude!();
334    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
335        mod primitives;
336        pub use crate::primitives::*;
337
338        mod sgx;
339        pub use crate::sgx::*;
340
341        prelude!();
342    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
343        mod primitives;
344        pub use crate::primitives::*;
345
346        mod wasi;
347        pub use crate::wasi::*;
348
349        prelude!();
350    } else if #[cfg(target_os = "xous")] {
351        mod primitives;
352        pub use crate::primitives::*;
353
354        mod xous;
355        pub use crate::xous::*;
356
357        prelude!();
358    } else {
359        // non-supported targets: empty...
360    }
361}