mirror of https://github.com/aya-rs/aya
Simplify kernel version parsing
parent
c89c485bca
commit
16ed110359
@ -1,23 +1,42 @@
|
|||||||
use anyhow::bail;
|
use anyhow::{anyhow, Context as _};
|
||||||
use libc::{uname, utsname};
|
use libc::{uname, utsname};
|
||||||
use regex::Regex;
|
use std::{ffi::CStr, io::Error, mem};
|
||||||
use std::{cell::OnceCell, ffi::CStr, mem};
|
|
||||||
|
|
||||||
pub fn kernel_version() -> anyhow::Result<(u8, u8, u8)> {
|
pub fn kernel_version() -> anyhow::Result<(u8, u8, u8)> {
|
||||||
static mut RE: OnceCell<Regex> = OnceCell::new();
|
|
||||||
let re =
|
|
||||||
unsafe { &mut RE }.get_or_init(|| Regex::new(r"^([0-9]+)\.([0-9]+)\.([0-9]+)").unwrap());
|
|
||||||
let mut data: utsname = unsafe { mem::zeroed() };
|
let mut data: utsname = unsafe { mem::zeroed() };
|
||||||
let ret = unsafe { uname(&mut data) };
|
let ret = unsafe { uname(&mut data) };
|
||||||
assert!(ret >= 0, "libc::uname failed.");
|
if ret != 0 {
|
||||||
let release_cstr = unsafe { CStr::from_ptr(data.release.as_ptr()) };
|
return Err(Error::last_os_error()).context("uname failed");
|
||||||
let release = release_cstr.to_string_lossy();
|
|
||||||
if let Some(caps) = re.captures(&release) {
|
|
||||||
let major = caps.get(1).unwrap().as_str().parse().unwrap();
|
|
||||||
let minor = caps.get(2).unwrap().as_str().parse().unwrap();
|
|
||||||
let patch = caps.get(3).unwrap().as_str().parse().unwrap();
|
|
||||||
Ok((major, minor, patch))
|
|
||||||
} else {
|
|
||||||
bail!("no kernel version found");
|
|
||||||
}
|
}
|
||||||
|
let utsname { release, .. } = data;
|
||||||
|
let release: &[u8] =
|
||||||
|
unsafe { std::slice::from_raw_parts(release.as_ptr() as _, release.len()) };
|
||||||
|
let s = CStr::from_bytes_until_nul(release)?;
|
||||||
|
let s = s.to_str()?;
|
||||||
|
|
||||||
|
// Adapted from https://github.com/eminence/procfs/blob/d7ea846/procfs/src/sys/kernel/mod.rs#L51-L70.
|
||||||
|
let pos = s.find(|c: char| c != '.' && !c.is_ascii_digit());
|
||||||
|
let kernel = if let Some(pos) = pos {
|
||||||
|
let (s, _) = s.split_at(pos);
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
s
|
||||||
|
};
|
||||||
|
let mut kernel_split = kernel.split('.');
|
||||||
|
|
||||||
|
let major = kernel_split
|
||||||
|
.next()
|
||||||
|
.ok_or(anyhow!("Missing major version component"))?;
|
||||||
|
let minor = kernel_split
|
||||||
|
.next()
|
||||||
|
.ok_or(anyhow!("Missing minor version component"))?;
|
||||||
|
let patch = kernel_split
|
||||||
|
.next()
|
||||||
|
.ok_or(anyhow!("Missing patch version component"))?;
|
||||||
|
|
||||||
|
let major = major.parse().context("Failed to parse major version")?;
|
||||||
|
let minor = minor.parse().context("Failed to parse minor version")?;
|
||||||
|
let patch = patch.parse().context("Failed to parse patch version")?;
|
||||||
|
|
||||||
|
Ok((major, minor, patch))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue