1use std::path::Path;
2use std::ptr::null_mut;
3use std::ptr::NonNull;
4
5use crate::util::path_to_cstring;
6use crate::util::validate_bpf_ret;
7use crate::AsRawLibbpf;
8use crate::Error;
9use crate::ErrorExt as _;
10use crate::Result;
11
12#[derive(Debug)]
18pub struct Linker {
19 linker: NonNull<libbpf_sys::bpf_linker>,
21}
22
23impl Linker {
24 pub fn new<P>(output: P) -> Result<Self>
26 where
27 P: AsRef<Path>,
28 {
29 let output = path_to_cstring(output)?;
30 let opts = null_mut();
31 let ptr = unsafe { libbpf_sys::bpf_linker__new(output.as_ptr(), opts) };
33 let ptr = validate_bpf_ret(ptr).context("failed to attach iterator")?;
34 let slf = Self { linker: ptr };
35 Ok(slf)
36 }
37
38 pub fn add_file<P>(&mut self, file: P) -> Result<()>
40 where
41 P: AsRef<Path>,
42 {
43 let file = path_to_cstring(file)?;
44 let opts = null_mut();
45 let err =
47 unsafe { libbpf_sys::bpf_linker__add_file(self.linker.as_ptr(), file.as_ptr(), opts) };
48 if err != 0 {
49 Err(Error::from_raw_os_error(err)).context("bpf_linker__add_file failed")
50 } else {
51 Ok(())
52 }
53 }
54
55 pub fn add_buf(&mut self, buf: &[u8]) -> Result<()> {
57 let opts = null_mut();
58 let err = unsafe {
60 libbpf_sys::bpf_linker__add_buf(
61 self.linker.as_ptr(),
62 buf.as_ptr() as *mut _,
63 buf.len() as _,
64 opts,
65 )
66 };
67 if err != 0 {
68 Err(Error::from_raw_os_error(err)).context("bpf_linker__add_buf failed")
69 } else {
70 Ok(())
71 }
72 }
73
74 pub fn link(&self) -> Result<()> {
77 let err = unsafe { libbpf_sys::bpf_linker__finalize(self.linker.as_ptr()) };
79 if err != 0 {
80 return Err(Error::from_raw_os_error(err)).context("bpf_linker__finalize failed");
81 }
82 Ok(())
83 }
84}
85
86impl AsRawLibbpf for Linker {
87 type LibbpfType = libbpf_sys::bpf_linker;
88
89 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
91 self.linker
92 }
93}
94
95unsafe impl Send for Linker {}
97
98impl Drop for Linker {
99 fn drop(&mut self) {
100 unsafe { libbpf_sys::bpf_linker__free(self.linker.as_ptr()) }
102 }
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108
109 #[test]
111 fn linker_is_send() {
112 fn test<T>()
113 where
114 T: Send,
115 {
116 }
117
118 test::<Linker>();
119 }
120}