use std::path::Path;
use regex::Regex;
#[derive(Debug)]
pub enum OSErrors {
NoSuchFile,
FailedToRead,
RegexError,
NoSuchField,
}
pub const OS_RELEASE_PATHS: [&str; 3] = [
"/bedrock/etc/os-release",
"/etc/os-release",
"/usr/lib/os-release",
];
impl std::fmt::Display for OSErrors {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let error_msg = match self {
OSErrors::NoSuchFile => "Couldn't find os-release",
OSErrors::FailedToRead => "Failed to read os-release",
OSErrors::RegexError => "Regex failed",
OSErrors::NoSuchField => "No such field exists in the file",
};
write!(f, "{}", error_msg)
}
}
impl std::error::Error for OSErrors {}
pub fn get_os() -> Result<String, OSErrors> {
read_value_os_release("NAME")
}
pub fn get_os_id() -> Result<String, OSErrors> {
read_value_os_release("ID")
}
pub fn get_os_version() -> Result<String, OSErrors> {
read_value_os_release("VERSION_ID")
}
pub fn find_os_release() -> Result<String, OSErrors> {
for os_release in OS_RELEASE_PATHS {
if Path::new(os_release).exists() {
return Ok(os_release.to_string());
}
}
Err(OSErrors::NoSuchFile)
}
pub fn read_value_os_release(value: &str) -> Result<String, OSErrors> {
let os_release_path = find_os_release().map_err(|_| OSErrors::NoSuchFile)?;
let content = std::fs::read_to_string(os_release_path).map_err(|_| OSErrors::FailedToRead)?;
let reg_format = format!(r#"(?m)^{}=(?:"(.*?)"|(.+))$"#, regex::escape(value));
let reg = Regex::new(®_format).map_err(|_| OSErrors::RegexError)?;
let captures = reg.captures(&content).ok_or(OSErrors::NoSuchField)?;
captures
.get(2)
.or(captures.get(1))
.map(|m| m.as_str().to_string())
.ok_or(OSErrors::FailedToRead)
}