use anyhow::Result;
use serde::Serialize;
use std::path::PathBuf;
use std::process::Command;
#[derive(Debug, Clone, Serialize)]
pub struct LogSource {
pub label: String,
pub path: Option<PathBuf>,
pub size_bytes: u64,
}
pub fn scan_logs() -> Vec<LogSource> {
let mut out = Vec::new();
if let Some(size) = journald_size() {
out.push(LogSource { label: "journald".into(), path: Some(PathBuf::from("/var/log/journal")), size_bytes: size });
}
for p in ["/var/log/syslog", "/var/log/syslog.1", "/var/log/kern.log"] {
if let Ok(meta) = std::fs::metadata(p) {
out.push(LogSource { label: p.to_string(), path: Some(PathBuf::from(p)), size_bytes: meta.len() });
}
}
if let Some(home) = dirs::home_dir() {
let share = home.join(".local/share");
if let Ok(entries) = std::fs::read_dir(&share) {
for e in entries.flatten() {
let p = e.path();
if p.extension().and_then(|x| x.to_str()) == Some("log") {
if let Ok(meta) = e.metadata() {
out.push(LogSource { label: p.display().to_string(), path: Some(p), size_bytes: meta.len() });
}
}
}
}
}
out.sort_by(|a, b| b.size_bytes.cmp(&a.size_bytes));
out
}
fn journald_size() -> Option<u64> {
let out = Command::new("journalctl").arg("--disk-usage").output().ok()?;
let text = String::from_utf8_lossy(&out.stdout);
let mb = text.split_whitespace().find(|w| w.parse::<f64>().is_ok())?.parse::<f64>().ok()?;
Some((mb * 1024.0 * 1024.0) as u64)
}
pub fn vacuum_journald(keep: &str) -> Result<()> {
Command::new("journalctl").arg(format!("--vacuum-time={keep}")).status()?;
Ok(())
}