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 link(&self) -> Result<()> {
58 let err = unsafe { libbpf_sys::bpf_linker__finalize(self.linker.as_ptr()) };
60 if err != 0 {
61 return Err(Error::from_raw_os_error(err)).context("bpf_linker__finalize failed");
62 }
63 Ok(())
64 }
65}
66
67impl AsRawLibbpf for Linker {
68 type LibbpfType = libbpf_sys::bpf_linker;
69
70 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
72 self.linker
73 }
74}
75
76unsafe impl Send for Linker {}
78
79impl Drop for Linker {
80 fn drop(&mut self) {
81 unsafe { libbpf_sys::bpf_linker__free(self.linker.as_ptr()) }
83 }
84}
85
86#[cfg(test)]
87mod test {
88 use super::*;
89
90 #[test]
92 fn linker_is_send() {
93 fn test<T>()
94 where
95 T: Send,
96 {
97 }
98
99 test::<Linker>();
100 }
101}