pscand-cli: cleanup
Fixes path expansion and scanner lock release. Among other things. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia8695314852aaa4914f59da57351d1086a6a6964
This commit is contained in:
parent
5850f342a1
commit
9bec96db1b
4 changed files with 660 additions and 483 deletions
72
Cargo.lock
generated
72
Cargo.lock
generated
|
|
@ -82,6 +82,15 @@ version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.0"
|
version = "3.20.0"
|
||||||
|
|
@ -176,12 +185,41 @@ version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.21"
|
version = "0.8.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
|
|
@ -248,6 +286,16 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
|
@ -533,6 +581,7 @@ dependencies = [
|
||||||
"ringbuf",
|
"ringbuf",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -730,6 +779,17 @@ dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
|
@ -880,6 +940,12 @@ version = "1.0.6+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -892,6 +958,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ parking_lot = "0.12.5"
|
||||||
ringbuf = "0.4.8"
|
ringbuf = "0.4.8"
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
clap = { version = "4.5.59", features = ["derive"] }
|
clap = { version = "4.5.59", features = ["derive"] }
|
||||||
|
sha2 = "0.10.9"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,4 @@ ringbuf.workspace = true
|
||||||
dirs.workspace = true
|
dirs.workspace = true
|
||||||
sysinfo.workspace = true
|
sysinfo.workspace = true
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
|
sha2.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,31 @@
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use libloading::Library;
|
use libloading::Library;
|
||||||
|
use pscand_core::Config as CoreConfig;
|
||||||
use pscand_core::logging::{LogLevel, RingBufferLogger};
|
use pscand_core::logging::{LogLevel, RingBufferLogger};
|
||||||
use pscand_core::scanner::Scanner;
|
use pscand_core::scanner::Scanner;
|
||||||
use pscand_core::Config as CoreConfig;
|
use sha2::{Digest, Sha256};
|
||||||
use std::path::PathBuf;
|
use std::fs;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::io::Read;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tokio::time::interval;
|
use tokio::time::interval;
|
||||||
|
|
||||||
type ScannerCreator = pscand_core::ScannerCreatorFfi;
|
type ScannerCreator = pscand_core::ScannerCreatorFfi;
|
||||||
|
|
||||||
|
fn expand_path(path: &Path) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||||
|
let path_str = path.to_str().ok_or("Invalid path encoding")?;
|
||||||
|
if path_str.starts_with("~/") {
|
||||||
|
if let Some(home) = dirs::home_dir() {
|
||||||
|
return Ok(home.join(&path_str[2..]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(path.to_path_buf())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(
|
#[command(
|
||||||
name = "pscand",
|
name = "pscand",
|
||||||
|
|
@ -34,6 +47,37 @@ struct RunArgs {
|
||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_library(path: &Path) -> Result<(), String> {
|
||||||
|
let mut file = fs::File::open(path).map_err(|e| {
|
||||||
|
format!(
|
||||||
|
"failed to open library {} for verification: {}",
|
||||||
|
path.display(),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let mut buffer = [0u8; 4096];
|
||||||
|
let bytes_read = file.read(&mut buffer).map_err(|e| {
|
||||||
|
format!(
|
||||||
|
"failed to read library {} for hash calculation: {}",
|
||||||
|
path.display(),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if bytes_read < 4 {
|
||||||
|
return Err(format!(
|
||||||
|
"library {} is too small to be valid",
|
||||||
|
path.display()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(&buffer[..bytes_read]);
|
||||||
|
let _hash = hasher.finalize();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
struct LoadedScanner {
|
struct LoadedScanner {
|
||||||
name: String,
|
name: String,
|
||||||
scanner: Arc<RwLock<Box<dyn Scanner>>>,
|
scanner: Arc<RwLock<Box<dyn Scanner>>>,
|
||||||
|
|
@ -115,9 +159,14 @@ impl DaemonState {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_status(&self, logger: &RingBufferLogger) -> std::io::Result<()> {
|
async fn write_status(
|
||||||
|
&self,
|
||||||
|
logger: &RingBufferLogger,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
let uptime = SystemTime::now()
|
let uptime = SystemTime::now()
|
||||||
.duration_since(self.start_time.try_read().map(|t| *t).unwrap_or(UNIX_EPOCH))
|
.duration_since(
|
||||||
|
self.start_time.try_read().map(|t| *t).unwrap_or(UNIX_EPOCH),
|
||||||
|
)
|
||||||
.map(|d| d.as_secs())
|
.map(|d| d.as_secs())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let collections = self.collection_count.try_read().map(|c| *c).unwrap_or(0);
|
let collections = self.collection_count.try_read().map(|c| *c).unwrap_or(0);
|
||||||
|
|
@ -158,10 +207,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
match args {
|
match args {
|
||||||
Args::Run(run_args) => {
|
Args::Run(run_args) => {
|
||||||
run_daemon(run_args).await?;
|
run_daemon(run_args).await?;
|
||||||
}
|
},
|
||||||
Args::List => {
|
Args::List => {
|
||||||
list_scanners().await?;
|
list_scanners().await?;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -169,30 +218,44 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if args.debug {
|
if args.debug {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
|
env_logger::Builder::from_env(
|
||||||
|
env_logger::Env::default().default_filter_or("debug"),
|
||||||
|
)
|
||||||
|
.init();
|
||||||
} else {
|
} else {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(
|
||||||
|
env_logger::Env::default().default_filter_or("info"),
|
||||||
|
)
|
||||||
|
.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Starting pscand daemon");
|
log::info!("Starting pscand daemon");
|
||||||
|
|
||||||
let config = if args.config.exists() {
|
// Expand ~ in config path
|
||||||
CoreConfig::load(&args.config)?
|
let config_path = expand_path(&args.config)
|
||||||
|
.map_err(|e| format!("Failed to expand config path: {}", e))?;
|
||||||
|
|
||||||
|
let config = if config_path.exists() {
|
||||||
|
CoreConfig::load(&config_path)?
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Config file not found at {:?}", args.config);
|
log::warn!("Config file not found at {:?}", config_path);
|
||||||
log::info!("Creating default config. Run with --config to specify a different path.");
|
log::info!(
|
||||||
|
"Creating default config. Run with --config to specify a different path."
|
||||||
|
);
|
||||||
|
|
||||||
// Create default config directory if it doesn't exist
|
// Create default config directory if it doesn't exist
|
||||||
if let Some(parent) = args.config.parent() {
|
if let Some(parent) = config_path.parent() {
|
||||||
if let Err(e) = std::fs::create_dir_all(parent) {
|
if let Err(e) = std::fs::create_dir_all(parent) {
|
||||||
log::warn!("Failed to create config directory: {}", e);
|
log::error!("Failed to create config directory {:?}: {}", parent, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreConfig::default()
|
CoreConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
std::fs::create_dir_all(&config.log_dir)?;
|
std::fs::create_dir_all(&config.log_dir).map_err(|e| {
|
||||||
|
format!("Failed to create log directory {:?}: {}", config.log_dir, e)
|
||||||
|
})?;
|
||||||
|
|
||||||
let log_file = config.log_dir.join("pscand.log");
|
let log_file = config.log_dir.join("pscand.log");
|
||||||
let logger = Arc::new(RingBufferLogger::new(
|
let logger = Arc::new(RingBufferLogger::new(
|
||||||
|
|
@ -267,8 +330,12 @@ async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if scanners.is_empty() {
|
if scanners.is_empty() {
|
||||||
log::error!("No scanners loaded!");
|
log::error!("No scanners loaded!");
|
||||||
log::error!("Please ensure:");
|
log::error!("Please ensure:");
|
||||||
log::error!(" 1. Scanner plugins are installed in one of the configured directories");
|
log::error!(
|
||||||
log::error!(" 2. Scanner directories are correctly set in config file or PSCAND_SCANNER_DIRS env var");
|
" 1. Scanner plugins are installed in one of the configured directories"
|
||||||
|
);
|
||||||
|
log::error!(
|
||||||
|
" 2. Scanner directories are correctly set in config file or PSCAND_SCANNER_DIRS env var"
|
||||||
|
);
|
||||||
log::error!(" 3. Scanners are not disabled in the configuration");
|
log::error!(" 3. Scanners are not disabled in the configuration");
|
||||||
logger.log(
|
logger.log(
|
||||||
LogLevel::Error,
|
LogLevel::Error,
|
||||||
|
|
@ -327,7 +394,7 @@ async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
logger.log(
|
logger.log(
|
||||||
LogLevel::Error,
|
LogLevel::Error,
|
||||||
|
|
@ -335,16 +402,22 @@ async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
"final_collection_error",
|
"final_collection_error",
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
state.record_collection().await;
|
state.record_collection().await;
|
||||||
state.update_heartbeat().await.ok();
|
if let Err(e) = state.update_heartbeat().await {
|
||||||
|
log::warn!("Failed to update heartbeat during shutdown: {}", e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let scan_start = Instant::now();
|
let scan_start = Instant::now();
|
||||||
let scanner_guard = scanner.read().await;
|
let collect_result = {
|
||||||
match scanner_guard.collect() {
|
let guard = scanner.read().await;
|
||||||
|
guard.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
match collect_result {
|
||||||
Ok(metrics) => {
|
Ok(metrics) => {
|
||||||
let elapsed = scan_start.elapsed().as_millis();
|
let elapsed = scan_start.elapsed().as_millis();
|
||||||
logger.log(
|
logger.log(
|
||||||
|
|
@ -358,13 +431,24 @@ async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
state.record_collection().await;
|
state.record_collection().await;
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
logger.log(LogLevel::Error, &name, "collection_error", e.to_string());
|
logger.log(
|
||||||
|
LogLevel::Error,
|
||||||
|
&name,
|
||||||
|
"collection_error",
|
||||||
|
e.to_string(),
|
||||||
|
);
|
||||||
state.record_error().await;
|
state.record_error().await;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if let Err(e) = state.update_heartbeat().await {
|
||||||
|
log::warn!("Failed to update heartbeat: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.update_heartbeat().await.ok();
|
|
||||||
|
if let Err(e) = scanner.write().await.cleanup() {
|
||||||
|
logger.log(LogLevel::Warn, &name, "cleanup_error", e.to_string());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -379,12 +463,15 @@ async fn run_daemon(args: RunArgs) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut ticker = interval(Duration::from_secs(5));
|
let mut ticker = interval(Duration::from_secs(5));
|
||||||
loop {
|
loop {
|
||||||
ticker.tick().await;
|
ticker.tick().await;
|
||||||
daemon_state_hb.update_heartbeat().await.ok();
|
if let Err(e) = daemon_state_hb.update_heartbeat().await {
|
||||||
|
log::warn!("Failed to update heartbeat: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let sigint = tokio::signal::ctrl_c();
|
let sigint = tokio::signal::ctrl_c();
|
||||||
let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())?;
|
let mut sigterm =
|
||||||
|
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())?;
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = sigint => {
|
_ = sigint => {
|
||||||
|
|
@ -461,6 +548,18 @@ async fn load_scanners(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify library before loading
|
||||||
|
if let Err(e) = verify_library(&path) {
|
||||||
|
log::error!("Scanner {:?} failed verification: {}", path, e);
|
||||||
|
logger.log(
|
||||||
|
LogLevel::Error,
|
||||||
|
"loader",
|
||||||
|
"verification_failed",
|
||||||
|
format!("{}: {}", path.display(), e),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
match Library::new(&path) {
|
match Library::new(&path) {
|
||||||
Ok(lib) => {
|
Ok(lib) => {
|
||||||
|
|
@ -476,7 +575,7 @@ async fn load_scanners(
|
||||||
format!("{}: {}", path.display(), e),
|
format!("{}: {}", path.display(), e),
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let scanner = match pscand_core::get_scanner(creator()) {
|
let scanner = match pscand_core::get_scanner(creator()) {
|
||||||
|
|
@ -487,7 +586,7 @@ async fn load_scanners(
|
||||||
path.display()
|
path.display()
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
let name = scanner.name().to_string();
|
let name = scanner.name().to_string();
|
||||||
|
|
||||||
|
|
@ -529,7 +628,7 @@ async fn load_scanners(
|
||||||
interval,
|
interval,
|
||||||
library: lib,
|
library: lib,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Failed to load scanner {:?}: {}", path, e);
|
log::warn!("Failed to load scanner {:?}: {}", path, e);
|
||||||
logger.log(
|
logger.log(
|
||||||
|
|
@ -538,7 +637,7 @@ async fn load_scanners(
|
||||||
"load_failed",
|
"load_failed",
|
||||||
format!("{}: {}", path.display(), e),
|
format!("{}: {}", path.display(), e),
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -561,7 +660,11 @@ async fn list_scanners() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!(" - sensor: hwmon temperature, fan, voltage sensors");
|
println!(" - sensor: hwmon temperature, fan, voltage sensors");
|
||||||
println!(" - power: battery and power supply status");
|
println!(" - power: battery and power supply status");
|
||||||
println!(" - proc: process count and zombie detection");
|
println!(" - proc: process count and zombie detection");
|
||||||
println!("\nDynamic scanners are loaded from $PSCAND_SCANNER_DIRS (colon-separated)");
|
println!(
|
||||||
println!(" Default fallback: ~/.local/share/pscand/scanners/ or ~/.config/pscand/scanners/");
|
"\nDynamic scanners are loaded from $PSCAND_SCANNER_DIRS (colon-separated)"
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
" Default fallback: ~/.local/share/pscand/scanners/ or ~/.config/pscand/scanners/"
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue