libkelp/lib/util/
os.rs

1use anyhow::{Context, Result};
2use kelpdot_macros::*;
3use serde::{Deserialize, Serialize};
4use std::path::Path;
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct Os {
7    /// Name of the os
8    pub name: String,
9    /// File used to reconise it
10    pub file: String,
11    /// "Priority" of the OS
12    /// For example
13    /// Arch has pritority 1 and file /etc/arch-release
14    /// And manjaro has priority 2 and files /etc/arch-release AND /etc/manjaro-release
15    /// If both /etc/manjaro-release and /etc/arch-release exists, the higher priority will be used
16    /// In this case it's 2 (manjaro)
17    pub priority: i16,
18    /// The "pretty" name of the OS: for example "Arch GNU/Linux"
19    pub prettyname: String,
20    /// Submatches (parent distros)
21    pub submatches: Vec<String>,
22}
23/// Find oses to detect
24pub fn build_os_list() -> Result<Vec<Os>> {
25    let mut osyaml: Vec<Os> = vec![];
26    let search_paths = vec!["/etc/kelpdot/os.yaml", "/etc/kelpdot/os.yml"];
27    for path in search_paths {
28        if Path::new(path).exists() {
29            debug_print!("Reading OS file {}", path);
30            let content = std::fs::read_to_string(path)
31                .with_context(|| red!("Unable to read OS file {}", path))?;
32            let yaml: Vec<Os> = serde_yaml::from_str(&content)
33                .with_context(|| red!("Failed to parse OS file {}", path))?;
34            for os in yaml {
35                osyaml.push(os);
36            }
37        }
38    }
39    debug_print!("Reading bundled OS file...");
40    let bundled = include_str!("../../config/oses.yaml");
41    let oses: Vec<Os> = serde_yaml::from_str(&bundled).with_context(|| {
42        red!("Unable to parse bundled OS list file (please report this with a GitHub issue)")
43    })?;
44    for os in oses {
45        osyaml.push(os);
46    }
47    Ok(osyaml)
48}
49/// Gets the host's OS
50pub fn get_host_os() -> anyhow::Result<Os> {
51    // Get a Vec<Os> wich is a list of reconisables oses
52    let oses = build_os_list()?;
53    let mut validoses: Vec<Os> = vec![];
54    for system in oses {
55        if Path::new(&system.file).exists() && system.name != "generic" {
56            validoses.push(system);
57        }
58    }
59    let mut sys: Os = Os {
60        name: String::from("generic"),
61        file: String::from("/"),
62        priority: 0,
63        prettyname: String::from("Generic GNU/Linux OS"),
64        submatches: vec![],
65    };
66    for system in validoses {
67        if sys.priority < system.priority {
68            sys = system;
69        }
70    }
71    Ok(sys)
72}
73
74pub fn is_os(name: &str) -> Result<bool> {
75    let os = get_host_os()?;
76    if os.submatches.iter().any(|x| x == name) || os.name == name {
77        return Ok(true);
78    }
79    Ok(false)
80}