use std::ffi::CStr;
use std::mem;
use crate::error::{Error, Result};
use crate::linux_version::LinuxVersion;
use crate::utils::str_from_u8;
use libc::{uname, utsname};
pub struct Uname {
uts_struct: utsname,
}
impl Uname {
pub fn new() -> Result<Self> {
let mut uts_struct: utsname = unsafe { mem::zeroed() };
let ret_val = unsafe { uname(&mut uts_struct) };
if ret_val < 0 {
return Err(Error::UnameFailed);
}
Ok(Self { uts_struct })
}
pub fn print_info(&self) -> Result<()> {
let sysname = unsafe { CStr::from_ptr(self.uts_struct.sysname.as_ptr()) };
let hostname = unsafe { CStr::from_ptr(self.uts_struct.nodename.as_ptr()) };
let release = unsafe { CStr::from_ptr(self.uts_struct.release.as_ptr()) };
let arch = unsafe { CStr::from_ptr(self.uts_struct.machine.as_ptr()) };
let sysname = str_from_u8(sysname.to_bytes())?;
let hostname = str_from_u8(hostname.to_bytes())?;
let release = str_from_u8(release.to_bytes())?;
let arch = str_from_u8(arch.to_bytes())?;
println!("OS: {}", sysname);
println!("Hostname: {}", hostname);
println!("Version: {}", release);
println!("Architecture: {}", arch);
Ok(())
}
pub fn parse_version(&self) -> Result<LinuxVersion> {
let release = unsafe { CStr::from_ptr(self.uts_struct.release.as_ptr()) };
let release = str_from_u8(release.to_bytes())?;
let dot_idx = match release.find('.') {
Some(idx) => idx,
None => return Err(Error::InvalidLinuxVersion),
};
let (major, minor) = release.split_at(dot_idx);
let major = match major.parse::<u8>() {
Ok(major) => major,
Err(_) => return Err(Error::InvalidLinuxVersion),
};
let minor = &minor[1..];
let dot_idx = match minor.find('.') {
Some(idx) => idx,
None => return Err(Error::InvalidLinuxVersion),
};
let minor = match (&minor[0..dot_idx]).parse::<u8>() {
Ok(minor) => minor,
Err(_) => return Err(Error::InvalidLinuxVersion),
};
Ok(LinuxVersion { major, minor })
}
}