use crate::jailer::common::fs::copy_if_newer;
use boxlite_shared::errors::{BoxliteError, BoxliteResult};
use std::path::{Path, PathBuf};
#[cfg(any(target_os = "linux", target_os = "macos"))]
const LIBKRUNFW_PREFIX: &str = "libkrunfw.";
pub fn copy_shim_to_box(shim_path: &Path, box_dir: &Path) -> BoxliteResult<PathBuf> {
let bin_dir = box_dir.join("bin");
std::fs::create_dir_all(&bin_dir).map_err(|e| {
BoxliteError::Storage(format!(
"Failed to create bin directory {}: {}",
bin_dir.display(),
e
))
})?;
let shim_name = shim_path.file_name().unwrap_or_default();
let dest_shim = bin_dir.join(shim_name);
let copied = copy_if_newer(shim_path, &dest_shim).map_err(|e| {
BoxliteError::Storage(format!(
"Failed to copy shim {} to {}: {}",
shim_path.display(),
dest_shim.display(),
e
))
})?;
if copied {
tracing::debug!(
src = %shim_path.display(),
dst = %dest_shim.display(),
"Copied shim binary to box directory"
);
}
if let Some(shim_dir) = shim_path.parent() {
copy_libkrunfw(shim_dir, &bin_dir)?;
}
Ok(dest_shim)
}
fn copy_libkrunfw(src_dir: &Path, dest_dir: &Path) -> BoxliteResult<()> {
let entries = match std::fs::read_dir(src_dir) {
Ok(entries) => entries,
Err(e) => {
tracing::warn!(
src_dir = %src_dir.display(),
error = %e,
"Could not read source directory for libkrunfw"
);
return Ok(());
}
};
for entry in entries.filter_map(|e| e.ok()) {
let name = entry.file_name();
let name_str = name.to_string_lossy();
if name_str.starts_with(LIBKRUNFW_PREFIX) {
let src_path = entry.path();
let dest_path = dest_dir.join(&name);
let copied = copy_if_newer(&src_path, &dest_path).map_err(|e| {
BoxliteError::Storage(format!(
"Failed to copy libkrunfw {} to {}: {}",
src_path.display(),
dest_path.display(),
e
))
})?;
if copied {
tracing::debug!(
lib = %name_str,
dst = %dest_path.display(),
"Copied libkrunfw to box directory"
);
}
}
}
Ok(())
}