Skip to content

Commit

Permalink
minimally refactor ubuntu kernel version parsing to be testable
Browse files Browse the repository at this point in the history
  • Loading branch information
belohnung authored and alessandrod committed Jun 13, 2024
1 parent 4972b92 commit ef08eb3
Showing 1 changed file with 44 additions and 14 deletions.
58 changes: 44 additions & 14 deletions aya/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,29 +88,48 @@ impl KernelVersion {
(u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch)
}

// This is ported from https://github.com/torvalds/linux/blob/3f01e9f/tools/lib/bpf/libbpf_probes.c#L21-L101.

// This (L92-L133) is ported from https://github.com/torvalds/linux/blob/3f01e9f/tools/lib/bpf/libbpf_probes.c#L21-L101.
fn get_ubuntu_kernel_version() -> Result<Option<Self>, CurrentKernelVersionError> {
if let Some(content) = Self::read_ubuntu_kernel_version_file()? {
if let Some(v) = Self::parse_ubuntu_kernel_version(&content).ok().flatten() {
return Ok(Some(v));
}
}
Ok(None)
}

fn parse_ubuntu_kernel_version(
ubuntu_kver_file_content: &str,
) -> Result<Option<Self>, CurrentKernelVersionError> {
let mut parts = ubuntu_kver_file_content.split_terminator(char::is_whitespace);
let mut next = || {
parts.next().ok_or_else(|| {
CurrentKernelVersionError::ParseError(ubuntu_kver_file_content.to_string())
})
};
let _ubuntu: &str = next()?;
let _ubuntu_version: &str = next()?;
let kernel_version_string = next()?;
Self::parse_kernel_version_string(kernel_version_string).map(Some)
}

fn read_ubuntu_kernel_version_file() -> Result<Option<String>, CurrentKernelVersionError> {
const UBUNTU_KVER_FILE: &str = "/proc/version_signature";
let s = match fs::read_to_string(UBUNTU_KVER_FILE) {
Ok(s) => s,
Ok(s) => {
if s.is_empty() {
return Ok(None);
}
s
}
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
return Ok(None);
}
return Err(e.into());
}
};
let mut parts = s.split_terminator(char::is_whitespace);
let mut next = || {
parts
.next()
.ok_or_else(|| CurrentKernelVersionError::ParseError(s.to_string()))
};
let _ubuntu: &str = next()?;
let _ubuntu_version: &str = next()?;
let kernel_version_string = next()?;
Self::parse_kernel_version_string(kernel_version_string).map(Some)
Ok(Some(s))
}

fn get_debian_kernel_version(
Expand All @@ -130,7 +149,7 @@ impl KernelVersion {
}

fn get_kernel_version() -> Result<Self, CurrentKernelVersionError> {
if let Some(v) = Self::get_ubuntu_kernel_version().ok().flatten() {
if let Some(v) = Self::get_ubuntu_kernel_version()? {
return Ok(v);
}

Expand Down Expand Up @@ -381,6 +400,17 @@ mod tests {

#[test]
fn test_parse_kernel_version_string() {
// cat /proc/version_signature on Proxmox VE 8.1.4
assert_matches!(
KernelVersion::parse_ubuntu_kernel_version(""),
Err(CurrentKernelVersionError::ParseError(s)) => { s.is_empty() }
);
// cat /proc/version_signature on Ubuntu 22.04
assert_matches!(KernelVersion::parse_ubuntu_kernel_version(
"Ubuntu 5.15.0-82.91-generic 5.15.111"
), Ok(Some(kernel_version))=> {
assert_eq!(kernel_version, KernelVersion::new(5, 15, 111))
});
// WSL.
assert_matches!(KernelVersion::parse_kernel_version_string("5.15.90.1-microsoft-standard-WSL2"), Ok(kernel_version) => {
assert_eq!(kernel_version, KernelVersion::new(5, 15, 90))
Expand Down

0 comments on commit ef08eb3

Please sign in to comment.