1+ //! Kernel command line parsing utilities.
2+ //!
3+ //! This module provides functionality for parsing and working with kernel command line
4+ //! arguments, supporting both key-only switches and key-value pairs with proper quote handling.
5+
16use std:: borrow:: Cow ;
27
38use anyhow:: Result ;
@@ -7,19 +12,35 @@ pub(crate) const INITRD_ARG_PREFIX: &[u8] = b"rd.";
712/// The kernel argument for configuring the rootfs flags.
813pub ( crate ) const ROOTFLAGS : & [ u8 ] = b"rootflags" ;
914
15+ /// A parsed kernel command line.
16+ ///
17+ /// Wraps the raw command line bytes and provides methods for parsing and iterating
18+ /// over individual parameters. Uses copy-on-write semantics to avoid unnecessary
19+ /// allocations when working with borrowed data.
1020pub ( crate ) struct Cmdline < ' a > ( Cow < ' a , [ u8 ] > ) ;
1121
1222impl < ' a , T : AsRef < [ u8 ] > + ?Sized > From < & ' a T > for Cmdline < ' a > {
23+ /// Creates a new `Cmdline` from any type that can be referenced as bytes.
24+ ///
25+ /// Uses borrowed data when possible to avoid unnecessary allocations.
1326 fn from ( input : & ' a T ) -> Self {
1427 Self ( Cow :: Borrowed ( input. as_ref ( ) ) )
1528 }
1629}
1730
1831impl < ' a > Cmdline < ' a > {
32+ /// Reads the kernel command line from `/proc/cmdline`.
33+ ///
34+ /// Returns an error if the file cannot be read or if there are I/O issues.
1935 pub fn from_proc ( ) -> Result < Self > {
2036 Ok ( Self ( Cow :: Owned ( std:: fs:: read ( "/proc/cmdline" ) ?) ) )
2137 }
2238
39+ /// Returns an iterator over all parameters in the command line.
40+ ///
41+ /// Properly handles quoted values containing whitespace and splits on
42+ /// unquoted whitespace characters. Parameters are parsed as either
43+ /// key-only switches or key=value pairs.
2344 pub fn iter ( & ' a self ) -> impl Iterator < Item = Parameter < ' a > > {
2445 let mut in_quotes = false ;
2546
@@ -34,29 +55,50 @@ impl<'a> Cmdline<'a> {
3455 }
3556
3657 /// Locate a kernel argument with the given key name.
58+ ///
59+ /// Returns the first parameter matching the given key, or `None` if not found.
60+ /// Key comparison treats dashes and underscores as equivalent.
3761 pub fn find ( & ' a self , key : impl AsRef < [ u8 ] > ) -> Option < Parameter < ' a > > {
3862 let key = key. as_ref ( ) ;
3963 self . iter ( ) . find ( |p| p. key == key)
4064 }
4165}
4266
67+ /// A single kernel command line parameter.
68+ ///
69+ /// Can represent either a simple switch (key only) or a key-value pair.
70+ /// Handles quoted values and treats dashes and underscores in keys as equivalent.
4371#[ derive( Debug , Eq ) ]
4472pub ( crate ) struct Parameter < ' a > {
73+ /// The parameter key as raw bytes
4574 pub key : & ' a [ u8 ] ,
75+ /// The parameter value as raw bytes, if present
4676 pub value : Option < & ' a [ u8 ] > ,
4777}
4878
4979impl < ' a > Parameter < ' a > {
80+ /// Returns the key as a lossy UTF-8 string.
81+ ///
82+ /// Invalid UTF-8 sequences are replaced with the Unicode replacement character.
5083 pub fn key_lossy ( & self ) -> String {
5184 String :: from_utf8_lossy ( self . key ) . to_string ( )
5285 }
5386
87+ /// Returns the value as a lossy UTF-8 string.
88+ ///
89+ /// Invalid UTF-8 sequences are replaced with the Unicode replacement character.
90+ /// Returns an empty string if no value is present.
5491 pub fn value_lossy ( & self ) -> String {
5592 String :: from_utf8_lossy ( self . value . unwrap_or ( & [ ] ) ) . to_string ( )
5693 }
5794}
5895
5996impl < ' a , T : AsRef < [ u8 ] > + ?Sized > From < & ' a T > for Parameter < ' a > {
97+ /// Parses a parameter from raw bytes.
98+ ///
99+ /// Splits on the first `=` character to separate key and value.
100+ /// Strips only the outermost pair of double quotes from values.
101+ /// If no `=` is found, treats the entire input as a key-only parameter.
60102 fn from ( input : & ' a T ) -> Self {
61103 let input = input. as_ref ( ) ;
62104 let equals = input. iter ( ) . position ( |b| * b == b'=' ) ;
@@ -90,6 +132,11 @@ impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for Parameter<'a> {
90132}
91133
92134impl PartialEq for Parameter < ' _ > {
135+ /// Compares two parameters for equality.
136+ ///
137+ /// Keys are compared with dashes and underscores treated as equivalent.
138+ /// Values must match exactly if both are present, or both must be absent.
139+ /// Prevents substring matching by ensuring full length equality.
93140 fn eq ( & self , other : & Self ) -> bool {
94141 let dedashed = |& c: & u8 | {
95142 if c == b'-' {
@@ -118,6 +165,11 @@ impl PartialEq for Parameter<'_> {
118165}
119166
120167impl std:: fmt:: Display for Parameter < ' _ > {
168+ /// Formats the parameter for display.
169+ ///
170+ /// Key-only parameters are displayed as just the key.
171+ /// Key-value parameters are displayed as `key=value`.
172+ /// Values containing whitespace are automatically quoted.
121173 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
122174 let key = self . key_lossy ( ) ;
123175
0 commit comments