nixos-init: pick the last init= on the kernel cmdline
This matches the behaviour of both the scripted initrd and the kernel itself.
This commit is contained in:
@@ -87,20 +87,16 @@ pub fn find_init_in_prefix(prefix: &str) -> Result<PathBuf> {
|
||||
}
|
||||
|
||||
/// Extract the value of the `init` parameter from the given kernel `cmdline`.
|
||||
///
|
||||
/// If `init=` appears multiple times the last one wins, matching the kernel.
|
||||
/// This is what makes appending `init=/bin/sh` at the boot prompt work even
|
||||
/// though the boot entry already has an `init=`.
|
||||
fn extract_init(cmdline: &str) -> Result<PathBuf> {
|
||||
let init_params: Vec<&str> = cmdline
|
||||
let init = cmdline
|
||||
.split_ascii_whitespace()
|
||||
.filter(|p| p.starts_with("init="))
|
||||
.collect();
|
||||
|
||||
if init_params.len() != 1 {
|
||||
bail!("Expected exactly one init param on kernel cmdline: {cmdline}")
|
||||
}
|
||||
|
||||
let init = init_params
|
||||
.first()
|
||||
.and_then(|s| s.split('=').next_back())
|
||||
.context("Failed to extract init path from kernel cmdline: {cmdline}")?;
|
||||
.filter_map(|p| p.strip_prefix("init="))
|
||||
.next_back()
|
||||
.with_context(|| format!("No init= parameter on kernel cmdline: {cmdline}"))?;
|
||||
|
||||
Ok(PathBuf::from(init))
|
||||
}
|
||||
@@ -129,4 +125,25 @@ mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_init_single() {
|
||||
assert_eq!(
|
||||
extract_init("root=fstab init=/nix/store/xxx-nixos/init quiet").unwrap(),
|
||||
PathBuf::from("/nix/store/xxx-nixos/init")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_init_last_wins() {
|
||||
assert_eq!(
|
||||
extract_init("init=/nix/store/xxx-nixos/init init=/bin/sh").unwrap(),
|
||||
PathBuf::from("/bin/sh")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_init_missing() {
|
||||
assert!(extract_init("root=fstab quiet").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user