kumoba 0.2.1

Local libkrun microVM sandboxes for Rust applications
Documentation
use crate::{Error, GuestPath, HostMount, Result};

pub fn validate_host_mounts(mounts: &[HostMount]) -> Result<()> {
    if mounts.is_empty() {
        return Ok(());
    }
    if !cfg!(target_os = "macos") {
        return Err(Error::InvalidInput(
            "host folder mounts currently require macOS confinement; Linux support is not enabled"
                .into(),
        ));
    }
    if mounts.len() > 8 {
        return Err(Error::InvalidInput(
            "at most 8 host mounts are supported".into(),
        ));
    }
    for (index, mount) in mounts.iter().enumerate() {
        GuestPath::new(&mount.target)?;
        if !mount.target.starts_with("/workspace/")
            || mount.target.ends_with('/')
            || mount.target.split('/').any(|p| p == ".")
        {
            return Err(Error::InvalidInput(
                "host mounts must target a directory below /workspace".into(),
            ));
        }
        let source = std::fs::canonicalize(&mount.source)?;
        if source != mount.source
            || !source.is_dir()
            || source.parent().is_none()
            || source.as_os_str().as_encoded_bytes().len() > 4096
        {
            return Err(Error::InvalidInput(
                "mount source must be a canonical host directory other than root".into(),
            ));
        }
        for other in &mounts[..index] {
            if std::path::Path::new(&mount.target).starts_with(&other.target)
                || std::path::Path::new(&other.target).starts_with(&mount.target)
                || source.starts_with(&other.source)
                || other.source.starts_with(&source)
            {
                return Err(Error::InvalidInput(
                    "mount sources and targets must not overlap".into(),
                ));
            }
        }
    }
    Ok(())
}