1use 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}