* Revert "chore(ksud): bump ksud's deps (#585)"
* Because it may cause compilation errors.
This reverts commit c8020b2066.
* chore(ksud): remove unused Result
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
* chore(ksud): enable clippy::all, clippy::pedantic && make clippy happy
https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or
https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items
https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
...
and use some #![allow(...)] or #[allow(...)]
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
---------
Signed-off-by: Tools-app <localhost.hutao@gmail.com>
784 lines
23 KiB
Rust
784 lines
23 KiB
Rust
use anyhow::{Ok, Result};
|
|
use clap::Parser;
|
|
use std::path::PathBuf;
|
|
|
|
#[cfg(target_os = "android")]
|
|
use android_logger::Config;
|
|
#[cfg(target_os = "android")]
|
|
use log::LevelFilter;
|
|
|
|
use crate::{apk_sign, assets, debug, defs, init_event, ksucalls, module, module_config, utils};
|
|
|
|
/// KernelSU userspace cli
|
|
#[derive(Parser, Debug)]
|
|
#[command(author, version = defs::VERSION_NAME, about, long_about = None)]
|
|
struct Args {
|
|
#[command(subcommand)]
|
|
command: Commands,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Commands {
|
|
/// Manage KernelSU modules
|
|
Module {
|
|
#[command(subcommand)]
|
|
command: Module,
|
|
},
|
|
|
|
/// Trigger `post-fs-data` event
|
|
PostFsData,
|
|
|
|
/// Trigger `service` event
|
|
Services,
|
|
|
|
/// Trigger `boot-complete` event
|
|
BootCompleted,
|
|
|
|
/// Install KernelSU userspace component to system
|
|
Install {
|
|
#[arg(long, default_value = None)]
|
|
magiskboot: Option<PathBuf>,
|
|
},
|
|
|
|
/// Uninstall KernelSU modules and itself(LKM Only)
|
|
Uninstall {
|
|
/// magiskboot path, if not specified, will search from $PATH
|
|
#[arg(long, default_value = None)]
|
|
magiskboot: Option<PathBuf>,
|
|
},
|
|
|
|
/// SELinux policy Patch tool
|
|
Sepolicy {
|
|
#[command(subcommand)]
|
|
command: Sepolicy,
|
|
},
|
|
|
|
/// Manage App Profiles
|
|
Profile {
|
|
#[command(subcommand)]
|
|
command: Profile,
|
|
},
|
|
|
|
/// Manage kernel features
|
|
Feature {
|
|
#[command(subcommand)]
|
|
command: Feature,
|
|
},
|
|
|
|
/// Patch boot or init_boot images to apply KernelSU
|
|
BootPatch {
|
|
/// boot image path, if not specified, will try to find the boot image automatically
|
|
#[arg(short, long)]
|
|
boot: Option<PathBuf>,
|
|
|
|
/// kernel image path to replace
|
|
#[arg(short, long)]
|
|
kernel: Option<PathBuf>,
|
|
|
|
/// LKM module path to replace, if not specified, will use the builtin one
|
|
#[arg(short, long)]
|
|
module: Option<PathBuf>,
|
|
|
|
/// init to be replaced
|
|
#[arg(short, long, requires("module"))]
|
|
init: Option<PathBuf>,
|
|
|
|
/// will use another slot when boot image is not specified
|
|
#[arg(short = 'u', long, default_value = "false")]
|
|
ota: bool,
|
|
|
|
/// Flash it to boot partition after patch
|
|
#[arg(short, long, default_value = "false")]
|
|
flash: bool,
|
|
|
|
/// output path, if not specified, will use current directory
|
|
#[arg(short, long, default_value = None)]
|
|
out: Option<PathBuf>,
|
|
|
|
/// magiskboot path, if not specified, will search from $PATH
|
|
#[arg(long, default_value = None)]
|
|
magiskboot: Option<PathBuf>,
|
|
|
|
/// KMI version, if specified, will use the specified KMI
|
|
#[arg(long, default_value = None)]
|
|
kmi: Option<String>,
|
|
|
|
/// target partition override (init_boot | boot | vendor_boot)
|
|
#[arg(long, default_value = None)]
|
|
partition: Option<String>,
|
|
},
|
|
|
|
/// Restore boot or init_boot images patched by KernelSU
|
|
BootRestore {
|
|
/// boot image path, if not specified, will try to find the boot image automatically
|
|
#[arg(short, long)]
|
|
boot: Option<PathBuf>,
|
|
|
|
/// Flash it to boot partition after patch
|
|
#[arg(short, long, default_value = "false")]
|
|
flash: bool,
|
|
|
|
/// magiskboot path, if not specified, will search from $PATH
|
|
#[arg(long, default_value = None)]
|
|
magiskboot: Option<PathBuf>,
|
|
},
|
|
|
|
/// Show boot information
|
|
BootInfo {
|
|
#[command(subcommand)]
|
|
command: BootInfo,
|
|
},
|
|
|
|
/// KPM module manager
|
|
#[cfg(target_arch = "aarch64")]
|
|
Kpm {
|
|
#[command(subcommand)]
|
|
command: kpm_cmd::Kpm,
|
|
},
|
|
|
|
/// Manage kernel umount paths
|
|
Umount {
|
|
#[command(subcommand)]
|
|
command: Umount,
|
|
},
|
|
|
|
/// For developers
|
|
Debug {
|
|
#[command(subcommand)]
|
|
command: Debug,
|
|
},
|
|
/// Kernel interface
|
|
Kernel {
|
|
#[command(subcommand)]
|
|
command: Kernel,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum BootInfo {
|
|
/// show current kmi version
|
|
CurrentKmi,
|
|
|
|
/// show supported kmi versions
|
|
SupportedKmis,
|
|
|
|
/// check if device is A/B capable
|
|
IsAbDevice,
|
|
|
|
/// show auto-selected boot partition name
|
|
DefaultPartition,
|
|
|
|
/// list available partitions for current or OTA toggled slot
|
|
AvailablePartitions,
|
|
|
|
/// show slot suffix for current or OTA toggled slot
|
|
SlotSuffix {
|
|
/// toggle to another slot
|
|
#[arg(short = 'u', long, default_value = "false")]
|
|
ota: bool,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Debug {
|
|
/// Set the manager app, kernel CONFIG_KSU_DEBUG should be enabled.
|
|
SetManager {
|
|
/// manager package name
|
|
#[arg(default_value_t = String::from("com.sukisu.ultra"))]
|
|
apk: String,
|
|
},
|
|
|
|
/// Get apk size and hash
|
|
GetSign {
|
|
/// apk path
|
|
apk: String,
|
|
},
|
|
|
|
/// Root Shell
|
|
Su {
|
|
/// switch to gloabl mount namespace
|
|
#[arg(short, long, default_value = "false")]
|
|
global_mnt: bool,
|
|
},
|
|
|
|
/// Get kernel version
|
|
Version,
|
|
|
|
/// For testing
|
|
Test,
|
|
|
|
/// Process mark management
|
|
Mark {
|
|
#[command(subcommand)]
|
|
command: MarkCommand,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum MarkCommand {
|
|
/// Get mark status for a process (or all)
|
|
Get {
|
|
/// target pid (0 for total count)
|
|
#[arg(default_value = "0")]
|
|
pid: i32,
|
|
},
|
|
|
|
/// Mark a process
|
|
Mark {
|
|
/// target pid (0 for all processes)
|
|
#[arg(default_value = "0")]
|
|
pid: i32,
|
|
},
|
|
|
|
/// Unmark a process
|
|
Unmark {
|
|
/// target pid (0 for all processes)
|
|
#[arg(default_value = "0")]
|
|
pid: i32,
|
|
},
|
|
|
|
/// Refresh mark for all running processes
|
|
Refresh,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Sepolicy {
|
|
/// Patch sepolicy
|
|
Patch {
|
|
/// sepolicy statements
|
|
sepolicy: String,
|
|
},
|
|
|
|
/// Apply sepolicy from file
|
|
Apply {
|
|
/// sepolicy file path
|
|
file: String,
|
|
},
|
|
|
|
/// Check if sepolicy statement is supported/valid
|
|
Check {
|
|
/// sepolicy statements
|
|
sepolicy: String,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Module {
|
|
/// Install module <ZIP>
|
|
Install {
|
|
/// module zip file path
|
|
zip: String,
|
|
},
|
|
|
|
/// Undo module uninstall mark <id>
|
|
UndoUninstall {
|
|
/// module id
|
|
id: String,
|
|
},
|
|
|
|
/// Uninstall module <id>
|
|
Uninstall {
|
|
/// module id
|
|
id: String,
|
|
},
|
|
|
|
/// enable module <id>
|
|
Enable {
|
|
/// module id
|
|
id: String,
|
|
},
|
|
|
|
/// disable module <id>
|
|
Disable {
|
|
// module id
|
|
id: String,
|
|
},
|
|
|
|
/// run action for module <id>
|
|
Action {
|
|
// module id
|
|
id: String,
|
|
},
|
|
|
|
/// list all modules
|
|
List,
|
|
|
|
/// manage module configuration
|
|
Config {
|
|
#[command(subcommand)]
|
|
command: ModuleConfigCmd,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum ModuleConfigCmd {
|
|
/// Get a config value
|
|
Get {
|
|
/// config key
|
|
key: String,
|
|
},
|
|
|
|
/// Set a config value
|
|
Set {
|
|
/// config key
|
|
key: String,
|
|
/// config value
|
|
value: String,
|
|
/// use temporary config (cleared on reboot)
|
|
#[arg(short, long)]
|
|
temp: bool,
|
|
},
|
|
|
|
/// List all config entries
|
|
List,
|
|
|
|
/// Delete a config entry
|
|
Delete {
|
|
/// config key
|
|
key: String,
|
|
/// delete from temporary config
|
|
#[arg(short, long)]
|
|
temp: bool,
|
|
},
|
|
|
|
/// Clear all config entries
|
|
Clear {
|
|
/// clear temporary config
|
|
#[arg(short, long)]
|
|
temp: bool,
|
|
},
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Profile {
|
|
/// get root profile's selinux policy of <package-name>
|
|
GetSepolicy {
|
|
/// package name
|
|
package: String,
|
|
},
|
|
|
|
/// set root profile's selinux policy of <package-name> to <profile>
|
|
SetSepolicy {
|
|
/// package name
|
|
package: String,
|
|
/// policy statements
|
|
policy: String,
|
|
},
|
|
|
|
/// get template of <id>
|
|
GetTemplate {
|
|
/// template id
|
|
id: String,
|
|
},
|
|
|
|
/// set template of <id> to <template string>
|
|
SetTemplate {
|
|
/// template id
|
|
id: String,
|
|
/// template string
|
|
template: String,
|
|
},
|
|
|
|
/// delete template of <id>
|
|
DeleteTemplate {
|
|
/// template id
|
|
id: String,
|
|
},
|
|
|
|
/// list all templates
|
|
ListTemplates,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Feature {
|
|
/// Get feature value and support status
|
|
Get {
|
|
/// Feature ID or name (su_compat, kernel_umount)
|
|
id: String,
|
|
},
|
|
|
|
/// Set feature value
|
|
Set {
|
|
/// Feature ID or name
|
|
id: String,
|
|
/// Feature value (0=disable, 1=enable)
|
|
value: u64,
|
|
},
|
|
|
|
/// List all available features
|
|
List,
|
|
|
|
/// Check feature status (supported/unsupported/managed)
|
|
Check {
|
|
/// Feature ID or name (su_compat, kernel_umount)
|
|
id: String,
|
|
},
|
|
|
|
/// Load configuration from file and apply to kernel
|
|
Load,
|
|
|
|
/// Save current kernel feature states to file
|
|
Save,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Kernel {
|
|
/// Nuke ext4 sysfs
|
|
NukeExt4Sysfs {
|
|
/// mount point
|
|
mnt: String,
|
|
},
|
|
/// Manage umount list
|
|
Umount {
|
|
#[command(subcommand)]
|
|
command: UmountOp,
|
|
},
|
|
/// Notify that module is mounted
|
|
NotifyModuleMounted,
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum UmountOp {
|
|
/// Add mount point to umount list
|
|
Add {
|
|
/// mount point path
|
|
mnt: String,
|
|
/// umount flags (default: 0, MNT_DETACH: 2)
|
|
#[arg(short, long, default_value = "0")]
|
|
flags: u32,
|
|
},
|
|
/// Delete mount point from umount list
|
|
Del {
|
|
/// mount point path
|
|
mnt: String,
|
|
},
|
|
/// Wipe all entries from umount list
|
|
Wipe,
|
|
}
|
|
|
|
#[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,
|
|
}
|
|
}
|
|
|
|
#[derive(clap::Subcommand, Debug)]
|
|
enum Umount {
|
|
/// Add custom umount path
|
|
Add {
|
|
/// Mount path to add
|
|
path: String,
|
|
|
|
/// Check mount type (overlay)
|
|
#[arg(long, default_value = "false")]
|
|
|
|
/// Umount flags (0 or 8 for MNT_DETACH)
|
|
#[arg(long, default_value = "-1")]
|
|
flags: i32,
|
|
},
|
|
|
|
/// Remove custom umount path
|
|
Remove {
|
|
/// Mount path to remove
|
|
path: String,
|
|
},
|
|
|
|
/// List all umount paths
|
|
List,
|
|
|
|
/// Clear all recorded umount paths
|
|
ClearCustom,
|
|
|
|
/// Save configuration to file
|
|
Save,
|
|
|
|
/// Load and apply configuration from file
|
|
Load,
|
|
|
|
/// Apply current configuration to kernel
|
|
Apply,
|
|
}
|
|
|
|
pub fn run() -> Result<()> {
|
|
#[cfg(target_os = "android")]
|
|
android_logger::init_once(
|
|
Config::default()
|
|
.with_max_level(LevelFilter::Trace) // limit log level
|
|
.with_tag("KernelSU"), // logs will show under mytag tag
|
|
);
|
|
|
|
#[cfg(not(target_os = "android"))]
|
|
env_logger::init();
|
|
|
|
// the kernel executes su with argv[0] = "su" and replace it with us
|
|
let arg0 = std::env::args().next().unwrap_or_default();
|
|
if arg0 == "su" || arg0 == "/system/bin/su" {
|
|
return crate::su::root_shell();
|
|
}
|
|
|
|
let cli = Args::parse();
|
|
|
|
log::info!("command: {:?}", cli.command);
|
|
|
|
let result = match cli.command {
|
|
Commands::PostFsData => init_event::on_post_data_fs(),
|
|
Commands::BootCompleted => {
|
|
init_event::on_boot_completed();
|
|
Ok(())
|
|
}
|
|
|
|
Commands::Module { command } => {
|
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
|
{
|
|
utils::switch_mnt_ns(1)?;
|
|
}
|
|
match command {
|
|
Module::Install { zip } => module::install_module(&zip),
|
|
Module::UndoUninstall { id } => module::undo_uninstall_module(&id),
|
|
Module::Uninstall { id } => module::uninstall_module(&id),
|
|
Module::Enable { id } => module::enable_module(&id),
|
|
Module::Disable { id } => module::disable_module(&id),
|
|
Module::Action { id } => module::run_action(&id),
|
|
Module::List => module::list_modules(),
|
|
Module::Config { command } => {
|
|
// Get module ID from environment variable
|
|
let module_id = std::env::var("KSU_MODULE").map_err(|_| {
|
|
anyhow::anyhow!("This command must be run in the context of a module")
|
|
})?;
|
|
|
|
match command {
|
|
ModuleConfigCmd::Get { key } => {
|
|
// Use merge_configs to respect priority (temp overrides persist)
|
|
let config = module_config::merge_configs(&module_id)?;
|
|
match config.get(&key) {
|
|
Some(value) => {
|
|
println!("{value}");
|
|
Ok(())
|
|
}
|
|
None => anyhow::bail!("Key '{key}' not found"),
|
|
}
|
|
}
|
|
ModuleConfigCmd::Set { key, value, temp } => {
|
|
// Validate input at CLI layer for better user experience
|
|
module_config::validate_config_key(&key)?;
|
|
module_config::validate_config_value(&value)?;
|
|
|
|
let config_type = if temp {
|
|
module_config::ConfigType::Temp
|
|
} else {
|
|
module_config::ConfigType::Persist
|
|
};
|
|
module_config::set_config_value(&module_id, &key, &value, config_type)
|
|
}
|
|
ModuleConfigCmd::List => {
|
|
let config = module_config::merge_configs(&module_id)?;
|
|
if config.is_empty() {
|
|
println!("No config entries found");
|
|
} else {
|
|
for (key, value) in config {
|
|
println!("{key}={value}");
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
ModuleConfigCmd::Delete { key, temp } => {
|
|
let config_type = if temp {
|
|
module_config::ConfigType::Temp
|
|
} else {
|
|
module_config::ConfigType::Persist
|
|
};
|
|
module_config::delete_config_value(&module_id, &key, config_type)
|
|
}
|
|
ModuleConfigCmd::Clear { temp } => {
|
|
let config_type = if temp {
|
|
module_config::ConfigType::Temp
|
|
} else {
|
|
module_config::ConfigType::Persist
|
|
};
|
|
module_config::clear_config(&module_id, config_type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Commands::Install { magiskboot } => utils::install(magiskboot),
|
|
Commands::Uninstall { magiskboot } => utils::uninstall(magiskboot),
|
|
Commands::Sepolicy { command } => match command {
|
|
Sepolicy::Patch { sepolicy } => crate::sepolicy::live_patch(&sepolicy),
|
|
Sepolicy::Apply { file } => crate::sepolicy::apply_file(file),
|
|
Sepolicy::Check { sepolicy } => crate::sepolicy::check_rule(&sepolicy),
|
|
},
|
|
Commands::Services => {
|
|
init_event::on_services();
|
|
Ok(())
|
|
}
|
|
Commands::Profile { command } => match command {
|
|
Profile::GetSepolicy { package } => crate::profile::get_sepolicy(package),
|
|
Profile::SetSepolicy { package, policy } => {
|
|
crate::profile::set_sepolicy(package, policy)
|
|
}
|
|
Profile::GetTemplate { id } => crate::profile::get_template(id),
|
|
Profile::SetTemplate { id, template } => crate::profile::set_template(id, template),
|
|
Profile::DeleteTemplate { id } => crate::profile::delete_template(id),
|
|
Profile::ListTemplates => crate::profile::list_templates(),
|
|
},
|
|
|
|
Commands::Feature { command } => match command {
|
|
Feature::Get { id } => crate::feature::get_feature(&id),
|
|
Feature::Set { id, value } => crate::feature::set_feature(&id, value),
|
|
Feature::List => {
|
|
crate::feature::list_features();
|
|
Ok(())
|
|
}
|
|
Feature::Check { id } => crate::feature::check_feature(&id),
|
|
Feature::Load => crate::feature::load_config_and_apply(),
|
|
Feature::Save => crate::feature::save_config(),
|
|
},
|
|
|
|
Commands::Debug { command } => match command {
|
|
Debug::SetManager { apk } => debug::set_manager(&apk),
|
|
Debug::GetSign { apk } => {
|
|
let sign = apk_sign::get_apk_signature(&apk)?;
|
|
println!("size: {:#x}, hash: {}", sign.0, sign.1);
|
|
Ok(())
|
|
}
|
|
Debug::Version => {
|
|
println!("Kernel Version: {}", ksucalls::get_version());
|
|
Ok(())
|
|
}
|
|
Debug::Su { global_mnt } => crate::su::grant_root(global_mnt),
|
|
Debug::Test => assets::ensure_binaries(false),
|
|
Debug::Mark { command } => match command {
|
|
MarkCommand::Get { pid } => debug::mark_get(pid),
|
|
MarkCommand::Mark { pid } => debug::mark_set(pid),
|
|
MarkCommand::Unmark { pid } => debug::mark_unset(pid),
|
|
MarkCommand::Refresh => debug::mark_refresh(),
|
|
},
|
|
},
|
|
|
|
Commands::BootPatch {
|
|
boot,
|
|
init,
|
|
kernel,
|
|
module,
|
|
ota,
|
|
flash,
|
|
out,
|
|
magiskboot,
|
|
kmi,
|
|
partition,
|
|
} => crate::boot_patch::patch(
|
|
boot, kernel, module, init, ota, flash, out, magiskboot, kmi, partition,
|
|
),
|
|
|
|
Commands::BootInfo { command } => match command {
|
|
BootInfo::CurrentKmi => {
|
|
let kmi = crate::boot_patch::get_current_kmi()?;
|
|
println!("{kmi}");
|
|
// return here to avoid printing the error message
|
|
return Ok(());
|
|
}
|
|
BootInfo::SupportedKmis => {
|
|
let kmi = crate::assets::list_supported_kmi();
|
|
for kmi in &kmi {
|
|
println!("{kmi}");
|
|
}
|
|
return Ok(());
|
|
}
|
|
BootInfo::IsAbDevice => {
|
|
let val = crate::utils::getprop("ro.build.ab_update")
|
|
.unwrap_or_else(|| String::from("false"));
|
|
let is_ab = val.trim().to_lowercase() == "true";
|
|
println!("{}", if is_ab { "true" } else { "false" });
|
|
return Ok(());
|
|
}
|
|
BootInfo::DefaultPartition => {
|
|
let kmi = crate::boot_patch::get_current_kmi().unwrap_or_else(|_| String::new());
|
|
let name = crate::boot_patch::choose_boot_partition(&kmi, false, &None);
|
|
println!("{name}");
|
|
return Ok(());
|
|
}
|
|
BootInfo::SlotSuffix { ota } => {
|
|
let suffix = crate::boot_patch::get_slot_suffix(ota);
|
|
println!("{suffix}");
|
|
return Ok(());
|
|
}
|
|
BootInfo::AvailablePartitions => {
|
|
let parts = crate::boot_patch::list_available_partitions();
|
|
for p in &parts {
|
|
println!("{p}");
|
|
}
|
|
return Ok(());
|
|
}
|
|
},
|
|
Commands::BootRestore {
|
|
boot,
|
|
magiskboot,
|
|
flash,
|
|
} => crate::boot_patch::restore(boot, magiskboot, flash),
|
|
Commands::Kernel { command } => match command {
|
|
Kernel::NukeExt4Sysfs { mnt } => ksucalls::nuke_ext4_sysfs(&mnt),
|
|
Kernel::Umount { command } => match command {
|
|
UmountOp::Add { mnt, flags } => ksucalls::umount_list_add(&mnt, flags),
|
|
UmountOp::Del { mnt } => ksucalls::umount_list_del(&mnt),
|
|
UmountOp::Wipe => ksucalls::umount_list_wipe().map_err(Into::into),
|
|
},
|
|
Kernel::NotifyModuleMounted => {
|
|
ksucalls::report_module_mounted();
|
|
Ok(())
|
|
}
|
|
},
|
|
#[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(),
|
|
}
|
|
}
|
|
Commands::Umount { command } => match command {
|
|
Umount::Add { path, flags } => crate::umount_manager::add_umount_path(&path, flags),
|
|
Umount::Remove { path } => crate::umount_manager::remove_umount_path(&path),
|
|
Umount::List => crate::umount_manager::list_umount_paths(),
|
|
Umount::ClearCustom => crate::umount_manager::clear_custom_paths(),
|
|
Umount::Save => crate::umount_manager::save_umount_config(),
|
|
Umount::Load => crate::umount_manager::load_and_apply_config(),
|
|
Umount::Apply => crate::umount_manager::apply_config_to_kernel(),
|
|
},
|
|
};
|
|
|
|
if let Err(e) = &result {
|
|
log::error!("Error: {e:?}");
|
|
}
|
|
result
|
|
}
|