1use anyhow::Result;
24use async_std::task;
25use ferrix_lib::dmi::{Baseboard, Bios, Chassis, Processor};
26use serde::{Deserialize, Serialize};
27use std::{path::Path, process::Command};
28
29use crate::load_state::{LoadState, ToLoadState};
30
31fn auth_app() -> Option<&'static str> {
32 let apps = ["pkexec", "gksudo"];
33 let bin_dirs = ["/usr/sbin", "/sbin", "/usr/bin", "/bin"];
34
35 for a in apps {
36 for b in bin_dirs {
37 if Path::new(b).join(a).exists() {
38 return Some(a);
39 }
40 }
41 }
42
43 None
44}
45
46pub async fn get_dmi_data() -> LoadState<DMIData> {
47 let auth_app = match auth_app() {
48 Some(auth_app) => auth_app,
49 None => return LoadState::Error("No authentication software found".to_string()),
50 };
51
52 let output = task::spawn_blocking(move || {
53 Command::new(auth_app)
54 .arg("ferrix-polkit")
55 .arg("dmi")
56 .output()
57 })
58 .await;
59
60 if let Err(why) = output {
61 return LoadState::Error(why.to_string());
62 }
63 let output = output.unwrap();
64 if output.status.code().unwrap_or(0) != 0 {
65 return LoadState::Error(format!(
66 "[ferrix-polkit] Non-zero return code:\n{}",
67 String::from_utf8_lossy(&output.stderr)
68 ));
69 }
70
71 let json_str = String::from_utf8_lossy(&output.stdout);
72 let json_data = DMIData::from_json(&json_str);
73
74 match json_data {
75 Ok(data) => LoadState::Loaded(data),
76 Err(why) => LoadState::Error(why.to_string()),
77 }
78}
79
80#[derive(Debug, Serialize, Deserialize, Clone)]
81pub struct DMIData {
82 pub bios: LoadState<Bios>,
83 pub baseboard: LoadState<Baseboard>,
84 pub chassis: LoadState<Chassis>,
85 pub processor: LoadState<Processor>,
86}
87
88impl DMIData {
89 pub fn new() -> Self {
90 Self {
91 bios: Bios::new().to_load_state(),
92 baseboard: Baseboard::new().to_load_state(),
93 chassis: Chassis::new().to_load_state(),
94 processor: Processor::new().to_load_state(),
95 }
96 }
97
98 pub fn to_json(&self) -> Result<String> {
99 let contents = serde_json::to_string(&self)?;
100 Ok(contents)
101 }
102
103 pub fn from_json(json: &str) -> Result<Self> {
104 Ok(serde_json::from_str(json)?)
105 }
106}