linux_api/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Type definitions and utilities for interacting with the Linux API.
//! Does not depend on the `std` crate (i.e. is `no_std`) nor libc.
//!
//! We currently re-export C bindings. This allows normal C code, using
//! libc headers, to work with these kernel types. Normally this can't be done
//! because the libc and kernel headers contain incompatible definitions.
//!
//! # Type names
//!
//! We provide 3 styles of types:
//!
//! * snake-cased-types prefixed with `linux_`. These are ABI-compatible with
//!   the corresponding kernel types. These types are re-exported in this crate's
//!   generated C header, and are the types used in exported C function APIs.
//!
//! * snake-cased-types *without* the `linux_` prefix. These are *also* ABI-compatible
//!   with the corresponding kernel types, and are intended for use in Rust
//!   code.  They never require or enforce invariants beyond that bytes are
//!   initialized, so are safe to transmute from initialized bytes, or from the
//!   corresponding `linux_` type if the required bytes are known to be
//!   initialized. See [`crate::signal::sigaction`] for an example of a type
//!   with such invariants.
//!
//!   We do *not* expose these types in C interfaces, since they have the same
//!   name as types in the original Linux headers, and often with the same name
//!   in C library headers. Exported C APIs should use the `linux_` types in their
//!   signatures, and convert internally to the non-prefixed types. In cases
//!   where the 2 types are not simply aliased, they usually implement
//!   `bytemuck::TransparentWrapper` or similar APIs that allow converting
//!   values *and references* in both directions.
//!
//! * camel-cased types are *not* necessarily bitwise-compatible with kernel types
//!   with similar names. These primarily include `enum`s and `bitflags` types.
//!   Kernel constants such as `O_WRONLY` are typically defined as instants of
//!   such types, and are convertible to and from the original integer types.

#![cfg_attr(not(any(test, feature = "std")), no_std)]
// https://github.com/rust-lang/rfcs/blob/master/text/2585-unsafe-block-in-unsafe-fn.md
#![deny(unsafe_op_in_unsafe_fn)]
#![allow(clippy::not_unsafe_ptr_arg_deref)]
#![allow(clippy::enum_variant_names)]
#![allow(clippy::too_many_arguments)]

#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
// https://github.com/rust-lang/rust/issues/66220
#[allow(improper_ctypes)]
#[allow(unsafe_op_in_unsafe_fn)]
#[allow(clippy::all)]
#[allow(unused)]
mod bindings;

pub mod capability;
pub mod close_range;
pub mod epoll;
pub mod errno;
pub mod exit;
pub mod fcntl;
pub mod futex;
pub mod inet;
pub mod ioctls;
pub mod ldt;
pub mod limits;
pub mod mman;
pub mod netlink;
pub mod poll;
pub mod posix_types;
pub mod prctl;
pub mod resource;
pub mod rseq;
pub mod rtnetlink;
pub mod sched;
pub mod signal;
pub mod socket;
pub mod stat;
pub mod syscall;
pub mod sysinfo;
pub mod time;
pub mod ucontext;
pub mod utsname;
pub mod wait;

// Internally we often end up needing to convert from types that bindgen inferred, in const
// contexts.
//
// We could use `as`, but it'd be easy to accidentally truncate, especially if
// the constant we're converting isn't the type we thought it was.
//
// Because these are in const contexts, we can't use `try_from`.
mod const_conversions {
    pub const fn u64_from_u32(val: u32) -> u64 {
        // Guaranteed not to truncate
        val as u64
    }

    pub const fn usize_from_u32(val: u32) -> usize {
        // Guaranteed not to truncate
        val as usize
    }

    pub const fn i32_from_u32(val: u32) -> i32 {
        // Maybe not strictly necessary for safety, but probably
        // a mistake of some kind if this fails.
        assert!(val <= (i32::MAX as u32));

        val as i32
    }

    pub const fn i32_from_u32_allowing_wraparound(val: u32) -> i32 {
        val as i32
    }

    pub const fn u16_from_u32(val: u32) -> u16 {
        assert!(val <= (u16::MAX as u32));

        val as u16
    }
}