bijux_cli/features/diagnostics/
state_diagnostics.rs1#![forbid(unsafe_code)]
2use std::fs;
5use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9#[allow(clippy::struct_excessive_bools)]
10pub struct StatePathStatus {
11 pub path: PathBuf,
13 pub exists: bool,
15 pub is_file: bool,
17 pub is_dir: bool,
19 pub size_bytes: u64,
21 pub readable: bool,
23 pub writable: bool,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct StateDiagnosticsQuery {
30 pub config: StatePathStatus,
32 pub history: StatePathStatus,
34 pub plugins_registry: StatePathStatus,
36 pub memory: StatePathStatus,
38}
39
40fn parent_dir_is_writable(path: &Path) -> bool {
41 let mut cursor = path.parent();
42 while let Some(parent) = cursor {
43 if let Ok(metadata) = fs::metadata(parent) {
44 return metadata.is_dir() && !metadata.permissions().readonly();
45 }
46 cursor = parent.parent();
47 }
48 false
49}
50
51fn state_path_status(path: &Path) -> StatePathStatus {
52 let metadata = fs::metadata(path);
53 StatePathStatus {
54 path: path.to_path_buf(),
55 exists: metadata.is_ok(),
56 is_file: metadata.as_ref().is_ok_and(std::fs::Metadata::is_file),
57 is_dir: metadata.as_ref().is_ok_and(std::fs::Metadata::is_dir),
58 size_bytes: metadata.as_ref().map_or(0_u64, |entry| entry.len()),
59 readable: fs::read(path).is_ok(),
60 writable: if path.exists() {
61 fs::OpenOptions::new().append(true).open(path).is_ok()
62 } else {
63 parent_dir_is_writable(path)
64 },
65 }
66}
67
68#[must_use]
70pub fn state_diagnostics_query(
71 config: &Path,
72 history: &Path,
73 plugins_registry: &Path,
74 memory: &Path,
75) -> StateDiagnosticsQuery {
76 StateDiagnosticsQuery {
77 config: state_path_status(config),
78 history: state_path_status(history),
79 plugins_registry: state_path_status(plugins_registry),
80 memory: state_path_status(memory),
81 }
82}