diff --git a/Cargo.lock b/Cargo.lock index c0a01b6..aafa565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "ahash" version = "0.8.7" @@ -528,6 +534,15 @@ dependencies = [ "libc", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -537,6 +552,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -603,6 +627,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "dary_heap" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" + [[package]] name = "derivative" version = "2.2.0" @@ -1160,6 +1190,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -1220,7 +1259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", "serde", ] @@ -1303,6 +1342,7 @@ dependencies = [ "futures", "lact-schema", "libdrm_amdgpu_sys", + "libflate", "nix 0.27.1", "os-release", "pciid-parser", @@ -1398,6 +1438,30 @@ dependencies = [ "libc", ] +[[package]] +name = "libflate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7d5654ae1795afc7ff76f4365c2c8791b0feb18e8996a96adad8ffd7c3b2bf" +dependencies = [ + "adler32", + "core2", + "crc32fast", + "dary_heap", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5f52fb8c451576ec6b79d3f4deb327398bc05bbdbd99021a6e77a4c855d524" +dependencies = [ + "core2", + "hashbrown 0.13.2", + "rle-decode-fast", +] + [[package]] name = "libloading" version = "0.7.4" @@ -1886,6 +1950,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/lact-daemon/Cargo.toml b/lact-daemon/Cargo.toml index a25c790..0c3dcf0 100644 --- a/lact-daemon/Cargo.toml +++ b/lact-daemon/Cargo.toml @@ -36,5 +36,6 @@ futures = { version = "0.3.30", default-features = false } zbus = { version = "3.14.1", default-features = false, features = ["tokio"] } libdrm_amdgpu_sys = { optional = true, version = "0.5.0" } tar = "0.4.40" +libflate = "2.0.0" chrono = "0.4.31" os-release = "0.1.0" diff --git a/lact-daemon/src/server/handler.rs b/lact-daemon/src/server/handler.rs index e977f69..85f1cb5 100644 --- a/lact-daemon/src/server/handler.rs +++ b/lact-daemon/src/server/handler.rs @@ -1,6 +1,6 @@ use super::{ gpu_controller::{fan_control::FanCurve, GpuController}, - system::PP_FEATURE_MASK_PATH, + system::{self, detect_initramfs_type, PP_FEATURE_MASK_PATH}, }; use crate::config::{self, default_fan_static_speed, Config, FanControlSettings}; use amdgpu_sysfs::{ @@ -14,6 +14,9 @@ use lact_schema::{ ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanCurveMap, PmfwOptions, PowerStates, }; +use libflate::gzip; +use os_release::OS_RELEASE; +use serde_json::json; use std::{ cell::RefCell, collections::BTreeMap, @@ -432,11 +435,12 @@ impl<'a> Handler { pub fn generate_snapshot(&self) -> anyhow::Result { let datetime = chrono::Local::now().format("%Y%m%d-%H%M%S"); - let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar"); + let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar.gz"); let out_file = File::create(&out_path) .with_context(|| "Could not create output file at {out_path}")?; - let out_writer = BufWriter::new(out_file); + let out_writer = gzip::Encoder::new(BufWriter::new(out_file)) + .context("Could not create GZIP encoder")?; let mut archive = tar::Builder::new(out_writer); @@ -481,10 +485,35 @@ impl<'a> Handler { } } + let system_info = system::info() + .ok() + .map(|info| serde_json::to_value(info).unwrap()); + let initramfs_type = match OS_RELEASE.as_ref() { + Ok(os_release) => detect_initramfs_type(os_release) + .map(|initramfs_type| serde_json::to_value(initramfs_type).unwrap()), + Err(err) => Some(err.to_string().into()), + }; + + let info = json!({ + "system_info": system_info, + "initramfs_type": initramfs_type, + }); + let info_data = serde_json::to_vec_pretty(&info).unwrap(); + + let mut info_header = tar::Header::new_gnu(); + info_header.set_size(info_data.len().try_into().unwrap()); + info_header.set_mode(0o755); + info_header.set_cksum(); + + archive.append_data(&mut info_header, "info.json", Cursor::new(info_data))?; + let mut writer = archive.into_inner().context("Could not finish archive")?; writer.flush().context("Could not flush output file")?; writer + .finish() + .into_result() + .context("Could not finish GZIP archive")? .into_inner()? .set_permissions(Permissions::from_mode(0o775)) .context("Could not set permissions on output file")?; diff --git a/lact-daemon/src/server/system.rs b/lact-daemon/src/server/system.rs index 58e62c2..120583e 100644 --- a/lact-daemon/src/server/system.rs +++ b/lact-daemon/src/server/system.rs @@ -115,7 +115,7 @@ fn regenerate_initramfs() -> anyhow::Result { } } -fn detect_initramfs_type(os_release: &OsRelease) -> Option { +pub(crate) fn detect_initramfs_type(os_release: &OsRelease) -> Option { let id_like: Vec<_> = os_release.id_like.split_whitespace().collect(); if os_release.id == "debian" || id_like.contains(&"debian") {