Ksud: refactor KPM event handling logic, add error handling and ensure KPM catalog exists

This commit is contained in:
ShirkNeko
2025-04-14 15:26:30 +08:00
parent c2ed3da87c
commit d087ec510e

View File

@@ -3,11 +3,13 @@ use notify::{Watcher, RecursiveMode};
use std::path::Path; use std::path::Path;
use std::fs; use std::fs;
use anyhow::anyhow; use anyhow::anyhow;
use std::ffi::OsStr;
pub const KPM_DIR: &str = "/data/adb/kpm"; pub const KPM_DIR: &str = "/data/adb/kpm";
pub const KPMMGR_PATH: &str = "/data/adb/ksu/bin/kpmmgr"; pub const KPMMGR_PATH: &str = "/data/adb/ksu/bin/kpmmgr";
// 确保 KPM 目录存在,如果不存在则创建
pub fn ensure_kpm_dir() -> Result<()> { pub fn ensure_kpm_dir() -> Result<()> {
if !Path::new(KPM_DIR).exists() { if !Path::new(KPM_DIR).exists() {
fs::create_dir_all(KPM_DIR)?; fs::create_dir_all(KPM_DIR)?;
@@ -39,29 +41,44 @@ pub fn start_kpm_watcher() -> Result<()> {
Ok(()) Ok(())
} }
// 处理 KPM 事件
pub fn handle_kpm_event(event: notify::Event) { pub fn handle_kpm_event(event: notify::Event) {
match event.kind { match event.kind {
notify::EventKind::Create(_) => { notify::EventKind::Create(_) => handle_create_event(event.paths),
event.paths.iter().for_each(|path| { notify::EventKind::Remove(_) => handle_remove_event(event.paths),
if path.extension().is_some_and(|ext| ext == "kpm") { notify::EventKind::Modify(_) => handle_modify_event(event.paths),
let _ = load_kpm(path);
}
});
}
notify::EventKind::Remove(_) => {
event.paths.iter().for_each(|path| {
if let Some(name) = path.file_stem() {
let _ = unload_kpm(name.to_string_lossy().as_ref());
}
});
}
_ => {} _ => {}
} }
} }
fn handle_create_event(paths: Vec<std::path::PathBuf>) {
for path in paths {
if path.extension() == Some(OsStr::new("kpm")) {
if let Err(e) = load_kpm(&path) {
log::warn!("Failed to load {}: {}", path.display(), e);
}
}
}
}
fn handle_remove_event(paths: Vec<std::path::PathBuf>) {
for path in paths {
if let Some(name) = path.file_stem().and_then(|s| s.to_str()) {
if let Err(e) = unload_kpm(name) {
log::warn!("Failed to unload {}: {}", name, e);
}
if let Err(e) = fs::remove_file(&path) {
log::error!("Failed to delete file: {}: {}", path.display(), e);
}
}
}
}
// 加载 KPM 模块
pub fn load_kpm(path: &Path) -> Result<()> { pub fn load_kpm(path: &Path) -> Result<()> {
let path_str = path.to_str().ok_or_else(|| anyhow!("Invalid path: {}", path.display()))?;
let status = std::process::Command::new(KPMMGR_PATH) let status = std::process::Command::new(KPMMGR_PATH)
.args(["load", path.to_str().unwrap(), ""]) .args(["load", path_str, ""])
.status()?; .status()?;
if status.success() { if status.success() {
@@ -70,20 +87,21 @@ pub fn load_kpm(path: &Path) -> Result<()> {
Ok(()) Ok(())
} }
// 卸载 KPM 模块并尝试删除对应文件
pub fn unload_kpm(name: &str) -> Result<()> { pub fn unload_kpm(name: &str) -> Result<()> {
let status = std::process::Command::new(KPMMGR_PATH) let status = std::process::Command::new(KPMMGR_PATH)
.args(["unload", name]) .args(["unload", name])
.status() .status()
.map_err(|e| anyhow!("Failed to execute kpmmgr: {}", e))?; .map_err(|e| anyhow!("Failed to execute kpmmgr: {}", e))?;
let kpm_path = Path::new(KPM_DIR).join(format!("{}.kpm", name));
if kpm_path.exists() {
fs::remove_file(&kpm_path)
.map_err(|e| anyhow!("Failed to delete KPM file: {}", e))
.map(|_| log::info!("Deleted KPM file: {}", kpm_path.display()))?;
}
if status.success() { if status.success() {
let kpm_path = find_kpm_file(name)?;
if let Some(path) = kpm_path {
fs::remove_file(&path)
.map_err(|e| anyhow!("Failed to delete KPM file: {}: {}", path.display(), e))?;
log::info!("Deleted KPM file: {}", path.display());
}
log::info!("Successfully unloaded KPM: {}", name); log::info!("Successfully unloaded KPM: {}", name);
} else { } else {
log::warn!("KPM unloading may have failed: {}", name); log::warn!("KPM unloading may have failed: {}", name);
@@ -92,6 +110,27 @@ pub fn unload_kpm(name: &str) -> Result<()> {
Ok(()) Ok(())
} }
// 通过名称查找 KPM 文件
fn find_kpm_file(name: &str) -> Result<Option<std::path::PathBuf>> {
let kpm_dir = Path::new(KPM_DIR);
if !kpm_dir.exists() {
return Ok(None);
}
for entry in fs::read_dir(kpm_dir)? {
let path = entry?.path();
if let Some(file_name) = path.file_stem() {
if let Some(file_name_str) = file_name.to_str() {
if file_name_str == name && path.extension() == Some(OsStr::new("kpm")) {
return Ok(Some(path));
}
}
}
}
Ok(None)
}
// 安全模式下删除所有 KPM 模块
pub fn remove_all_kpms() -> Result<()> { pub fn remove_all_kpms() -> Result<()> {
ensure_kpm_dir()?; ensure_kpm_dir()?;
@@ -99,23 +138,28 @@ pub fn remove_all_kpms() -> Result<()> {
let path = entry?.path(); let path = entry?.path();
if path.extension().is_some_and(|ext| ext == "kpm") { if path.extension().is_some_and(|ext| ext == "kpm") {
if let Some(name) = path.file_stem() { if let Some(name) = path.file_stem() {
unload_kpm(name.to_string_lossy().as_ref()) if let Err(e) = unload_kpm(name.to_string_lossy().as_ref()) {
.unwrap_or_else(|e| log::error!("Failed to remove KPM: {}", e)); log::error!("Failed to remove KPM: {}", e);
let _ = fs::remove_file(&path); }
if let Err(e) = fs::remove_file(&path) {
log::error!("Failed to delete file: {}: {}", path.display(), e);
}
} }
} }
} }
Ok(()) Ok(())
} }
// 加载所有现有的 KPM 模块 // 系统启动后加载所有现有的 KPM 模块
pub fn load_existing_kpms() -> Result<()> { pub fn load_existing_kpms() -> Result<()> {
ensure_kpm_dir()?; ensure_kpm_dir()?;
for entry in fs::read_dir(KPM_DIR)? { for entry in fs::read_dir(KPM_DIR)? {
let path = entry?.path(); let path = entry?.path();
if path.extension().map_or(false, |ext| ext == "kpm") { if path.extension().map_or(false, |ext| ext == "kpm") {
let _ = load_kpm(&path); if let Err(e) = load_kpm(&path) {
log::warn!("Failed to load {}: {}", path.display(), e);
}
} }
} }
Ok(()) Ok(())