ic_backup/ops/artifacts/
mod.rs1#[cfg(test)]
4mod tests;
5
6use crate::model::artifacts::ArtifactChecksumRecord;
7use ic_host_artifacts::artifact::tree::DirectoryChecksumError;
8use std::{
9 io,
10 path::{Path, PathBuf},
11};
12use thiserror::Error;
13
14pub(crate) fn checksum_directory(path: &Path) -> Result<ArtifactChecksumRecord, ArtifactError> {
15 #[cfg(unix)]
16 {
17 use ic_host_fs::read::tree::checksum::{TreeChecksumError, checksum_directory};
18 let digest = checksum_directory(path, u64::MAX).map_err(|error| match error {
19 TreeChecksumError::Io(error) => ArtifactError::Io(error),
20 TreeChecksumError::Input(error) => ArtifactError::Io(error.into()),
21 TreeChecksumError::Declaration(error) => ArtifactError::from(error),
22 TreeChecksumError::NonUtf8Path { path } => ArtifactError::NonUtf8Path { path },
23 TreeChecksumError::InvalidPath { path } => ArtifactError::UnsupportedEntry {
24 path: path.display().to_string(),
25 kind: "Unknown".into(),
26 },
27 TreeChecksumError::UnsupportedEntry { path, kind } => ArtifactError::UnsupportedEntry {
28 path: path.display().to_string(),
29 kind: format!("{kind:?}"),
30 },
31 })?;
32 Ok(ArtifactChecksumRecord::from_digest(*digest.as_bytes()))
33 }
34 #[cfg(not(unix))]
35 {
36 let _ = path;
37 Err(ArtifactError::UnsupportedPlatform(std::env::consts::OS))
38 }
39}
40
41pub(crate) fn checksum_relative_files(
42 files: Vec<(PathBuf, ArtifactChecksumRecord)>,
43) -> Result<ArtifactChecksumRecord, DirectoryChecksumError> {
44 let digest = ic_host_artifacts::artifact::tree::checksum_relative_files(
45 files
46 .into_iter()
47 .map(|(path, record)| (path, record.sha256()))
48 .collect(),
49 )?;
50 Ok(ArtifactChecksumRecord::from_digest(*digest.as_bytes()))
51}
52
53impl From<DirectoryChecksumError> for ArtifactError {
54 fn from(error: DirectoryChecksumError) -> Self {
55 match error {
56 DirectoryChecksumError::NonUtf8Path { path } => Self::NonUtf8Path { path },
57 error => Self::Io(io::Error::new(io::ErrorKind::InvalidData, error)),
58 }
59 }
60}
61
62#[derive(Debug, Error)]
64pub enum ArtifactError {
65 #[error("artifact path is not UTF-8: {path:?}")]
67 NonUtf8Path {
68 path: PathBuf,
70 },
71 #[error(transparent)]
73 Io(#[from] io::Error),
74 #[error("unsupported artifact entry at {path}: {kind}")]
76 UnsupportedEntry {
77 path: String,
79 kind: String,
81 },
82 #[error("secure artifact traversal is unsupported on platform {0}")]
84 UnsupportedPlatform(&'static str),
85}