bpf_compatible_rs/
lib.rs

1use std::path::{Path, PathBuf};
2
3pub use crate::error::Error;
4use tar::Archive;
5pub use tempfile;
6pub use tar;
7use tempfile::{tempdir, TempDir};
8pub type Result<T> = std::result::Result<T, Error>;
9
10/// Errors of this library
11pub mod error;
12
13/// Generate the btf archive path of the running kernel
14/// It returns somethings like `ubuntu/20.04/x86_64/xxxxxxx.btf`
15pub fn generate_current_system_btf_archive_path() -> Result<String> {
16    let release_info = os_release::OsRelease::new().map_err(Error::OsReleaseError)?;
17    let uname = uname_rs::Uname::new().map_err(Error::UnameError)?;
18    let btf_path = format!(
19        "{}/{}/{}/{}.btf",
20        release_info.id, release_info.version_id, uname.machine, uname.release
21    );
22    Ok(btf_path)
23}
24
25/// Try to get the btf file of the running system under the archive directory
26pub fn get_current_system_btf_file(archive_path: impl AsRef<Path>) -> Result<PathBuf> {
27    Ok(archive_path
28        .as_ref()
29        .join(generate_current_system_btf_archive_path()?))
30}
31/// A helper type definition for simplicity
32pub type BtfArchive = Option<(PathBuf, TempDir)>;
33
34/// Unpack a tar archive, returning the contents of `package.json`;
35///
36/// It will also try get the btfhub-archive path in the unpacked directory.
37///
38/// It will return the btf archive path and the temporary path to hold it, if applies
39///
40/// Note: once the tempdir was destructed, the btf archive will be deleted
41pub fn unpack_tar(tar_data: &[u8]) -> Result<(Vec<u8>, BtfArchive)> {
42    let mut archive = Archive::new(tar_data);
43    // tempdir
44    let tmp_dir = tempdir().map_err(Error::TempDirError)?;
45    archive
46        .unpack(tmp_dir.path())
47        .map_err(Error::TarUnpackError)?;
48
49    let json_object_buffer = std::fs::read(tmp_dir.path().join("package.json"))
50        .map_err(|e| Error::FileReadError("package.json".to_string(), e))?;
51    let btf_archive_path = tmp_dir.path().join("btfhub-archive");
52    let btf_archive_path = if btf_archive_path.exists() && btf_archive_path.is_dir() {
53        Some((btf_archive_path, tmp_dir))
54    } else {
55        None
56    };
57    Ok((json_object_buffer, btf_archive_path))
58}