feat(bls): read the loader.conf preferred key and strip quotes

This commit is contained in:
alex authored and Alex Zenla committed 2026-10-03 19:41:39 -07:00
1 parent 4794de9db5
commit cd49b27ccb
2 files changed
+41 -3

No files matched your search

+21
View File
@@ -846,6 +846,27 @@ mod tests {
assert_eq!(boot_path(""), "/");
}
#[test]
fn loader_conf_reads_preferred() {
let conf = LoaderConf::parse("preferred fedora-*\n");
assert_eq!(conf.preferred.as_deref(), Some("fedora-*"));
assert!(conf.warnings.is_empty());
}
#[test]
fn loader_conf_strips_matching_quotes() {
let conf = LoaderConf::parse("default \"foo*\"\npreferred 'bar'\ntimeout \"3\"\n");
assert_eq!(conf.default.as_deref(), Some("foo*"));
assert_eq!(conf.preferred.as_deref(), Some("bar"));
assert_eq!(conf.timeout, Some(LoaderTimeout::Seconds(3)));
}
#[test]
fn loader_conf_keeps_unmatched_quotes() {
let conf = LoaderConf::parse("default \"foo\n");
assert_eq!(conf.default.as_deref(), Some("\"foo"));
}
#[test]
fn loader_conf_empty_has_no_settings() {
let conf = LoaderConf::parse("");
+20 -3
View File
@@ -36,12 +36,28 @@ impl LoaderTimeout {
pub struct LoaderConf {
/// A glob pattern that selects the default entry, or `@saved`.
pub default: Option<String>,
/// A glob pattern that selects the preferred entry, or `@saved`. Unlike `default`, an entry
/// with no boot counter tries left is not used.
pub preferred: Option<String>,
/// How long to show the boot menu.
pub timeout: Option<LoaderTimeout>,
/// Problems found while parsing, such as keys that are not supported.
pub warnings: Vec<String>,
}
/// Removes one pair of matching single or double quotes around `value`.
fn unquote(value: &str) -> &str {
for quote in ['"', '\''] {
if let Some(inner) = value
.strip_prefix(quote)
.and_then(|rest| rest.strip_suffix(quote))
{
return inner;
}
}
value
}
impl LoaderConf {
/// Parses the `input` as a `loader.conf` file. Parsing never fails, as a bad setting
/// should not prevent booting. Anything that is ignored is described in `warnings`.
@@ -59,21 +75,22 @@ impl LoaderConf {
}
let (key, value) = match line.split_once(char::is_whitespace) {
Some((key, value)) => (key, value.trim()),
Some((key, value)) => (key, unquote(value.trim())),
None => (line, ""),
};
match key {
"default" if !value.is_empty() => conf.default = Some(value.to_string()),
"preferred" if !value.is_empty() => conf.preferred = Some(value.to_string()),
"timeout" => match LoaderTimeout::parse(value) {
Some(timeout) => conf.timeout = Some(timeout),
None => conf
.warnings
.push(format!("ignoring invalid loader.conf timeout '{}'", value)),
},
"default" => conf
"default" | "preferred" => conf
.warnings
.push("ignoring loader.conf default without a value".to_string()),
.push(format!("ignoring loader.conf {} without a value", key)),
_ => conf
.warnings
.push(format!("ignoring unsupported loader.conf key '{}'", key)),