Skip to main content

microsandbox_utils/
lib.rs

1//! Shared constants and utilities for the microsandbox project.
2
3pub mod copy;
4pub mod log_text;
5pub mod size;
6pub mod ttl_reverse_index;
7pub mod wake_pipe;
8
9//--------------------------------------------------------------------------------------------------
10// Constants: Directory Layout
11//--------------------------------------------------------------------------------------------------
12
13/// Name of the microsandbox home directory (relative to user's home).
14pub const BASE_DIR_NAME: &str = ".microsandbox";
15
16/// Subdirectory for shared libraries (libkrunfw).
17pub const LIB_SUBDIR: &str = "lib";
18
19/// Subdirectory for helper binaries.
20pub const BIN_SUBDIR: &str = "bin";
21
22/// Subdirectory for the database.
23pub const DB_SUBDIR: &str = "db";
24
25/// Subdirectory for OCI layer cache.
26pub const CACHE_SUBDIR: &str = "cache";
27
28/// Subdirectory for per-sandbox state.
29pub const SANDBOXES_SUBDIR: &str = "sandboxes";
30
31/// Subdirectory for named volumes.
32pub const VOLUMES_SUBDIR: &str = "volumes";
33
34/// Subdirectory for snapshot artifacts.
35pub const SNAPSHOTS_SUBDIR: &str = "snapshots";
36
37/// Subdirectory for logs.
38pub const LOGS_SUBDIR: &str = "logs";
39
40/// Subdirectory for secrets.
41pub const SECRETS_SUBDIR: &str = "secrets";
42
43/// Subdirectory for TLS certificates.
44pub const TLS_SUBDIR: &str = "tls";
45
46/// Subdirectory for SSH keys.
47pub const SSH_SUBDIR: &str = "ssh";
48
49//--------------------------------------------------------------------------------------------------
50// Constants: Binary Names
51//--------------------------------------------------------------------------------------------------
52
53/// Guest agent binary name.
54pub const AGENTD_BINARY: &str = "agentd";
55
56/// CLI binary name.
57pub const MSB_BINARY: &str = "msb";
58
59//--------------------------------------------------------------------------------------------------
60// Constants: Versions
61//--------------------------------------------------------------------------------------------------
62
63/// Version for downloading prebuilt release artifacts.
64///
65/// This tracks the published crate/package version so the SDK and the
66/// downloaded runtime bundle stay aligned.
67pub const PREBUILT_VERSION: &str = env!("CARGO_PKG_VERSION");
68
69/// libkrunfw release version. Keep in sync with justfile.
70pub const LIBKRUNFW_VERSION: &str = "5.2.1";
71
72/// libkrunfw ABI version (soname major). Keep in sync with justfile.
73pub const LIBKRUNFW_ABI: &str = "5";
74
75//--------------------------------------------------------------------------------------------------
76// Constants: Filenames
77//--------------------------------------------------------------------------------------------------
78
79/// Database filename.
80pub const DB_FILENAME: &str = "msb.db";
81
82/// Global configuration filename.
83pub const CONFIG_FILENAME: &str = "config.json";
84
85/// Project-local sandbox configuration filename.
86pub const SANDBOXFILE_NAME: &str = "Sandboxfile";
87
88//--------------------------------------------------------------------------------------------------
89// Constants: GitHub
90//--------------------------------------------------------------------------------------------------
91
92/// GitHub organization.
93pub const GITHUB_ORG: &str = "superradcompany";
94
95/// Main repository name.
96pub const MICROSANDBOX_REPO: &str = "microsandbox";
97
98//--------------------------------------------------------------------------------------------------
99// Functions
100//--------------------------------------------------------------------------------------------------
101
102/// Resolve the microsandbox home directory.
103///
104/// Order of resolution:
105/// 1. `MSB_HOME` env var (used as-is, no `.microsandbox` suffix appended)
106/// 2. `~/.microsandbox/` (i.e. `dirs::home_dir().join(BASE_DIR_NAME)`)
107/// 3. `./.microsandbox/` if no home is available
108///
109/// `MSB_HOME` lets CI and integration tests isolate microsandbox state
110/// (db, sandboxes, cache, logs) per process without disturbing other
111/// `$HOME`-rooted tooling.
112pub fn resolve_home() -> std::path::PathBuf {
113    if let Some(path) = std::env::var_os("MSB_HOME") {
114        return std::path::PathBuf::from(path);
115    }
116    dirs::home_dir()
117        .unwrap_or_else(|| std::path::PathBuf::from("."))
118        .join(BASE_DIR_NAME)
119}
120
121/// Returns the platform-specific libkrunfw filename.
122pub fn libkrunfw_filename(os: &str) -> String {
123    if os == "macos" {
124        format!("libkrunfw.{LIBKRUNFW_ABI}.dylib")
125    } else {
126        format!("libkrunfw.so.{LIBKRUNFW_VERSION}")
127    }
128}
129
130/// Returns the GitHub release download URL for libkrunfw.
131pub fn libkrunfw_download_url(version: &str, arch: &str, os: &str) -> String {
132    let (target_os, ext) = if os == "macos" {
133        ("darwin", "dylib")
134    } else {
135        ("linux", "so")
136    };
137
138    format!(
139        "https://github.com/{GITHUB_ORG}/{MICROSANDBOX_REPO}/releases/download/v{version}/libkrunfw-{target_os}-{arch}.{ext}"
140    )
141}
142
143/// Returns the GitHub release download URL for the agentd binary.
144pub fn agentd_download_url(version: &str, arch: &str) -> String {
145    format!(
146        "https://github.com/{GITHUB_ORG}/{MICROSANDBOX_REPO}/releases/download/v{version}/{AGENTD_BINARY}-{arch}"
147    )
148}
149
150/// Returns the GitHub release download URL for the microsandbox bundle tarball.
151pub fn bundle_download_url(version: &str, arch: &str, os: &str) -> String {
152    let target_os = if os == "macos" { "darwin" } else { "linux" };
153    format!(
154        "https://github.com/{GITHUB_ORG}/{MICROSANDBOX_REPO}/releases/download/v{version}/{MICROSANDBOX_REPO}-{target_os}-{arch}.tar.gz"
155    )
156}
157
158/// Returns an HTTP client configured for release asset downloads.
159#[cfg(feature = "http-client")]
160pub fn http_client() -> ureq::Agent {
161    ureq::Agent::config_builder()
162        .tls_config(
163            ureq::tls::TlsConfig::builder()
164                .root_certs(ureq::tls::RootCerts::PlatformVerifier)
165                .build(),
166        )
167        .build()
168        .new_agent()
169}
170
171//--------------------------------------------------------------------------------------------------
172// Tests
173//--------------------------------------------------------------------------------------------------
174
175#[cfg(test)]
176mod tests {
177    use super::*;
178
179    /// `MSB_HOME` is honoured verbatim (no `.microsandbox` suffix appended)
180    /// so callers can isolate state per process without disturbing tooling
181    /// that reads `$HOME` (npm cache, ssh keys, etc.).
182    ///
183    /// Uses a unique env var per test process to avoid clashing with other
184    /// parallel tests that read `MSB_HOME`.
185    #[test]
186    fn test_resolve_home_respects_env_override() {
187        // SAFETY: This test sets a process-global env var. Vitest-style
188        // single-test isolation isn't available; rely on the test being
189        // the sole reader of `MSB_HOME` in this binary.
190        let custom = std::path::PathBuf::from("/tmp/msb-home-resolve-test-12345");
191        unsafe { std::env::set_var("MSB_HOME", &custom) };
192        let resolved = resolve_home();
193        unsafe { std::env::remove_var("MSB_HOME") };
194        assert_eq!(resolved, custom);
195    }
196}