From b8eebcda5a7b2eeb48095c88617dc8d147ad1ad5 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Mon, 13 Oct 2025 17:40:33 +0800 Subject: [PATCH] kernel: Bump susfs binary version to 1.5.12 - Removed functionally coupled versions 1.5.10-1.5.11 - Removed `statusMagicMount` status retrieval - Use `getSuSFSFeatures` to replace `CMD_GET_SUSFS_FEATURE_STATUS` for obtaining SUSFS status. --- manager/app/src/main/assets/ksu_susfs_1.5.11 | Bin 30332 -> 0 bytes .../{ksu_susfs_1.5.10 => ksu_susfs_1.5.12} | Bin manager/app/src/main/cpp/jni.c | 31 ------ manager/app/src/main/cpp/ksu.c | 9 -- manager/app/src/main/cpp/ksu.h | 18 ---- .../src/main/java/com/sukisu/ultra/Natives.kt | 22 ---- .../com/sukisu/ultra/ui/susfs/SuSFSConfig.kt | 85 +++++++++++---- .../ultra/ui/susfs/util/SuSFSManager.kt | 99 +++++++++++------- .../java/com/sukisu/ultra/ui/util/KsuCli.kt | 4 +- .../app/src/main/res/values-idn/strings.xml | 1 - .../app/src/main/res/values-in/strings.xml | 1 - .../app/src/main/res/values-ja/strings.xml | 1 - .../app/src/main/res/values-ru/strings.xml | 1 - .../app/src/main/res/values-tr/strings.xml | 1 - .../app/src/main/res/values-uk/strings.xml | 1 - .../app/src/main/res/values-vi/strings.xml | 1 - .../src/main/res/values-zh-rCN/strings.xml | 3 +- .../src/main/res/values-zh-rHK/strings.xml | 1 - .../src/main/res/values-zh-rTW/strings.xml | 1 - manager/app/src/main/res/values/strings.xml | 3 +- 20 files changed, 135 insertions(+), 148 deletions(-) delete mode 100755 manager/app/src/main/assets/ksu_susfs_1.5.11 rename manager/app/src/main/assets/{ksu_susfs_1.5.10 => ksu_susfs_1.5.12} (100%) diff --git a/manager/app/src/main/assets/ksu_susfs_1.5.11 b/manager/app/src/main/assets/ksu_susfs_1.5.11 deleted file mode 100755 index 34c9f3e0f463e1843d94219136b4c45be13a0c2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30332 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 w4`I6B@vzjf%5Z&mR diff --git a/manager/app/src/main/assets/ksu_susfs_1.5.10 b/manager/app/src/main/assets/ksu_susfs_1.5.12 similarity index 100% rename from manager/app/src/main/assets/ksu_susfs_1.5.10 rename to manager/app/src/main/assets/ksu_susfs_1.5.12 diff --git a/manager/app/src/main/cpp/jni.c b/manager/app/src/main/cpp/jni.c index 05c028c1..a5b0f816 100644 --- a/manager/app/src/main/cpp/jni.c +++ b/manager/app/src/main/cpp/jni.c @@ -310,37 +310,6 @@ NativeBridgeNP(getHookType, jstring) { return GetEnvironment()->NewStringUTF(env, hook_type); } -// SuSFS Related Function Status -NativeBridgeNP(getSusfsFeatureStatus, jobject) { - struct susfs_feature_status status; - bool result = get_susfs_feature_status(&status); - - if (!result) { - return NULL; - } - - jclass cls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$SusfsFeatureStatus"); - jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "", "()V"); - jobject obj = GetEnvironment()->NewObject(env, cls, constructor); - - SET_BOOLEAN_FIELD(obj, cls, statusSusPath, status.status_sus_path); - SET_BOOLEAN_FIELD(obj, cls, statusSusMount, status.status_sus_mount); - SET_BOOLEAN_FIELD(obj, cls, statusAutoDefaultMount, status.status_auto_default_mount); - SET_BOOLEAN_FIELD(obj, cls, statusAutoBindMount, status.status_auto_bind_mount); - SET_BOOLEAN_FIELD(obj, cls, statusSusKstat, status.status_sus_kstat); - SET_BOOLEAN_FIELD(obj, cls, statusTryUmount, status.status_try_umount); - SET_BOOLEAN_FIELD(obj, cls, statusAutoTryUmountBind, status.status_auto_try_umount_bind); - SET_BOOLEAN_FIELD(obj, cls, statusSpoofUname, status.status_spoof_uname); - SET_BOOLEAN_FIELD(obj, cls, statusEnableLog, status.status_enable_log); - SET_BOOLEAN_FIELD(obj, cls, statusHideSymbols, status.status_hide_symbols); - SET_BOOLEAN_FIELD(obj, cls, statusSpoofCmdline, status.status_spoof_cmdline); - SET_BOOLEAN_FIELD(obj, cls, statusOpenRedirect, status.status_open_redirect); - SET_BOOLEAN_FIELD(obj, cls, statusMagicMount, status.status_magic_mount); - SET_BOOLEAN_FIELD(obj, cls, statusSusSu, status.status_sus_su); - - return obj; -} - // dynamic manager NativeBridge(setDynamicManager, jboolean, jint size, jstring hash) { if (!hash) { diff --git a/manager/app/src/main/cpp/ksu.c b/manager/app/src/main/cpp/ksu.c index 1094a4b1..245ae290 100644 --- a/manager/app/src/main/cpp/ksu.c +++ b/manager/app/src/main/cpp/ksu.c @@ -45,7 +45,6 @@ extern const char* zako_file_verrcidx2str(uint8_t index); #define CMD_ENABLE_KPM 100 #define CMD_HOOK_TYPE 101 -#define CMD_GET_SUSFS_FEATURE_STATUS 102 #define CMD_DYNAMIC_MANAGER 103 #define CMD_GET_MANAGERS 104 #define CMD_ENABLE_UID_SCANNER 105 @@ -150,14 +149,6 @@ bool get_hook_type(char* hook_type, size_t size) { return true; } -bool get_susfs_feature_status(struct susfs_feature_status* status) { - if (status == NULL) { - return false; - } - - return ksuctl(CMD_GET_SUSFS_FEATURE_STATUS, status, NULL); -} - bool set_dynamic_manager(unsigned int size, const char* hash) { if (hash == NULL) { return false; diff --git a/manager/app/src/main/cpp/ksu.h b/manager/app/src/main/cpp/ksu.h index 57c93833..2ea7fe29 100644 --- a/manager/app/src/main/cpp/ksu.h +++ b/manager/app/src/main/cpp/ksu.h @@ -39,23 +39,6 @@ struct dynamic_manager_user_config { char hash[65]; }; -// SUSFS Functional State Structures -struct susfs_feature_status { - bool status_sus_path; - bool status_sus_mount; - bool status_auto_default_mount; - bool status_auto_bind_mount; - bool status_sus_kstat; - bool status_try_umount; - bool status_auto_try_umount_bind; - bool status_spoof_uname; - bool status_enable_log; - bool status_hide_symbols; - bool status_spoof_cmdline; - bool status_open_redirect; - bool status_magic_mount; - bool status_sus_su; -}; struct root_profile { int32_t uid; @@ -125,7 +108,6 @@ bool is_KPM_enable(); bool get_hook_type(char* hook_type, size_t size); -bool get_susfs_feature_status(struct susfs_feature_status* status); bool set_dynamic_manager(unsigned int size, const char* hash); diff --git a/manager/app/src/main/java/com/sukisu/ultra/Natives.kt b/manager/app/src/main/java/com/sukisu/ultra/Natives.kt index 7a803626..36f37528 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/Natives.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/Natives.kt @@ -106,7 +106,6 @@ object Natives { * Get SUSFS feature status from kernel * @return SusfsFeatureStatus object containing all feature states, or null if failed */ - external fun getSusfsFeatureStatus(): SusfsFeatureStatus? /** * Set dynamic managerature configuration @@ -183,27 +182,6 @@ object Natives { return isVersionLessThan(getFullVersion(), MINIMAL_SUPPORTED_KERNEL_FULL) } - @Immutable - @Parcelize - @Keep - data class SusfsFeatureStatus( - val statusSusPath: Boolean = false, - val statusSusMount: Boolean = false, - val statusAutoDefaultMount: Boolean = false, - val statusAutoBindMount: Boolean = false, - val statusSusKstat: Boolean = false, - val statusTryUmount: Boolean = false, - val statusAutoTryUmountBind: Boolean = false, - val statusSpoofUname: Boolean = false, - val statusEnableLog: Boolean = false, - val statusHideSymbols: Boolean = false, - val statusSpoofCmdline: Boolean = false, - val statusOpenRedirect: Boolean = false, - val statusMagicMount: Boolean = false, - val statusOverlayfsAutoKstat: Boolean = false, - val statusSusSu: Boolean = false - ) : Parcelable - @Immutable @Parcelize @Keep diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/SuSFSConfig.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/SuSFSConfig.kt index 2f15f14c..dfa01e5d 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/SuSFSConfig.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/SuSFSConfig.kt @@ -42,6 +42,7 @@ import com.sukisu.ultra.ui.theme.CardConfig import com.sukisu.ultra.ui.susfs.util.SuSFSManager import com.sukisu.ultra.ui.susfs.util.SuSFSManager.isSusVersion158 import com.sukisu.ultra.ui.susfs.util.SuSFSManager.isSusVersion159 +import com.sukisu.ultra.ui.util.getSuSFSVersion import com.sukisu.ultra.ui.util.isAbDevice import kotlinx.coroutines.launch import java.io.File @@ -168,6 +169,38 @@ fun SuSFSConfigScreen( } } + var showVersionMismatchDialog by remember { mutableStateOf(false) } + + if (showVersionMismatchDialog) { + AlertDialog( + onDismissRequest = { showVersionMismatchDialog = false }, + title = { + Text( + text = stringResource(R.string.warning), + style = MaterialTheme.typography.headlineSmall, + fontWeight = FontWeight.Bold + ) + }, + text = { + Text( + stringResource( + R.string.susfs_version_mismatch, + try { getSuSFSVersion() } catch (_: Exception) { "unknown" }, + SuSFSManager.MAX_SUSFS_VERSION + ) + ) + }, + confirmButton = { + TextButton( + onClick = { showVersionMismatchDialog = false }, + modifier = Modifier.padding(8.dp) + ) { + Text(stringResource(R.string.confirm)) + } + } + ) + } + // 文件选择器 val backupFileLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.CreateDocument("application/json") @@ -253,25 +286,41 @@ fun SuSFSConfigScreen( // 加载当前配置 LaunchedEffect(Unit) { - unameValue = SuSFSManager.getUnameValue(context) - buildTimeValue = SuSFSManager.getBuildTimeValue(context) - autoStartEnabled = SuSFSManager.isAutoStartEnabled(context) - executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context) - susPaths = SuSFSManager.getSusPaths(context) - susLoopPaths = SuSFSManager.getSusLoopPaths(context) - susMounts = SuSFSManager.getSusMounts(context) - tryUmounts = SuSFSManager.getTryUmounts(context) - androidDataPath = SuSFSManager.getAndroidDataPath(context) - sdcardPath = SuSFSManager.getSdcardPath(context) - kstatConfigs = SuSFSManager.getKstatConfigs(context) - addKstatPaths = SuSFSManager.getAddKstatPaths(context) - hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) - enableHideBl = SuSFSManager.getEnableHideBl(context) - enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) - umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context) - enableAvcLogSpoofing = SuSFSManager.getEnableAvcLogSpoofing(context) + coroutineScope.launch { + try { + val version = getSuSFSVersion() + val binaryName = "ksu_susfs_${version.removePrefix("v")}" - loadSlotInfo() + val isBinaryAvailable = try { + context.assets.open(binaryName).use { true } + } catch (_: Exception) { false } + + if (!isBinaryAvailable) { + showVersionMismatchDialog = true + } + } catch (_: Exception) { + } + + unameValue = SuSFSManager.getUnameValue(context) + buildTimeValue = SuSFSManager.getBuildTimeValue(context) + autoStartEnabled = SuSFSManager.isAutoStartEnabled(context) + executeInPostFsData = SuSFSManager.getExecuteInPostFsData(context) + susPaths = SuSFSManager.getSusPaths(context) + susLoopPaths = SuSFSManager.getSusLoopPaths(context) + susMounts = SuSFSManager.getSusMounts(context) + tryUmounts = SuSFSManager.getTryUmounts(context) + androidDataPath = SuSFSManager.getAndroidDataPath(context) + sdcardPath = SuSFSManager.getSdcardPath(context) + kstatConfigs = SuSFSManager.getKstatConfigs(context) + addKstatPaths = SuSFSManager.getAddKstatPaths(context) + hideSusMountsForAllProcs = SuSFSManager.getHideSusMountsForAllProcs(context) + enableHideBl = SuSFSManager.getEnableHideBl(context) + enableCleanupResidue = SuSFSManager.getEnableCleanupResidue(context) + umountForZygoteIsoService = SuSFSManager.getUmountForZygoteIsoService(context) + enableAvcLogSpoofing = SuSFSManager.getEnableAvcLogSpoofing(context) + + loadSlotInfo() + } } // 当切换到启用功能状态标签页时加载数据 diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/util/SuSFSManager.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/util/SuSFSManager.kt index 70a68481..24a570f6 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/util/SuSFSManager.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/susfs/util/SuSFSManager.kt @@ -9,7 +9,6 @@ import android.os.Build import android.util.Log import android.widget.Toast import com.dergoogler.mmrl.platform.Platform.Companion.context -import com.sukisu.ultra.Natives import com.sukisu.ultra.R import com.topjohnwu.superuser.Shell import kotlinx.coroutines.Dispatchers @@ -22,6 +21,7 @@ import java.io.IOException import androidx.core.content.edit import com.sukisu.ultra.ui.util.getRootShell import com.sukisu.ultra.ui.util.getSuSFSVersion +import com.sukisu.ultra.ui.util.getSuSFSFeatures import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -65,6 +65,7 @@ object SuSFSManager { private const val MODULE_PATH = "/data/adb/modules/$MODULE_ID" private const val MIN_VERSION_FOR_HIDE_MOUNT = "1.5.8" private const val MIN_VERSION_FOR_LOOP_PATH = "1.5.9" + const val MAX_SUSFS_VERSION = "1.5.12" private const val BACKUP_FILE_EXTENSION = ".susfs_backup" private const val MEDIA_DATA_PATH = "/data/media/0/Android/data" private const val CGROUP_UID_PATH_PREFIX = "/sys/fs/cgroup/uid_" @@ -185,11 +186,23 @@ object SuSFSManager { private fun getPrefs(context: Context): SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - private fun getSuSFSVersionUse(): String = try { - getSuSFSVersion() - } catch (_: Exception) { MIN_VERSION_FOR_HIDE_MOUNT } + private fun getSuSFSVersionUse(context: Context): String = try { + val version = getSuSFSVersion() + val binaryName = "${SUSFS_BINARY_TARGET_NAME}_${version.removePrefix("v")}" + if (isBinaryAvailable(context, binaryName)) { + version + } else { + MAX_SUSFS_VERSION + } + } catch (_: Exception) { + MAX_SUSFS_VERSION + } - private fun getSuSFSBinaryName(): String = "${SUSFS_BINARY_TARGET_NAME}_${getSuSFSVersionUse().removePrefix("v")}" + fun isBinaryAvailable(context: Context, binaryName: String): Boolean = try { + context.assets.open(binaryName).use { true } + } catch (_: IOException) { false } + + private fun getSuSFSBinaryName(context: Context): String = "${SUSFS_BINARY_TARGET_NAME}_${getSuSFSVersionUse(context).removePrefix("v")}" private fun getSuSFSTargetPath(): String = "/data/adb/ksu/bin/$SUSFS_BINARY_TARGET_NAME" @@ -715,7 +728,7 @@ object SuSFSManager { // 二进制文件管理 private suspend fun copyBinaryFromAssets(context: Context): String? = withContext(Dispatchers.IO) { try { - val binaryName = getSuSFSBinaryName() + val binaryName = getSuSFSBinaryName(context) val targetPath = getSuSFSTargetPath() val tempFile = File(context.cacheDir, binaryName) @@ -736,7 +749,7 @@ object SuSFSManager { } fun isBinaryAvailable(context: Context): Boolean = try { - context.assets.open(getSuSFSBinaryName()).use { true } + context.assets.open(getSuSFSBinaryName(context)).use { true } } catch (_: IOException) { false } // 命令执行 @@ -823,9 +836,10 @@ object SuSFSManager { // 功能状态获取 suspend fun getEnabledFeatures(context: Context): List = withContext(Dispatchers.IO) { try { - val status = Natives.getSusfsFeatureStatus() - if (status != null) { - parseEnabledFeaturesFromStatus(context, status) + val featuresOutput = getSuSFSFeatures() + + if (featuresOutput.isNotBlank() && featuresOutput != "Invalid") { + parseEnabledFeaturesFromOutput(context, featuresOutput) } else { getDefaultDisabledFeatures(context) } @@ -835,10 +849,47 @@ object SuSFSManager { } } + private fun parseEnabledFeaturesFromOutput(context: Context, featuresOutput: String): List { + val enabledConfigs = featuresOutput.lines() + .map { it.trim() } + .filter { it.isNotEmpty() } + .toSet() + + val featureMap = mapOf( + "CONFIG_KSU_SUSFS_SUS_PATH" to context.getString(R.string.sus_path_feature_label), + "CONFIG_KSU_SUSFS_SUS_MOUNT" to context.getString(R.string.sus_mount_feature_label), + "CONFIG_KSU_SUSFS_TRY_UMOUNT" to context.getString(R.string.try_umount_feature_label), + "CONFIG_KSU_SUSFS_SPOOF_UNAME" to context.getString(R.string.spoof_uname_feature_label), + "CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG" to context.getString(R.string.spoof_cmdline_feature_label), + "CONFIG_KSU_SUSFS_OPEN_REDIRECT" to context.getString(R.string.open_redirect_feature_label), + "CONFIG_KSU_SUSFS_ENABLE_LOG" to context.getString(R.string.enable_log_feature_label), + "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT" to context.getString(R.string.auto_default_mount_feature_label), + "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT" to context.getString(R.string.auto_bind_mount_feature_label), + "CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT" to context.getString(R.string.auto_try_umount_bind_feature_label), + "CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS" to context.getString(R.string.hide_symbols_feature_label), + "CONFIG_KSU_SUSFS_SUS_KSTAT" to context.getString(R.string.sus_kstat_feature_label), + "CONFIG_KSU_SUSFS_SUS_SU" to context.getString(R.string.sus_su_feature_label) + ) + + + return featureMap.map { (configKey, displayName) -> + val isEnabled = enabledConfigs.contains(configKey) + + val statusText = if (isEnabled) { + context.getString(R.string.susfs_feature_enabled) + } else { + context.getString(R.string.susfs_feature_disabled) + } + + val canConfigure = displayName == context.getString(R.string.enable_log_feature_label) + + EnabledFeature(displayName, isEnabled, statusText, canConfigure) + }.sortedBy { it.name } + } + private fun getDefaultDisabledFeatures(context: Context): List { val defaultFeatures = listOf( "sus_path_feature_label" to context.getString(R.string.sus_path_feature_label), - "sus_loop_path_feature_label" to context.getString(R.string.sus_loop_path_feature_label), "sus_mount_feature_label" to context.getString(R.string.sus_mount_feature_label), "try_umount_feature_label" to context.getString(R.string.try_umount_feature_label), "spoof_uname_feature_label" to context.getString(R.string.spoof_uname_feature_label), @@ -850,7 +901,6 @@ object SuSFSManager { "auto_try_umount_bind_feature_label" to context.getString(R.string.auto_try_umount_bind_feature_label), "hide_symbols_feature_label" to context.getString(R.string.hide_symbols_feature_label), "sus_kstat_feature_label" to context.getString(R.string.sus_kstat_feature_label), - "magic_mount_feature_label" to context.getString(R.string.magic_mount_feature_label), "sus_su_feature_label" to context.getString(R.string.sus_su_feature_label) ) @@ -864,31 +914,6 @@ object SuSFSManager { }.sortedBy { it.name } } - private fun parseEnabledFeaturesFromStatus(context: Context, status: Natives.SusfsFeatureStatus): List { - val featureList = listOf( - Triple("status_sus_path", context.getString(R.string.sus_path_feature_label), status.statusSusPath), - Triple("status_sus_mount", context.getString(R.string.sus_mount_feature_label), status.statusSusMount), - Triple("status_try_umount", context.getString(R.string.try_umount_feature_label), status.statusTryUmount), - Triple("status_spoof_uname", context.getString(R.string.spoof_uname_feature_label), status.statusSpoofUname), - Triple("status_spoof_cmdline", context.getString(R.string.spoof_cmdline_feature_label), status.statusSpoofCmdline), - Triple("status_open_redirect", context.getString(R.string.open_redirect_feature_label), status.statusOpenRedirect), - Triple("status_enable_log", context.getString(R.string.enable_log_feature_label), status.statusEnableLog), - Triple("status_auto_default_mount", context.getString(R.string.auto_default_mount_feature_label), status.statusAutoDefaultMount), - Triple("status_auto_bind_mount", context.getString(R.string.auto_bind_mount_feature_label), status.statusAutoBindMount), - Triple("status_auto_try_umount_bind", context.getString(R.string.auto_try_umount_bind_feature_label), status.statusAutoTryUmountBind), - Triple("status_hide_symbols", context.getString(R.string.hide_symbols_feature_label), status.statusHideSymbols), - Triple("status_sus_kstat", context.getString(R.string.sus_kstat_feature_label), status.statusSusKstat), - Triple("status_magic_mount", context.getString(R.string.magic_mount_feature_label), status.statusMagicMount), - Triple("status_sus_su", context.getString(R.string.sus_su_feature_label), status.statusSusSu) - ) - - return featureList.map { (id, displayName, isEnabled) -> - val statusText = if (isEnabled) context.getString(R.string.susfs_feature_enabled) else context.getString(R.string.susfs_feature_disabled) - val canConfigure = id == "status_enable_log" - EnabledFeature(displayName, isEnabled, statusText, canConfigure) - }.sortedBy { it.name } - } - // sus日志开关 suspend fun setEnableLog(context: Context, enabled: Boolean): Boolean { val success = executeSusfsCommand(context, "enable_log ${if (enabled) 1 else 0}") diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/util/KsuCli.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/util/KsuCli.kt index 4252c779..70df5e98 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/util/KsuCli.kt @@ -528,8 +528,8 @@ fun getSuSFSVariant(): String { fun getSuSFSFeatures(): String { val shell = getRootShell() - val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features") - return result + val cmd = "${getSuSFSDaemonPath()} features" + return runCmd(shell, cmd) } fun susfsSUS_SU_0(): String { diff --git a/manager/app/src/main/res/values-idn/strings.xml b/manager/app/src/main/res/values-idn/strings.xml index 0a4aed09..9a883b2d 100644 --- a/manager/app/src/main/res/values-idn/strings.xml +++ b/manager/app/src/main/res/values-idn/strings.xml @@ -446,7 +446,6 @@ Tanamkan: Secara permanen memasang ke sistem Kaitan Bind Otomatis Coba Lepas Kaitan Bind Otomatis Sembunyikan Simbol KSU SUSFS - Dukungan Magic Mount Dukungan SUS Kstat Fitur Toggle Mode SUS SU diff --git a/manager/app/src/main/res/values-in/strings.xml b/manager/app/src/main/res/values-in/strings.xml index 8887462e..3baf148a 100644 --- a/manager/app/src/main/res/values-in/strings.xml +++ b/manager/app/src/main/res/values-in/strings.xml @@ -443,7 +443,6 @@ Pemasangan Bind Otomatis Coba Umount Bind Mount Otomatis Sembunyikan Simbol KSU SUSFS - Dukungan Pemasangan Ajaib Dukungan SUS Kstat Fungsi pengalihan mode SUS SU diff --git a/manager/app/src/main/res/values-ja/strings.xml b/manager/app/src/main/res/values-ja/strings.xml index 1feec5cd..b4e674a9 100644 --- a/manager/app/src/main/res/values-ja/strings.xml +++ b/manager/app/src/main/res/values-ja/strings.xml @@ -443,7 +443,6 @@ 自動でバインドマウント 自動でバインドマウントのアンマウントを試す KSU SUSFS シンボルを非表示 - Magic Mount の対応 SUS Kstat の対応 SUS SU モード切り替え機能 diff --git a/manager/app/src/main/res/values-ru/strings.xml b/manager/app/src/main/res/values-ru/strings.xml index 0f84799c..85f644b8 100644 --- a/manager/app/src/main/res/values-ru/strings.xml +++ b/manager/app/src/main/res/values-ru/strings.xml @@ -443,7 +443,6 @@ Автоматическое бинд монтирование Автоматически попробовать размонтировать привязать монтировать Скрытие KSU SUSFS Symbols - Поддержка Magic Mount Поддержка SUS Kstat Функция переключения режима SUS SU diff --git a/manager/app/src/main/res/values-tr/strings.xml b/manager/app/src/main/res/values-tr/strings.xml index b513a103..3b9780a8 100644 --- a/manager/app/src/main/res/values-tr/strings.xml +++ b/manager/app/src/main/res/values-tr/strings.xml @@ -441,7 +441,6 @@ Otomatik Bağlama Noktası Bağlama Otomatik Bağlamayı Kaldırmayı Dene Bağlama KSU SUSFS Sembollerini Gizle - Magic Mount Desteği SUS Kstat Desteği SUS SU mod değiştirme işlevi diff --git a/manager/app/src/main/res/values-uk/strings.xml b/manager/app/src/main/res/values-uk/strings.xml index 46e73e81..27593eaa 100644 --- a/manager/app/src/main/res/values-uk/strings.xml +++ b/manager/app/src/main/res/values-uk/strings.xml @@ -441,7 +441,6 @@ Автоматичне прив\'язане монтування Автоматична спроба відмонтування прив\'язаного монтування Приховати символи KSU SUSFS - Підтримка Magic Mount Підтримка SUS Kstat Функція перемикання режиму SUS SU diff --git a/manager/app/src/main/res/values-vi/strings.xml b/manager/app/src/main/res/values-vi/strings.xml index deb5539b..a6586dcf 100644 --- a/manager/app/src/main/res/values-vi/strings.xml +++ b/manager/app/src/main/res/values-vi/strings.xml @@ -441,7 +441,6 @@ Tự động Bind Mount Tự động Try Umount Bind Mount Ẩn biểu tượng KSU SuSFS - Hỗ trợ Magic Mount Hỗ trợ SuS Kstat Chức năng chuyển đổi chế độ SuS SU diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml index 87aa8db2..844200d1 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -441,7 +441,6 @@ 自动绑定挂载 自动尝试卸载绑定挂载 隐藏 KSU SuSFS 符号 - 魔法坐骑支持 SuS Kstat 支持 SuS SU 模式切换功能 @@ -559,6 +558,8 @@ 其他 应用 添加应用路径 + SuSFS 库版本不匹配,内核:%1$s vs 管理器:%2$s,建议更新内核或管理器 + 警告 搜索应用 %1$d 个已选应用 %1$d 个已添加应用 diff --git a/manager/app/src/main/res/values-zh-rHK/strings.xml b/manager/app/src/main/res/values-zh-rHK/strings.xml index f2faba62..8a15131e 100644 --- a/manager/app/src/main/res/values-zh-rHK/strings.xml +++ b/manager/app/src/main/res/values-zh-rHK/strings.xml @@ -438,7 +438,6 @@ 自動綁定掛載 自動嘗試卸載綁定掛載 隱藏 KSU SuSFS 符號 - 魔法坐騎支援 SuS Kstat 支援 SuS SU 模式切換功能 diff --git a/manager/app/src/main/res/values-zh-rTW/strings.xml b/manager/app/src/main/res/values-zh-rTW/strings.xml index 3cb7c3a6..62edc9ae 100644 --- a/manager/app/src/main/res/values-zh-rTW/strings.xml +++ b/manager/app/src/main/res/values-zh-rTW/strings.xml @@ -441,7 +441,6 @@ 自動綁定掛載 自動嘗試卸載綁定掛載 隱藏 KSU SuSFS 符號 - 魔法掛載支援 SuS 內核統計支援 SuS SU 模式切換功能 diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 2477f81c..c0e10bbf 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -443,7 +443,6 @@ Auto Bind Mount Auto Try Umount Bind Mount Hide KSU SUSFS Symbols - Magic Mount Support SUS Kstat Support SUS SU mode switching function @@ -561,6 +560,8 @@ Other App Add App Path + SuSFS library version mismatch, kernel: %1$s vs manager: %2$s, It is recommended to update the kernel or manager + Warning Search Apps %1$d apps selected %1$d apps already added