// Copyright (c) 2021 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

//! Constants and Data Types shared by Kata Containers components.

#![deny(missing_docs)]

#[macro_use]
extern crate slog;
#[macro_use]
extern crate serde;

/// Constants and data types related to annotations.
pub mod annotations;

/// Kata configuration information from configuration file.
pub mod config;

/// Constants and data types related to container.
pub mod container;

/// Constants and data types related to CPU.
pub mod cpu;

/// Contants and data types related to device.
pub mod device;

/// Constants and data types related to handler.
pub mod handler;

/// Constants and data types related to Kubernetes/kubelet.
pub mod k8s;

/// Constants and data types related to mount point.
pub mod mount;

pub(crate) mod utils;

/// hypervisor capabilities
pub mod capabilities;

/// Filesystem-related constants
pub mod fs;

/// The Initdata specification defines the key data structures and algorithms for injecting
/// any well-defined data from an untrusted host into a TEE (Trusted Execution Environment).
pub mod initdata;

/// rootless vmm
pub mod rootless;

/// machine type
pub mod machine_type;

/// GPT (GUID Partition Table) disk layout and metadata generation.
pub mod gpt_disk;

/// dm-verity related constants and data types.
#[cfg(feature = "devicemapper")]
pub mod dmverity;

use std::path::Path;

use crate::rootless::{is_rootless, rootless_dir};

/// Common error codes.
#[derive(thiserror::Error, Debug)]
pub enum Error {
    /// Invalid configuration list.
    #[error("invalid list {0}")]
    InvalidList(String),
}

/// Convenience macro to obtain the scoped logger
#[macro_export]
macro_rules! sl {
    () => {
        slog_scope::logger()
    };
}

/// Resolve a path to its final value.
#[macro_export]
macro_rules! resolve_path {
    ($field:expr, $fmt:expr) => {{
        if !$field.is_empty() {
            match Path::new(&$field).canonicalize() {
                Err(e) => Err(std::io::Error::other(format!($fmt, &$field, e))),
                Ok(path) => {
                    $field = path.to_string_lossy().to_string();
                    Ok(())
                }
            }
        } else {
            Ok(())
        }
    }};
}

/// Validate a path.
#[macro_export]
macro_rules! validate_path {
    ($field:expr, $fmt:expr) => {{
        if !$field.is_empty() {
            Path::new(&$field)
                .canonicalize()
                .map_err(|e| std::io::Error::other(format!($fmt, &$field, e)))
                .map(|_| ())
        } else {
            Ok(())
        }
    }};
}

/// Helper function that builds paths based on the vmm's rootless state.
pub fn build_path(path: &str) -> String {
    if is_rootless() {
        let path = Path::new(path);
        let path = if path.is_absolute() {
            path.strip_prefix("/").unwrap_or(path)
        } else {
            path
        };
        Path::new(&rootless_dir())
            .join(path)
            .to_string_lossy()
            .to_string()
    } else {
        path.to_string()
    }
}
