Skip to content

Commit 8d972c1

Browse files
authored
Merge pull request bootc-dev#613 from cgwalters/fix-composefs-truthiness
lib: Properly parse ostree tristate
2 parents 857f8d1 + e1e3745 commit 8d972c1

File tree

1 file changed

+90
-3
lines changed

1 file changed

+90
-3
lines changed

lib/src/ostree_prepareroot.rs

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
44
// SPDX-License-Identifier: Apache-2.0 OR MIT
55

6+
use std::str::FromStr;
7+
68
use anyhow::{Context, Result};
79
use camino::Utf8Path;
810
use glib::Cast;
@@ -11,6 +13,7 @@ use ostree::{gio, glib};
1113

1214
use crate::keyfileext::KeyFileExt;
1315
use crate::ostree_manual;
16+
use crate::utils::ResultExt;
1417

1518
pub(crate) const CONF_PATH: &str = "ostree/prepare-root.conf";
1619

@@ -44,14 +47,98 @@ pub(crate) fn overlayfs_root_enabled(root: &ostree::RepoFile) -> Result<bool> {
4447
}
4548
}
4649

50+
#[derive(Debug, PartialEq, Eq)]
51+
enum Tristate {
52+
Enabled,
53+
Disabled,
54+
Maybe,
55+
}
56+
57+
impl FromStr for Tristate {
58+
type Err = anyhow::Error;
59+
60+
fn from_str(s: &str) -> Result<Self> {
61+
let r = match s {
62+
// Keep this in sync with ot_keyfile_get_tristate_with_default from ostree
63+
"yes" | "true" | "1" => Tristate::Enabled,
64+
"no" | "false" | "0" => Tristate::Disabled,
65+
"maybe" => Tristate::Maybe,
66+
o => anyhow::bail!("Invalid tristate value: {o}"),
67+
};
68+
Ok(r)
69+
}
70+
}
71+
72+
impl Default for Tristate {
73+
fn default() -> Self {
74+
Self::Disabled
75+
}
76+
}
77+
78+
impl Tristate {
79+
pub(crate) fn maybe_enabled(&self) -> bool {
80+
match self {
81+
Self::Enabled | Self::Maybe => true,
82+
Self::Disabled => false,
83+
}
84+
}
85+
}
86+
4787
/// Query whether the config uses an overlayfs model (composefs or plain overlayfs).
4888
pub fn overlayfs_enabled_in_config(config: &glib::KeyFile) -> Result<bool> {
4989
let root_transient = config
5090
.optional_bool("root", "transient")?
5191
.unwrap_or_default();
52-
let required_composefs = config
92+
let composefs = config
5393
.optional_string("composefs", "enabled")?
54-
.map(|s| s.as_str() == "yes")
94+
.map(|s| Tristate::from_str(s.as_str()))
95+
.transpose()
96+
.log_err_default()
5597
.unwrap_or_default();
56-
Ok(root_transient || required_composefs)
98+
Ok(root_transient || composefs.maybe_enabled())
99+
}
100+
101+
#[test]
102+
fn test_tristate() {
103+
for v in ["yes", "true", "1"] {
104+
assert_eq!(Tristate::from_str(v).unwrap(), Tristate::Enabled);
105+
}
106+
assert_eq!(Tristate::from_str("maybe").unwrap(), Tristate::Maybe);
107+
for v in ["no", "false", "0"] {
108+
assert_eq!(Tristate::from_str(v).unwrap(), Tristate::Disabled);
109+
}
110+
for v in ["", "junk", "fal", "tr1"] {
111+
assert!(Tristate::from_str(v).is_err());
112+
}
113+
}
114+
115+
#[test]
116+
fn test_overlayfs_enabled() {
117+
let d0 = indoc::indoc! { r#"
118+
[foo]
119+
bar = baz
120+
[root]
121+
"# };
122+
let d1 = indoc::indoc! { r#"
123+
[root]
124+
transient = false
125+
"# };
126+
let d2 = indoc::indoc! { r#"
127+
[composefs]
128+
enabled = false
129+
"# };
130+
for v in ["", d0, d1, d2] {
131+
let kf = glib::KeyFile::new();
132+
kf.load_from_data(v, glib::KeyFileFlags::empty()).unwrap();
133+
assert_eq!(overlayfs_enabled_in_config(&kf).unwrap(), false);
134+
}
135+
136+
let e0 = format!("{d0}\n[root]\ntransient = true");
137+
let e1 = format!("{d1}\n[composefs]\nenabled = true\n[other]\nsomekey = someval");
138+
let e2 = format!("{d1}\n[composefs]\nenabled = yes");
139+
for v in [e0, e1, e2] {
140+
let kf = glib::KeyFile::new();
141+
kf.load_from_data(&v, glib::KeyFileFlags::empty()).unwrap();
142+
assert_eq!(overlayfs_enabled_in_config(&kf).unwrap(), true);
143+
}
57144
}

0 commit comments

Comments
 (0)