Crate libc

Raw FFI bindings to platform system libraries.

Usage Guidelines

libc exposes non-Rust interfaces in Rust, which makes for some caveats to its use that are not present in most Rust libraries. Observing the following guidelines are recommended to help avoid soundness and stability pitfalls.

  1. Never construct a libc struct with MaybeUninit::uninit(), initialize it, then call assume_init. Many structures have padding fields or may gain fields in the future, and it is far too easy to end up calling assume_init on partially initialized data.

    Instead, use MaybeUninit::zeroed() or the Default implementations that are slowly being added. Alternatively, access fields only via raw pointer without ever using assume_init.

  2. Avoid relying on the exact value of constants, the exact length of arrays, or the exact types of type aliases, as they may change across libc versions. That is, if libc contains code like:

    const IFNAMSIZ: usize = 16;
    
    pub struct ifreq {
        pub ifr_name: [c_char; IFNAMSIZ],
        // ...
    }
    
    extern "C" {
        pub fn time(time: *mut time_t) -> time_t;
    }
    

    Then avoid writing code like:

    // Bad assumption that the length will always be 16.
    fn takes_ifr_name(ifr_name: [c_char; 16]) { /* ... */ }
    
    fn process_ifr(ifr: ifreq) {
        takes_ifr_name(ifr.ifr_name);
    }
    
    // Bad assumption that `time_t` will always be an `i64`. Use `-> time_t` instead, or
    // explicitly cast to an `i64`.`
    fn get_time() -> i64 {
        unsafe { time(ptr::null_mut()) }
    }
    
    

    For takes_ifr_name, use [c_char; IFNAMSIZ] or just &[c_char] instead. For get_time, return a time_t or explicitly cast to an i64.

    Along the same lines, if you write code along the lines of assert_eq!(libc::ELAST, 97), expect that there may be a release where this starts to fail.

  3. Do not name __c_anonymous_* types anywhere, which exist to represent anonymous fields in C. For example, FreeBSD defines:

    struct filestat {
        int fs_type;
        // ...
        struct { struct filestat stqe_next; } next;
    };
    

    Which is represented in libc as:

    struct filestat {
        fs_type: c_int,
        // ...
        next: __c_anonymous_filestat,
    }
    
    struct __c_anonymous_filestat { stqe_next: *mut filestat }
    

    Accessing some_filestat.next.stqe_next is completely fine, but __c_anonymous_filestat should not be used anywhere (e.g. in a function signature). This is done to permit libc to switch to anonymous fields if the feature is ever added to Rust.

  4. Avoid accessing fields with names such as __reserved, _pad, or _spare. Usually the platform libraries use these to allow adding new fields without changing the size of a struct, but this means their types change frequently.

  5. Be aware of deprecation warnings. These are used as a way to migrate necessary API changes.

Cargo Features

Stability Expectations

Due to libc's position in the ecosystem, it can effectively never publish semver-breaking releases. However, the API that libc binds changes all the time; sometimes in ways that are harmless, sometimes in ways that are technically API-breaking for all users but unlikely to be noticed (e.g. removing deprecated API), and sometimes in ways that are nonbreaking in C but translate to breaking changes in Rust (e.g. changing the type of an integer). libc tries to strike a balance but all of this means that unfortunately, libc must occasionally ship changes within a semver-compatible release that are technically semver-breaking.

The following are examples of changes that fall into this category:

In general, libc aims to follow platform API changes, even when this means changes that are user-visible in Rust. There are a few guidelines used here:

While this section seems scary, keep in mind that it is meant to cover worst-case scenarios. In practice, breakage is rare and following the above-discussed Usage Guidelines means that most libc users will never encounter a problem.

Structs

Unions

Enums

Functions

Type Aliases

Constants

Statics