1#![doc(
36 html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg",
37 html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
38)]
39#![cfg_attr(docsrs, feature(doc_cfg))]
40#![deny(
41 clippy::all,
42 clippy::use_self,
43 absolute_paths_not_starting_with_crate,
44 deprecated_in_future,
45 elided_lifetimes_in_paths,
46 explicit_outlives_requirements,
47 ffi_unwind_calls,
48 keyword_idents,
49 macro_use_extern_crate,
51 meta_variable_misuse,
52 missing_abi,
53 missing_docs,
55 non_ascii_idents,
56 noop_method_call,
57 rust_2021_incompatible_closure_captures,
58 rust_2021_incompatible_or_patterns,
59 rust_2021_prefixes_incompatible_syntax,
60 rust_2021_prelude_collisions,
61 single_use_lifetimes,
62 trivial_numeric_casts,
63 unreachable_pub,
64 unstable_features,
66 unused_crate_dependencies,
67 unused_extern_crates,
68 unused_import_braces,
69 unused_lifetimes,
70 unused_macro_rules,
71 )]
74#![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)]
75#![cfg_attr(
76 all(feature = "async_tokio", feature = "async_std"),
77 allow(unused_crate_dependencies)
78)]
79
80mod bpf;
81pub mod maps;
82pub mod pin;
83pub mod programs;
84pub mod sys;
85pub mod util;
86
87use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
88
89use aya_obj as obj;
90use aya_obj::generated;
91pub use bpf::*;
92pub use obj::btf::{Btf, BtfError};
93pub use object::Endianness;
94#[doc(hidden)]
95pub use sys::netlink_set_link_up;
96
97#[derive(Debug)]
100struct MockableFd {
101 #[cfg(not(test))]
102 fd: OwnedFd,
103 #[cfg(test)]
104 fd: Option<OwnedFd>,
105}
106
107impl MockableFd {
108 #[cfg(test)]
109 const fn mock_signed_fd() -> i32 {
110 1337
111 }
112
113 #[cfg(test)]
114 const fn mock_unsigned_fd() -> u32 {
115 1337
116 }
117
118 #[cfg(not(test))]
119 fn from_fd(fd: OwnedFd) -> Self {
120 Self { fd }
121 }
122
123 #[cfg(test)]
124 fn from_fd(fd: OwnedFd) -> Self {
125 let fd = Some(fd);
126 Self { fd }
127 }
128
129 #[cfg(not(test))]
130 fn inner(&self) -> &OwnedFd {
131 let Self { fd } = self;
132 fd
133 }
134
135 #[cfg(test)]
136 fn inner(&self) -> &OwnedFd {
137 let Self { fd } = self;
138 fd.as_ref().unwrap()
139 }
140
141 #[cfg(not(test))]
142 fn into_inner(self) -> OwnedFd {
143 self.fd
144 }
145
146 #[cfg(test)]
147 fn into_inner(mut self) -> OwnedFd {
148 self.fd.take().unwrap()
149 }
150
151 fn try_clone(&self) -> std::io::Result<Self> {
152 let fd = self.inner();
153 let fd = fd.try_clone()?;
154 Ok(Self::from_fd(fd))
155 }
156}
157
158impl<T> From<T> for MockableFd
159where
160 OwnedFd: From<T>,
161{
162 fn from(value: T) -> Self {
163 let fd = OwnedFd::from(value);
164 Self::from_fd(fd)
165 }
166}
167
168impl AsFd for MockableFd {
169 fn as_fd(&self) -> BorrowedFd<'_> {
170 self.inner().as_fd()
171 }
172}
173
174impl AsRawFd for MockableFd {
175 fn as_raw_fd(&self) -> RawFd {
176 self.inner().as_raw_fd()
177 }
178}
179
180impl FromRawFd for MockableFd {
181 unsafe fn from_raw_fd(fd: RawFd) -> Self {
182 let fd = OwnedFd::from_raw_fd(fd);
183 Self::from_fd(fd)
184 }
185}
186
187#[cfg(test)]
188impl Drop for MockableFd {
189 fn drop(&mut self) {
190 use std::os::fd::AsRawFd as _;
191
192 let Self { fd } = self;
193 let fd = fd.take().unwrap();
194 if fd.as_raw_fd() < Self::mock_signed_fd() {
195 std::mem::drop(fd)
196 } else {
197 std::mem::forget(fd)
198 }
199 }
200}