| 3317 | } |
| 3318 | |
| 3319 | fn write_cache_binary_atomic(final_path: &Path, bytes: &[u8]) -> CoreResult<()> { |
| 3320 | let dir = final_path.parent().ok_or_else(|| { |
| 3321 | Error::config(format!( |
| 3322 | "docker supervisor cache path '{}' has no parent directory", |
| 3323 | final_path.display(), |
| 3324 | )) |
| 3325 | })?; |
| 3326 | let mut temp = tempfile::Builder::new() |
| 3327 | .prefix(".openshell-sandbox-") |
| 3328 | .tempfile_in(dir) |
| 3329 | .map_err(|err| { |
| 3330 | Error::config(format!( |
| 3331 | "failed to create temp file for supervisor binary in '{}': {err}", |
| 3332 | dir.display(), |
| 3333 | )) |
| 3334 | })?; |
| 3335 | std::io::Write::write_all(&mut temp, bytes).map_err(|err| { |
| 3336 | Error::config(format!( |
| 3337 | "failed to write supervisor binary to temp file: {err}", |
| 3338 | )) |
| 3339 | })?; |
| 3340 | temp.as_file().sync_all().map_err(|err| { |
| 3341 | Error::config(format!("failed to sync supervisor binary temp file: {err}")) |
| 3342 | })?; |
| 3343 | |
| 3344 | #[cfg(unix)] |
| 3345 | { |
| 3346 | use std::os::unix::fs::PermissionsExt; |
| 3347 | std::fs::set_permissions(temp.path(), std::fs::Permissions::from_mode(0o755)).map_err( |
| 3348 | |err| { |
| 3349 | Error::config(format!( |
| 3350 | "failed to chmod supervisor binary temp file: {err}", |
| 3351 | )) |
| 3352 | }, |
| 3353 | )?; |
| 3354 | } |
| 3355 | |
| 3356 | temp.persist(final_path).map_err(|err| { |
| 3357 | Error::config(format!( |
| 3358 | "failed to rename supervisor binary into '{}': {}", |
| 3359 | final_path.display(), |
| 3360 | err.error, |
| 3361 | )) |
| 3362 | })?; |
| 3363 | Ok(()) |
| 3364 | } |
| 3365 | |
| 3366 | /// Cache path for an extracted supervisor binary, keyed by the image's |
| 3367 | /// content-addressable digest (e.g. `sha256:abc123…`). The digest-prefixed |