manager: Simplify kpm management by migrating to the ksud side.
This commit is contained in:
@@ -122,6 +122,14 @@ enum Commands {
|
||||
#[command(subcommand)]
|
||||
command: BootInfo,
|
||||
},
|
||||
|
||||
/// KPM module manager
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
Kpm {
|
||||
#[command(subcommand)]
|
||||
command: kpm_cmd::Kpm,
|
||||
},
|
||||
|
||||
/// For developers
|
||||
Debug {
|
||||
#[command(subcommand)]
|
||||
@@ -272,6 +280,33 @@ enum Profile {
|
||||
ListTemplates,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mod kpm_cmd {
|
||||
use clap::Subcommand;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Kpm {
|
||||
/// Load a KPM module: load <path> [args]
|
||||
Load {
|
||||
path: PathBuf,
|
||||
args: Option<String>,
|
||||
},
|
||||
/// Unload a KPM module: unload <name>
|
||||
Unload { name: String },
|
||||
/// Get number of loaded modules
|
||||
Num,
|
||||
/// List loaded KPM modules
|
||||
List,
|
||||
/// Get info of a KPM module: info <name>
|
||||
Info { name: String },
|
||||
/// Send control command to a KPM module: control <name> <args>
|
||||
Control { name: String, args: String },
|
||||
/// Print KPM Loader version
|
||||
Version,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run() -> Result<()> {
|
||||
#[cfg(target_os = "android")]
|
||||
android_logger::init_once(
|
||||
@@ -381,6 +416,23 @@ pub fn run() -> Result<()> {
|
||||
magiskboot,
|
||||
flash,
|
||||
} => crate::boot_patch::restore(boot, magiskboot, flash),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
Commands::Kpm { command } => {
|
||||
use crate::cli::kpm_cmd::Kpm;
|
||||
match command {
|
||||
Kpm::Load { path, args } => crate::kpm::kpm_load(path.to_str().unwrap(), args.as_deref()),
|
||||
Kpm::Unload { name } => crate::kpm::kpm_unload(&name),
|
||||
Kpm::Num => crate::kpm::kpm_num().map(|_| ()),
|
||||
Kpm::List => crate::kpm::kpm_list(),
|
||||
Kpm::Info { name } => crate::kpm::kpm_info(&name),
|
||||
Kpm::Control { name, args } => {
|
||||
let ret = crate::kpm::kpm_control(&name, &args)?;
|
||||
println!("{}", ret);
|
||||
Ok(())
|
||||
}
|
||||
Kpm::Version => crate::kpm::kpm_version_loader(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = &result {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::defs::{KSU_MOUNT_SOURCE, NO_MOUNT_PATH, NO_TMPFS_PATH};
|
||||
use crate::module::{handle_updated_modules, prune_modules};
|
||||
use crate::{assets, defs, ksucalls, restorecon, utils, kpm, uid_scanner};
|
||||
use crate::{assets, defs, ksucalls, restorecon, utils, uid_scanner};
|
||||
use anyhow::{Context, Result};
|
||||
use log::{info, warn};
|
||||
use rustix::fs::{MountFlags, mount};
|
||||
use std::path::Path;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::kpm;
|
||||
|
||||
pub fn on_post_data_fs() -> Result<()> {
|
||||
ksucalls::report_post_fs_data();
|
||||
@@ -70,10 +72,12 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
warn!("apply root profile sepolicy failed: {e}");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
if let Err(e) = kpm::start_kpm_watcher() {
|
||||
warn!("KPM: Failed to start KPM watcher: {}", e);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
if let Err(e) = kpm::load_kpm_modules() {
|
||||
warn!("KPM: Failed to load KPM modules: {}", e);
|
||||
}
|
||||
|
||||
@@ -1,242 +1,236 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use libc::{prctl, c_char, c_void, c_int};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use libc::{c_char, c_int, c_void, prctl};
|
||||
use notify::{RecursiveMode, Watcher};
|
||||
use std::ffi::{CStr, CString, OsStr};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr;
|
||||
|
||||
pub const KPM_DIR: &str = "/data/adb/kpm";
|
||||
|
||||
const KSU_OPTIONS: u32 = 0xdeadbeef;
|
||||
const SUKISU_KPM_LOAD: i32 = 28;
|
||||
const SUKISU_KPM_LOAD: i32 = 28;
|
||||
const SUKISU_KPM_UNLOAD: i32 = 29;
|
||||
const SUKISU_KPM_VERSION: i32 = 34;
|
||||
const SUKISU_KPM_NUM: i32 = 30;
|
||||
const SUKISU_KPM_LIST: i32 = 31;
|
||||
const SUKISU_KPM_INFO: i32 = 32;
|
||||
const SUKISU_KPM_CONTROL:i32 = 33;
|
||||
const SUKISU_KPM_VERSION:i32 = 34;
|
||||
|
||||
pub fn check_kpm_version() -> Result<String> {
|
||||
let mut buffer: [u8; 1024] = [0; 1024];
|
||||
#[inline(always)]
|
||||
unsafe fn kpm_prctl(
|
||||
cmd: i32,
|
||||
arg1: *const c_void,
|
||||
arg2: *const c_void,
|
||||
) -> Result<i32> {
|
||||
let mut out: c_int = -1;
|
||||
|
||||
let _ret = unsafe {
|
||||
let ret = unsafe {
|
||||
prctl(
|
||||
KSU_OPTIONS as c_int,
|
||||
SUKISU_KPM_VERSION,
|
||||
buffer.as_mut_ptr() as *mut c_void,
|
||||
buffer.len() as *mut c_void,
|
||||
cmd as c_int,
|
||||
arg1,
|
||||
arg2,
|
||||
&mut out as *mut c_int as *mut c_void,
|
||||
)
|
||||
};
|
||||
|
||||
if out < 0 {
|
||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
||||
if ret != 0 || out < 0 {
|
||||
bail!("KPM prctl error: {}", std::io::Error::from_raw_os_error(-out));
|
||||
}
|
||||
|
||||
let version_str = unsafe {
|
||||
CStr::from_ptr(buffer.as_ptr() as *const c_char)
|
||||
}.to_string_lossy().to_string();
|
||||
|
||||
log::info!("KPM: Version check result: {}", version_str);
|
||||
|
||||
// 检查版本是否有效(不为空且不以Error开头)
|
||||
if version_str.is_empty() || version_str.starts_with("Error") {
|
||||
return Err(anyhow!("KPM: Invalid version response: {}", version_str));
|
||||
}
|
||||
|
||||
Ok(version_str)
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn str_to_cstr<R, F: FnOnce(*const c_char) -> R>(s: &str, f: F) -> Result<R> {
|
||||
let cs = CString::new(s)?;
|
||||
Ok(f(cs.as_ptr()))
|
||||
}
|
||||
|
||||
fn cbuf_to_string(buf: &[u8]) -> String {
|
||||
unsafe { CStr::from_ptr(buf.as_ptr() as *const c_char) }
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
pub fn kpm_load(path: &str, args: Option<&str>) -> Result<()> {
|
||||
str_to_cstr(path, |p_path| {
|
||||
let _args_cstring;
|
||||
let p_args = match args {
|
||||
Some(a) => {
|
||||
_args_cstring = CString::new(a)?;
|
||||
_args_cstring.as_ptr()
|
||||
}
|
||||
None => ptr::null(),
|
||||
};
|
||||
unsafe { kpm_prctl(SUKISU_KPM_LOAD, p_path as _, p_args as _) }?;
|
||||
println!("Success");
|
||||
Ok(())
|
||||
})?
|
||||
}
|
||||
|
||||
pub fn kpm_unload(name: &str) -> Result<()> {
|
||||
let _ = str_to_cstr(name, |p| unsafe {
|
||||
kpm_prctl(SUKISU_KPM_UNLOAD, p as _, ptr::null())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn kpm_num() -> Result<i32> {
|
||||
let n = unsafe { kpm_prctl(SUKISU_KPM_NUM, ptr::null(), ptr::null())? };
|
||||
println!("{}", n);
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
pub fn kpm_list() -> Result<()> {
|
||||
let mut buf = vec![0u8; 1024];
|
||||
unsafe {
|
||||
kpm_prctl(
|
||||
SUKISU_KPM_LIST,
|
||||
buf.as_mut_ptr() as _,
|
||||
buf.len() as *const c_void,
|
||||
)?;
|
||||
}
|
||||
print!("{}", cbuf_to_string(&buf));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn kpm_info(name: &str) -> Result<()> {
|
||||
let mut buf = vec![0u8; 256];
|
||||
let _ = str_to_cstr(name, |p| unsafe {
|
||||
kpm_prctl(SUKISU_KPM_INFO, p as _, buf.as_mut_ptr() as _)
|
||||
})?;
|
||||
println!("{}", cbuf_to_string(&buf));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn kpm_control(name: &str, args: &str) -> Result<i32> {
|
||||
str_to_cstr(name, |p_name| {
|
||||
str_to_cstr(args, |p_args| unsafe {
|
||||
kpm_prctl(SUKISU_KPM_CONTROL, p_name as _, p_args as _)
|
||||
})?
|
||||
})?
|
||||
}
|
||||
|
||||
pub fn kpm_version_loader() -> Result<()> {
|
||||
let mut buf = vec![0u8; 1024];
|
||||
unsafe {
|
||||
kpm_prctl(
|
||||
SUKISU_KPM_VERSION,
|
||||
buf.as_mut_ptr() as _,
|
||||
buf.len() as *const c_void,
|
||||
)?;
|
||||
}
|
||||
print!("{}", cbuf_to_string(&buf));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_kpm_version() -> Result<String> {
|
||||
let mut buf = vec![0u8; 1024];
|
||||
unsafe {
|
||||
kpm_prctl(
|
||||
SUKISU_KPM_VERSION,
|
||||
buf.as_mut_ptr() as _,
|
||||
buf.len() as *const c_void,
|
||||
)?;
|
||||
}
|
||||
let ver = cbuf_to_string(&buf);
|
||||
if ver.is_empty() || ver.starts_with("Error") {
|
||||
bail!("KPM: Invalid version response: {}", ver);
|
||||
}
|
||||
log::info!("KPM: Version check result: {}", ver);
|
||||
Ok(ver)
|
||||
}
|
||||
|
||||
// 确保 KPM 目录存在,并设置777权限
|
||||
pub fn ensure_kpm_dir() -> Result<()> {
|
||||
let path = Path::new(KPM_DIR);
|
||||
|
||||
if path.exists() {
|
||||
let meta = fs::metadata(path)?;
|
||||
let current = meta.permissions().mode() & 0o777;
|
||||
if current != 0o777 {
|
||||
log::info!("KPM: Fixing permissions to 777 for {}", KPM_DIR);
|
||||
fs::set_permissions(path, fs::Permissions::from_mode(0o777))?;
|
||||
}
|
||||
if !path.exists() {
|
||||
fs::create_dir_all(path)?;
|
||||
}
|
||||
let meta = fs::metadata(path)?;
|
||||
if meta.permissions().mode() & 0o777 != 0o777 {
|
||||
fs::set_permissions(path, fs::Permissions::from_mode(0o777))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_kpm_watcher() -> Result<()> {
|
||||
match check_kpm_version() {
|
||||
Ok(version) => {
|
||||
log::info!("KPM: Version check passed, version: {}", version);
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("KPM: Version check failed, skipping KPM functionality: {}", e);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
check_kpm_version()?;
|
||||
ensure_kpm_dir()?;
|
||||
|
||||
// 检查是否处于安全模式
|
||||
if crate::utils::is_safe_mode() {
|
||||
log::warn!("KPM: System is in safe mode, removing all KPM modules");
|
||||
if let Err(e) = remove_all_kpms() {
|
||||
log::error!("KPM: Error removing all KPM modules: {}", e);
|
||||
}
|
||||
log::warn!("KPM: Safe mode – removing all KPM modules");
|
||||
remove_all_kpms()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut watcher = notify::recommended_watcher(|res| match res {
|
||||
Ok(event) => handle_kpm_event(event),
|
||||
Err(e) => log::error!("KPM: File monitoring error: {:?}", e),
|
||||
Err(e) => log::error!("KPM: File monitor error: {:?}", e),
|
||||
})?;
|
||||
|
||||
watcher.watch(Path::new(KPM_DIR), RecursiveMode::NonRecursive)?;
|
||||
log::info!("KPM: Started file watcher for directory: {}", KPM_DIR);
|
||||
log::info!("KPM: File watcher started on {}", KPM_DIR);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 处理 KPM 事件
|
||||
pub fn handle_kpm_event(event: notify::Event) {
|
||||
fn handle_kpm_event(event: notify::Event) {
|
||||
match event.kind {
|
||||
notify::EventKind::Create(_) => handle_create_event(event.paths),
|
||||
notify::EventKind::Remove(_) => handle_remove_event(event.paths),
|
||||
notify::EventKind::Modify(_) => handle_modify_event(event.paths),
|
||||
notify::EventKind::Create(_) => {
|
||||
for p in event.paths {
|
||||
if p.extension() == Some(OsStr::new("kpm")) {
|
||||
if let Err(e) = load_kpm(&p) {
|
||||
log::warn!("KPM: Failed to load {}: {}", p.display(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
notify::EventKind::Modify(_) => {
|
||||
for p in event.paths {
|
||||
log::info!("KPM: Modified file: {}", p.display());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_create_event(paths: Vec<std::path::PathBuf>) {
|
||||
for path in paths {
|
||||
if path.extension() == Some(OsStr::new("kpm")) {
|
||||
log::info!("KPM: Detected new KPM file: {}", path.display());
|
||||
if let Err(e) = load_kpm(&path) {
|
||||
log::warn!("KPM: 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()) {
|
||||
log::info!("KPM: Detected KPM file removal: {}", name);
|
||||
if let Err(e) = unload_kpm(name) {
|
||||
log::warn!("KPM: Failed to unload {}: {}", name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_modify_event(paths: Vec<std::path::PathBuf>) {
|
||||
for path in paths {
|
||||
log::info!("KPM: Modified file detected: {}", path.display());
|
||||
}
|
||||
}
|
||||
|
||||
// 加载 KPM 模块
|
||||
pub fn load_kpm(path: &Path) -> Result<()> {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("KPM: Invalid path: {}", path.display()))?;
|
||||
|
||||
let path_cstring = CString::new(path_str)
|
||||
.map_err(|e| anyhow!("KPM: Failed to convert path to CString: {}", e))?;
|
||||
|
||||
let mut out: c_int = -1;
|
||||
|
||||
let _ret = unsafe {
|
||||
prctl(
|
||||
KSU_OPTIONS as c_int,
|
||||
SUKISU_KPM_LOAD,
|
||||
path_cstring.as_ptr() as *mut c_void,
|
||||
ptr::null_mut::<c_void>(),
|
||||
&mut out as *mut c_int as *mut c_void,
|
||||
)
|
||||
};
|
||||
|
||||
if out < 0 {
|
||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
||||
}
|
||||
|
||||
if out > 0 {
|
||||
log::info!("KPM: Successfully loaded module: {}", path.display());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
let path_str = path.to_str().ok_or_else(|| anyhow!("Invalid path"))?;
|
||||
kpm_load(path_str, None)
|
||||
}
|
||||
|
||||
// 卸载 KPM 模块
|
||||
pub fn unload_kpm(name: &str) -> Result<()> {
|
||||
let name_cstring = CString::new(name)
|
||||
.map_err(|e| anyhow!("KPM: Failed to convert name to CString: {}", e))?;
|
||||
|
||||
let mut out: c_int = -1;
|
||||
|
||||
let _ret = unsafe {
|
||||
prctl(
|
||||
KSU_OPTIONS as c_int,
|
||||
SUKISU_KPM_UNLOAD,
|
||||
name_cstring.as_ptr() as *mut c_void,
|
||||
ptr::null_mut::<c_void>(),
|
||||
&mut out as *mut c_int as *mut c_void,
|
||||
)
|
||||
};
|
||||
|
||||
if out < 0 {
|
||||
log::warn!("KPM: prctl returned error for unload: {}", out);
|
||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
||||
kpm_unload(name)?;
|
||||
if let Some(p) = find_kpm_file(name)? {
|
||||
fs::remove_file(&p).ok();
|
||||
log::info!("KPM: Deleted file {}", p.display());
|
||||
}
|
||||
|
||||
// 尝试删除对应的KPM文件
|
||||
if let Ok(Some(path)) = find_kpm_file(name) {
|
||||
if let Err(e) = fs::remove_file(&path) {
|
||||
log::warn!("KPM: Failed to delete KPM file {}: {}", path.display(), e);
|
||||
} else {
|
||||
log::info!("KPM: Deleted KPM file: {}", path.display());
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("KPM: Successfully unloaded module: {}", name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 通过名称查找 KPM 文件
|
||||
fn find_kpm_file(name: &str) -> Result<Option<std::path::PathBuf>> {
|
||||
let kpm_dir = Path::new(KPM_DIR);
|
||||
if !kpm_dir.exists() {
|
||||
fn find_kpm_file(name: &str) -> Result<Option<PathBuf>> {
|
||||
let dir = Path::new(KPM_DIR);
|
||||
if !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));
|
||||
}
|
||||
}
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let p = entry?.path();
|
||||
if p.extension() == Some(OsStr::new("kpm"))
|
||||
&& p.file_stem().map_or(false, |s| s == name)
|
||||
{
|
||||
return Ok(Some(p));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
// 安全模式下删除所有 KPM 模块
|
||||
pub fn remove_all_kpms() -> Result<()> {
|
||||
let kpm_dir = Path::new(KPM_DIR);
|
||||
if !kpm_dir.exists() {
|
||||
log::info!("KPM: KPM directory does not exist, nothing to remove");
|
||||
let dir = Path::new(KPM_DIR);
|
||||
if !dir.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(KPM_DIR)? {
|
||||
let path = entry?.path();
|
||||
if path.extension().is_some_and(|ext| ext == "kpm") {
|
||||
if let Some(name) = path.file_stem() {
|
||||
let name_str = name.to_string_lossy();
|
||||
log::info!("KPM: Removing module in safe mode: {}", name_str);
|
||||
if let Err(e) = unload_kpm(&name_str) {
|
||||
log::error!("KPM: Failed to remove module {}: {}", name_str, e);
|
||||
}
|
||||
if let Err(e) = fs::remove_file(&path) {
|
||||
log::error!("KPM: Failed to delete file {}: {}", path.display(), e);
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let p = entry?.path();
|
||||
if p.extension() == Some(OsStr::new("kpm")) {
|
||||
if let Some(name) = p.file_stem().and_then(|s| s.to_str()) {
|
||||
if let Err(e) = unload_kpm(name) {
|
||||
log::error!("KPM: Failed to unload {}: {}", name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,53 +238,26 @@ pub fn remove_all_kpms() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 加载所有 KPM 模块
|
||||
pub fn load_kpm_modules() -> Result<()> {
|
||||
match check_kpm_version() {
|
||||
Ok(version) => {
|
||||
log::info!("KPM: Version check passed before loading modules, version: {}", version);
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("KPM: Version check failed, skipping module loading: {}", e);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
check_kpm_version()?;
|
||||
ensure_kpm_dir()?;
|
||||
|
||||
let kpm_dir = Path::new(KPM_DIR);
|
||||
if !kpm_dir.exists() {
|
||||
log::info!("KPM: KPM directory does not exist, no modules to load");
|
||||
let dir = Path::new(KPM_DIR);
|
||||
if !dir.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut loaded_count = 0;
|
||||
let mut failed_count = 0;
|
||||
|
||||
for entry in std::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.is_empty() {
|
||||
log::warn!("KPM: Invalid KPM file name: {}", path.display());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if path.extension().is_some_and(|ext| ext == "kpm") {
|
||||
match load_kpm(&path) {
|
||||
Ok(()) => {
|
||||
log::info!("KPM: Successfully loaded module: {}", path.display());
|
||||
loaded_count += 1;
|
||||
}
|
||||
let (mut ok, mut ng) = (0, 0);
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let p = entry?.path();
|
||||
if p.extension() == Some(OsStr::new("kpm")) {
|
||||
match load_kpm(&p) {
|
||||
Ok(_) => ok += 1,
|
||||
Err(e) => {
|
||||
log::warn!("KPM: Failed to load module {}: {}", path.display(), e);
|
||||
failed_count += 1;
|
||||
log::warn!("KPM: Failed to load {}: {}", p.display(), e);
|
||||
ng += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("KPM: Module loading completed - loaded: {}, failed: {}", loaded_count, failed_count);
|
||||
log::info!("KPM: Load done – ok: {}, failed: {}", ok, ng);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ mod cli;
|
||||
mod debug;
|
||||
mod defs;
|
||||
mod init_event;
|
||||
mod kpm;
|
||||
mod ksucalls;
|
||||
#[cfg(target_os = "android")]
|
||||
mod magic_mount;
|
||||
@@ -16,6 +15,8 @@ mod sepolicy;
|
||||
mod su;
|
||||
mod utils;
|
||||
mod uid_scanner;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mod kpm;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
cli::run()
|
||||
|
||||
Reference in New Issue
Block a user