bootc_lib/
podman.rs

1use anyhow::Result;
2use camino::Utf8Path;
3use cap_std_ext::cap_std::fs::Dir;
4use serde::Deserialize;
5
6/// Where we look inside our container to find our own image
7/// for use with `bootc install`.
8pub(crate) const CONTAINER_STORAGE: &str = "/var/lib/containers";
9
10#[derive(Deserialize)]
11#[serde(rename_all = "PascalCase")]
12pub(crate) struct Inspect {
13    pub(crate) digest: String,
14}
15
16/// This is output from `podman image list --format=json`.
17#[derive(Deserialize)]
18#[serde(rename_all = "PascalCase")]
19pub(crate) struct ImageListEntry {
20    pub(crate) id: String,
21    pub(crate) names: Option<Vec<String>>,
22}
23
24/// Given an image ID, return its manifest digest
25pub(crate) fn imageid_to_digest(imgid: &str) -> Result<String> {
26    use bootc_utils::CommandRunExt;
27    let o: Vec<Inspect> = crate::install::run_in_host_mountns("podman")?
28        .args(["inspect", imgid])
29        .run_and_parse_json()?;
30    let i = o
31        .into_iter()
32        .next()
33        .ok_or_else(|| anyhow::anyhow!("No images returned for inspect"))?;
34    Ok(i.digest)
35}
36
37/// Return true if there is apparently an active container store at the target path.
38pub(crate) fn storage_exists(root: &Dir, path: impl AsRef<Utf8Path>) -> Result<bool> {
39    fn impl_storage_exists(root: &Dir, path: &Utf8Path) -> Result<bool> {
40        let lock = "storage.lock";
41        root.try_exists(path.join(lock)).map_err(Into::into)
42    }
43    impl_storage_exists(root, path.as_ref())
44}
45
46/// Return true if there is apparently an active container store in the default path
47/// for the target root.
48///
49/// Note this does not attempt to parse the root filesystem's container storage configuration,
50/// this uses a hardcoded default path.
51pub(crate) fn storage_exists_default(root: &Dir) -> Result<bool> {
52    storage_exists(root, CONTAINER_STORAGE.trim_start_matches('/'))
53}