Skip to content

Commit f38017a

Browse files
committed
kernel_cmdline: Update add_or_modify to better describe action taken
In some cases it will be important to differentiate whether we added a net-new parameter vs. modifying an existing parameter. Motivated by trying to update bootc_kargs to use kernel_cmdline. We want to parse the booted kargs, and then merge with any args defined in kargs.d. But it should error if a value in kargs.d already exists in the booted system with a different value. The previous API did not provide enough visibility to make this determiniation. Signed-off-by: John Eckersberg <[email protected]>
1 parent 390fcc0 commit f38017a

File tree

3 files changed

+66
-23
lines changed

3 files changed

+66
-23
lines changed

crates/kernel_cmdline/src/bytes.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use std::borrow::Cow;
77

8-
use crate::utf8;
8+
use crate::{utf8, Action};
99

1010
use anyhow::Result;
1111

@@ -134,11 +134,17 @@ impl<'a> Cmdline<'a> {
134134

135135
/// Add or modify a parameter to the command line
136136
///
137-
/// Returns `true` if the parameter was added or modified.
137+
/// Returns `Action::Added` if the parameter did not exist before
138+
/// and was added.
138139
///
139-
/// Returns `false` if the parameter already existed with the same
140-
/// content.
141-
pub fn add_or_modify(&mut self, param: &Parameter) -> bool {
140+
/// Returns `Action::Modified` if the parameter existed before,
141+
/// but contained a different value. The value was updated to the
142+
/// newly-requested value.
143+
///
144+
/// Returns `Action::Existed` if the parameter existed before, and
145+
/// contained the same value as the newly-requested value. No
146+
/// modification was made.
147+
pub fn add_or_modify(&mut self, param: &Parameter) -> Action {
142148
let mut new_params = Vec::new();
143149
let mut modified = false;
144150
let mut seen_key = false;
@@ -170,14 +176,14 @@ impl<'a> Cmdline<'a> {
170176
self_mut.push(b' ');
171177
}
172178
self_mut.extend_from_slice(param.parameter);
173-
return true;
179+
return Action::Added;
174180
}
175181
if modified {
176182
self.0 = Cow::Owned(new_params.join(b" ".as_slice()));
177-
true
183+
Action::Modified
178184
} else {
179185
// The parameter already existed with the same content, and there were no duplicates.
180-
false
186+
Action::Existed
181187
}
182188
}
183189

@@ -654,22 +660,28 @@ mod tests {
654660
let mut kargs = Cmdline::from(b"foo=bar");
655661

656662
// add new
657-
assert!(kargs.add_or_modify(&param("baz")));
663+
assert!(matches!(kargs.add_or_modify(&param("baz")), Action::Added));
658664
let mut iter = kargs.iter();
659665
assert_eq!(iter.next(), Some(param("foo=bar")));
660666
assert_eq!(iter.next(), Some(param("baz")));
661667
assert_eq!(iter.next(), None);
662668

663669
// modify existing
664-
assert!(kargs.add_or_modify(&param("foo=fuz")));
670+
assert!(matches!(
671+
kargs.add_or_modify(&param("foo=fuz")),
672+
Action::Modified
673+
));
665674
iter = kargs.iter();
666675
assert_eq!(iter.next(), Some(param("foo=fuz")));
667676
assert_eq!(iter.next(), Some(param("baz")));
668677
assert_eq!(iter.next(), None);
669678

670679
// already exists with same value returns false and doesn't
671680
// modify anything
672-
assert!(!kargs.add_or_modify(&param("foo=fuz")));
681+
assert!(matches!(
682+
kargs.add_or_modify(&param("foo=fuz")),
683+
Action::Existed
684+
));
673685
iter = kargs.iter();
674686
assert_eq!(iter.next(), Some(param("foo=fuz")));
675687
assert_eq!(iter.next(), Some(param("baz")));
@@ -679,14 +691,17 @@ mod tests {
679691
#[test]
680692
fn test_add_or_modify_empty_cmdline() {
681693
let mut kargs = Cmdline::from(b"");
682-
assert!(kargs.add_or_modify(&param("foo")));
694+
assert!(matches!(kargs.add_or_modify(&param("foo")), Action::Added));
683695
assert_eq!(kargs.0, b"foo".as_slice());
684696
}
685697

686698
#[test]
687699
fn test_add_or_modify_duplicate_parameters() {
688700
let mut kargs = Cmdline::from(b"a=1 a=2");
689-
assert!(kargs.add_or_modify(&param("a=3")));
701+
assert!(matches!(
702+
kargs.add_or_modify(&param("a=3")),
703+
Action::Modified
704+
));
690705
let mut iter = kargs.iter();
691706
assert_eq!(iter.next(), Some(param("a=3")));
692707
assert_eq!(iter.next(), None);

crates/kernel_cmdline/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ pub mod utf8;
1717
pub const INITRD_ARG_PREFIX: &str = "rd.";
1818
/// The kernel argument for configuring the rootfs flags.
1919
pub const ROOTFLAGS: &str = "rootflags";
20+
21+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22+
/// Possible outcomes for `add_or_modify` operations.
23+
pub enum Action {
24+
/// The parameter did not exist before and was added
25+
Added,
26+
/// The parameter existed before, but contained a different value.
27+
/// The value was updated to the newly-requested value.
28+
Modified,
29+
/// The parameter existed before, and contained the same value as
30+
/// the newly-requested value. No modification was made.
31+
Existed,
32+
}

crates/kernel_cmdline/src/utf8.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use std::ops::Deref;
77

8-
use crate::bytes;
8+
use crate::{bytes, Action};
99

1010
use anyhow::Result;
1111

@@ -120,11 +120,17 @@ impl<'a> Cmdline<'a> {
120120

121121
/// Add or modify a parameter to the command line
122122
///
123-
/// Returns `true` if the parameter was added or modified.
123+
/// Returns `Action::Added` if the parameter did not exist before
124+
/// and was added.
124125
///
125-
/// Returns `false` if the parameter already existed with the same
126-
/// content.
127-
pub fn add_or_modify(&mut self, param: &Parameter) -> bool {
126+
/// Returns `Action::Modified` if the parameter existed before,
127+
/// but contained a different value. The value was updated to the
128+
/// newly-requested value.
129+
///
130+
/// Returns `Action::Existed` if the parameter existed before, and
131+
/// contained the same value as the newly-requested value. No
132+
/// modification was made.
133+
pub fn add_or_modify(&mut self, param: &Parameter) -> Action {
128134
self.0.add_or_modify(&param.0)
129135
}
130136

@@ -612,22 +618,28 @@ mod tests {
612618
let mut kargs = Cmdline::from("foo=bar");
613619

614620
// add new
615-
assert!(kargs.add_or_modify(&param("baz")));
621+
assert!(matches!(kargs.add_or_modify(&param("baz")), Action::Added));
616622
let mut iter = kargs.iter();
617623
assert_eq!(iter.next(), Some(param("foo=bar")));
618624
assert_eq!(iter.next(), Some(param("baz")));
619625
assert_eq!(iter.next(), None);
620626

621627
// modify existing
622-
assert!(kargs.add_or_modify(&param("foo=fuz")));
628+
assert!(matches!(
629+
kargs.add_or_modify(&param("foo=fuz")),
630+
Action::Modified
631+
));
623632
iter = kargs.iter();
624633
assert_eq!(iter.next(), Some(param("foo=fuz")));
625634
assert_eq!(iter.next(), Some(param("baz")));
626635
assert_eq!(iter.next(), None);
627636

628637
// already exists with same value returns false and doesn't
629638
// modify anything
630-
assert!(!kargs.add_or_modify(&param("foo=fuz")));
639+
assert!(matches!(
640+
kargs.add_or_modify(&param("foo=fuz")),
641+
Action::Existed
642+
));
631643
iter = kargs.iter();
632644
assert_eq!(iter.next(), Some(param("foo=fuz")));
633645
assert_eq!(iter.next(), Some(param("baz")));
@@ -637,14 +649,17 @@ mod tests {
637649
#[test]
638650
fn test_add_or_modify_empty_cmdline() {
639651
let mut kargs = Cmdline::from("");
640-
assert!(kargs.add_or_modify(&param("foo")));
652+
assert!(matches!(kargs.add_or_modify(&param("foo")), Action::Added));
641653
assert_eq!(kargs.as_ref(), "foo");
642654
}
643655

644656
#[test]
645657
fn test_add_or_modify_duplicate_parameters() {
646658
let mut kargs = Cmdline::from("a=1 a=2");
647-
assert!(kargs.add_or_modify(&param("a=3")));
659+
assert!(matches!(
660+
kargs.add_or_modify(&param("a=3")),
661+
Action::Modified
662+
));
648663
let mut iter = kargs.iter();
649664
assert_eq!(iter.next(), Some(param("a=3")));
650665
assert_eq!(iter.next(), None);

0 commit comments

Comments
 (0)