ferrix_app/
dmi.rs

1/* dmi.rs
2 *
3 * Copyright 2025 Michail Krasnov <mskrasnov07@ya.ru>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21//! DMI Service Provider
22
23use anyhow::Result;
24use async_std::task;
25use ferrix_lib::dmi::{Baseboard, Chassis, Processor, Bios};
26use serde::{Deserialize, Serialize};
27use std::process::Command;
28
29use crate::DataLoadingState;
30
31pub async fn get_dmi_data() -> DataLoadingState<DMIResult> {
32    let output = task::spawn_blocking(|| {
33        Command::new("pkexec")
34            .arg("/usr/bin/ferrix-polkit")
35            .arg("dmi")
36            .output()
37    })
38    .await;
39
40    if let Err(why) = output {
41        return DataLoadingState::Error(why.to_string());
42    }
43    let output = output.unwrap();
44    if !output.status.success() {
45        return DataLoadingState::Error(format!(
46            "[ferrix-polkit] Non-zero return code:\n{}",
47            String::from_utf8_lossy(&output.stderr)
48        ));
49    }
50
51    let json_str = String::from_utf8_lossy(&output.stdout);
52    let json_data = DMIResult::from_json(&json_str);
53
54    match json_data {
55        Ok(data) => DataLoadingState::Loaded(data),
56        Err(why) => DataLoadingState::Error(why.to_string()),
57    }
58}
59
60#[derive(Debug, Serialize, Deserialize, Clone)]
61#[serde(untagged)]
62pub enum DMIResult {
63    Ok { data: DMIData },
64    Error { error: String },
65}
66
67impl DMIResult {
68    pub fn new() -> Self {
69        match DMIData::new() {
70            Ok(data) => Self::Ok { data },
71            Err(why) => Self::Error {
72                error: why.to_string(),
73            },
74        }
75    }
76
77    pub fn to_json(&self) -> Result<String> {
78        let contents = serde_json::to_string(&self)?;
79        Ok(contents)
80    }
81
82    pub fn from_json(json: &str) -> Result<Self> {
83        Ok(serde_json::from_str(json)?)
84    }
85}
86
87#[derive(Debug, Serialize, Deserialize, Clone)]
88pub struct DMIData {
89    pub bios: Bios,
90    pub baseboard: Baseboard,
91    pub chassis: Chassis,
92    pub processor: Processor,
93}
94
95impl DMIData {
96    pub fn new() -> Result<Self> {
97        Ok(Self {
98            bios: Bios::new()?,
99            baseboard: Baseboard::new()?,
100            chassis: Chassis::new()?,
101            processor: Processor::new()?,
102        })
103    }
104}