use tracing::debug;
use super::RegistryReconciler;
use crate::registry::error::RegistryError;
impl RegistryReconciler {
pub(super) fn is_cloacina_package(&self, package_data: &[u8]) -> bool {
package_data.len() >= 3
&& package_data[0] == 0x1f
&& package_data[1] == 0x8b
&& package_data[2] == 0x08
}
pub(super) async fn extract_library_from_cloacina(
&self,
package_data: &[u8],
) -> Result<Vec<u8>, RegistryError> {
use flate2::read::GzDecoder;
use std::io::Read;
use tar::Archive;
debug!(
"Starting library extraction from .cloacina archive, data length: {}",
package_data.len()
);
let library_extension = if cfg!(target_os = "macos") {
"dylib"
} else if cfg!(target_os = "windows") {
"dll"
} else {
"so"
};
debug!("Looking for library with extension: {}", library_extension);
let library_data = tokio::task::spawn_blocking({
let package_data = package_data.to_vec();
let library_extension = library_extension.to_string();
move || -> Result<Vec<u8>, RegistryError> {
debug!("Starting spawn_blocking task for library extraction");
let cursor = std::io::Cursor::new(package_data);
debug!("Created cursor from package data");
let gz_decoder = GzDecoder::new(cursor);
debug!("Created GzDecoder");
let mut archive = Archive::new(gz_decoder);
debug!("Created Archive from GzDecoder");
debug!("Starting to iterate through archive entries");
for entry_result in archive.entries().map_err(|e| {
debug!("Error reading archive entries: {}", e);
RegistryError::Loader(crate::registry::error::LoaderError::FileSystem {
path: "archive".to_string(),
error: format!("Failed to read archive entries: {}", e),
})
})? {
let mut entry = entry_result.map_err(|e| {
RegistryError::Loader(crate::registry::error::LoaderError::FileSystem {
path: "archive".to_string(),
error: format!("Failed to read archive entry: {}", e),
})
})?;
let path = entry.path().map_err(|e| {
RegistryError::Loader(crate::registry::error::LoaderError::FileSystem {
path: "archive".to_string(),
error: format!("Failed to get entry path: {}", e),
})
})?;
if let Some(filename) = path.file_name().and_then(|n| n.to_str()) {
if filename.ends_with(&format!(".{}", library_extension)) {
let path_string = path.to_string_lossy().to_string();
let mut file_data = Vec::new();
entry.read_to_end(&mut file_data).map_err(|e| {
RegistryError::Loader(
crate::registry::error::LoaderError::FileSystem {
path: path_string,
error: format!(
"Failed to read library file from archive: {}",
e
),
},
)
})?;
return Ok(file_data);
}
}
}
Err(RegistryError::Loader(
crate::registry::error::LoaderError::MetadataExtraction {
reason: format!(
"No library file with extension '{}' found in archive",
library_extension
),
},
))
}
})
.await
.map_err(|e| {
RegistryError::Loader(crate::registry::error::LoaderError::FileSystem {
path: "spawn_blocking".to_string(),
error: format!("Failed to spawn blocking task: {}", e),
})
})??;
Ok(library_data)
}
}