You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
Compare commits
39 Commits
testing
...
dc8130161b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc8130161b | ||
|
|
79e9edcb77 | ||
|
|
f0934e6b90 | ||
|
|
0744aebee0 | ||
|
|
f5b771f6af | ||
|
|
e497c5396c | ||
|
|
43a6fcce28 | ||
|
|
aa37bcc368 | ||
|
|
107cd4add0 | ||
|
|
94c4b41ea3 | ||
|
|
0bde9047b9 | ||
|
|
bc9927b9b6 | ||
|
|
d4f4c0a0cc | ||
|
|
0aaae919c0 | ||
|
|
3f4c23a34f | ||
|
|
d69a72c658 | ||
|
|
adbff41a22 | ||
|
|
512f84504e | ||
|
|
c44f48c8a4 | ||
|
|
5c6c3870a0 | ||
|
|
c6b5440682 | ||
|
|
a917314e84 | ||
|
|
948975ba35 | ||
|
|
45ad73e9dd | ||
|
|
892a62afdf | ||
|
|
d61de07c21 | ||
|
|
4382dca515 | ||
|
|
2c9078e038 | ||
|
|
81f4f09d0c | ||
|
|
2241696498 | ||
|
|
514c5458ed | ||
|
|
d30bb33a9c | ||
|
|
ec7fe6b039 | ||
|
|
3fd61e0ee5 | ||
|
|
8fc85993f1 | ||
|
|
df07860e44 | ||
|
|
bd03c296a1 | ||
|
|
14b7861f44 | ||
|
|
3c421b1362 |
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -60,8 +60,9 @@ body:
|
||||
value: |
|
||||
- Device:
|
||||
- OS Version:
|
||||
- KernelSU Version:
|
||||
- Kernel Version:
|
||||
- KSUN Driver Version:
|
||||
- KSUN Manager Version:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
6
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request
|
||||
url: https://t.me/ksunext/578
|
||||
about: "We do not accept external Feature Requests anymore, check the link for more details."
|
||||
blank_issues_enabled: false
|
||||
41
.github/ISSUE_TEMPLATE/request.yml
vendored
Normal file
41
.github/ISSUE_TEMPLATE/request.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or improvement for KernelSU Next.
|
||||
title: "[Feature] <short description>"
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to suggest a feature! Please fill out the following details.
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: "Is your feature request related to a problem?"
|
||||
description: "A clear and concise description of what the problem is. Ex: I'm always frustrated when..."
|
||||
placeholder: "Describe the problem or need."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: "Describe the solution you'd like"
|
||||
description: "A clear and concise description of what you want to happen."
|
||||
placeholder: "Describe your proposed solution."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: "Describe alternatives you've considered"
|
||||
description: "A clear and concise description of any alternative solutions or features you've considered."
|
||||
placeholder: "List any alternatives."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Add any other context or screenshots about the feature request here."
|
||||
placeholder: "Additional context or screenshots."
|
||||
validations:
|
||||
required: false
|
||||
12
.github/workflows/gki-kernel.yml
vendored
12
.github/workflows/gki-kernel.yml
vendored
@@ -195,6 +195,18 @@ jobs:
|
||||
sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
|
||||
fi
|
||||
|
||||
- name: Setup Syscall Hooks
|
||||
if: ${{ inputs.build_lkm == false }}
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE/android-kernel/common
|
||||
echo "[+] Patch Kernel"
|
||||
curl -L https://github.com/KernelSU-Next/kernel_patches/raw/main/syscall_hook/min_scope_syscall_hooks_v1.4.patch | patch -p1 --fuzz=3
|
||||
echo "[+] Set Config"
|
||||
echo "CONFIG_KSU=y" >> ./arch/arm64/configs/gki_defconfig
|
||||
echo "CONFIG_KSU_KPROBES_HOOK=n" >> ./arch/arm64/configs/gki_defconfig
|
||||
echo "[+] Disable Config Check"
|
||||
sed -i 's/check_defconfig//' ./build.config.gki
|
||||
|
||||
- name: Make working directory clean to avoid dirty
|
||||
working-directory: android-kernel
|
||||
run: |
|
||||
|
||||
31
build.sh
Executable file
31
build.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script builds the KernelSU Next manager APK.
|
||||
|
||||
# Ensure you have the setup Android SDK & NDK installed and necessary environment variables set and sourced.
|
||||
|
||||
# For LKM make sure you have imported the androidX-X.X_kernelsu.ko drivers to userspace/ksud_*/bin/aarch64 directory.
|
||||
|
||||
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud_magic/Cargo.toml
|
||||
|
||||
cp userspace/ksud_magic/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
||||
|
||||
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud_overlayfs/Cargo.toml
|
||||
|
||||
cp userspace/ksud_overlayfs/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
||||
|
||||
cd userspace/susfsd/jni
|
||||
|
||||
ndk-build
|
||||
|
||||
cp ../libs/arm64-v8a/susfsd ../../../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
||||
|
||||
cd ../../..
|
||||
|
||||
cd manager
|
||||
|
||||
./setup.sh
|
||||
|
||||
cd ..
|
||||
|
||||
adb install manager/app/build/outputs/apk/release/KernelSU_Next_v*.apk
|
||||
@@ -74,6 +74,7 @@ If you’d like to support the project:
|
||||
|
||||
- **USDT (BEP20, ERC20)**: `0x12b5224b7aca0121c2f003240a901e1d064371c1`
|
||||
- **USDT (TRC20)**: `TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh`
|
||||
- **USDT (SOL)**: `A4wqBXYd6Ey4nK4SJ2bmjeMgGyaLKT9TwDLh8BEo8Zu6`
|
||||
- **ETH (ERC20)**: `0x12b5224b7aca0121c2f003240a901e1d064371c1`
|
||||
- **LTC**: `Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL`
|
||||
- **BTC**: `19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6`
|
||||
@@ -87,5 +88,4 @@ If you’d like to support the project:
|
||||
- [Genuine](https://github.com/brevent/genuine/) – APK v2 signature validation
|
||||
- [Diamorphine](https://github.com/m0nad/Diamorphine) – Rootkit techniques
|
||||
- [KernelSU](https://github.com/tiann/KernelSU) – The original base that made KernelSU Next possible
|
||||
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs) – 💜 to 5ec1cff for keeping KernelSU alive
|
||||
- [Crowdin Translators](https://crowdin.com/project/kernelsu-next/members) – 💬 Thanks to everyone for helping make KernelSU Next multi-lingual!
|
||||
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs) – For magic mount support
|
||||
|
||||
@@ -49,12 +49,12 @@ ifeq ($(shell grep "ssize_t kernel_write" $(srctree)/fs/read_write.c | grep -q "
|
||||
ccflags-y += -DKSU_KERNEL_WRITE
|
||||
endif
|
||||
|
||||
ifndef KSU_NEXT_EXPECTED_SIZE
|
||||
KSU_NEXT_EXPECTED_SIZE := 0x3e6
|
||||
ifndef KSU_NEXT_MANAGER_SIZE
|
||||
KSU_NEXT_MANAGER_SIZE := 0x3e6
|
||||
endif
|
||||
|
||||
ifndef KSU_NEXT_EXPECTED_HASH
|
||||
KSU_NEXT_EXPECTED_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
|
||||
ifndef KSU_NEXT_MANAGER_HASH
|
||||
KSU_NEXT_MANAGER_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7
|
||||
endif
|
||||
|
||||
ifdef KSU_MANAGER_PACKAGE
|
||||
@@ -62,48 +62,14 @@ ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
|
||||
$(info -- KernelSU-Next Manager package name: $(KSU_MANAGER_PACKAGE))
|
||||
endif
|
||||
|
||||
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_EXPECTED_SIZE))
|
||||
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_EXPECTED_HASH))
|
||||
$(info -- KernelSU-Next Manager signature size: $(KSU_NEXT_MANAGER_SIZE))
|
||||
$(info -- KernelSU-Next Manager signature hash: $(KSU_NEXT_MANAGER_HASH))
|
||||
|
||||
ccflags-y += -DEXPECTED_NEXT_SIZE=$(KSU_NEXT_EXPECTED_SIZE)
|
||||
ccflags-y += -DEXPECTED_NEXT_HASH=\"$(KSU_NEXT_EXPECTED_HASH)\"
|
||||
|
||||
ccflags-y += -DKSU_COMPAT_GET_CRED_RCU
|
||||
ccflags-y += -DEXPECTED_MANAGER_SIZE=$(KSU_NEXT_MANAGER_SIZE)
|
||||
ccflags-y += -DEXPECTED_MANAGER_HASH=\"$(KSU_NEXT_MANAGER_HASH)\"
|
||||
|
||||
ccflags-y += -DKSU_UMOUNT
|
||||
|
||||
# Determine the appropriate atomic function and apply patch accordingly
|
||||
ifeq ($(shell grep -q "atomic_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
|
||||
ATOMIC_INC_FUNC = atomic_inc_not_zero
|
||||
else ifeq ($(shell grep -q "atomic_long_inc_not_zero" $(srctree)/kernel/cred.c; echo $$?),0)
|
||||
ATOMIC_INC_FUNC = atomic_long_inc_not_zero
|
||||
else
|
||||
$(info -- KSU_NEXT: Neither atomic_inc_not_zero nor atomic_long_inc_not_zero found in kernel/cred.c)
|
||||
endif
|
||||
|
||||
# Inform which function is being patched
|
||||
$(info -- KSU_NEXT: Using $(ATOMIC_INC_FUNC) in get_cred_rcu patch.)
|
||||
|
||||
# Add the get_cred_rcu function to cred.h if not already present
|
||||
ifneq ($(shell grep -Eq "^static inline const struct cred \*get_cred_rcu" $(srctree)/include/linux/cred.h; echo $$?),0)
|
||||
$(info -- KSU_NEXT: adding function 'static inline const struct cred *get_cred_rcu(const struct cred *cred);' to $(srctree)/include/linux/cred.h)
|
||||
GET_CRED_RCU = static inline const struct cred *get_cred_rcu(const struct cred *cred)\n\
|
||||
{\n\t\
|
||||
struct cred *nonconst_cred = (struct cred *) cred;\n\t\
|
||||
if (!cred)\n\t\t\
|
||||
return NULL;\n\t\
|
||||
if (!$(ATOMIC_INC_FUNC)(&nonconst_cred->usage))\n\t\t\
|
||||
return NULL;\n\t\
|
||||
validate_creds(cred);\n\t\
|
||||
return cred;\n\
|
||||
}\n
|
||||
$(shell grep -qF "$(GET_CRED_RCU)" $(srctree)/include/linux/cred.h || sed -i '/^static inline void put_cred/i $(GET_CRED_RCU)' $(srctree)/include/linux/cred.h)
|
||||
|
||||
# Modify get_task_cred in cred.c
|
||||
$(info -- KSU_NEXT: modifying 'get_task_cred' function in $(srctree)/kernel/cred.c)
|
||||
$(shell sed -i "s/!$(ATOMIC_INC_FUNC)(&((struct cred \*)cred)->usage)/!get_cred_rcu(cred)/g" $(srctree)/kernel/cred.c)
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
|
||||
$(info -- KSU_NEXT: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
|
||||
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
#include <linux/moduleparam.h>
|
||||
#endif
|
||||
#include <crypto/hash.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
|
||||
#include <crypto/sha2.h>
|
||||
@@ -19,6 +18,8 @@
|
||||
#include "kernel_compat.h"
|
||||
#include "throne_tracker.h"
|
||||
|
||||
static unsigned int expected_manager_size = EXPECTED_MANAGER_SIZE;
|
||||
static char expected_manager_hash[SHA256_DIGEST_SIZE * 2 + 1] = EXPECTED_MANAGER_HASH;
|
||||
|
||||
struct sdesc {
|
||||
struct shash_desc shash;
|
||||
@@ -313,6 +314,53 @@ static struct kernel_param_ops expected_size_ops = {
|
||||
module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
|
||||
&ksu_debug_manager_uid, S_IRUSR | S_IWUSR);
|
||||
|
||||
#else
|
||||
|
||||
static int set_expected_size(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
int rv = param_set_uint(val, kp);
|
||||
pr_info("expected_manager_size set to %u\n", expected_manager_size);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int get_expected_size(char *buf, const struct kernel_param *kp)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", expected_manager_size);
|
||||
}
|
||||
|
||||
static int set_expected_hash(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
if (strlen(val) != SHA256_DIGEST_SIZE * 2) {
|
||||
pr_err("Invalid hash length: %s\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strncpy(expected_manager_hash, val, SHA256_DIGEST_SIZE * 2);
|
||||
expected_manager_hash[SHA256_DIGEST_SIZE * 2] = '\0';
|
||||
|
||||
pr_info("expected_manager_hash set to %s\n", expected_manager_hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_expected_hash(char *buf, const struct kernel_param *kp)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", expected_manager_hash);
|
||||
}
|
||||
|
||||
static struct kernel_param_ops expected_size_ops = {
|
||||
.set = set_expected_size,
|
||||
.get = get_expected_size,
|
||||
};
|
||||
|
||||
static struct kernel_param_ops expected_hash_ops = {
|
||||
.set = set_expected_hash,
|
||||
.get = get_expected_hash,
|
||||
};
|
||||
|
||||
module_param_cb(expected_manager_size, &expected_size_ops, &expected_manager_size, 0644);
|
||||
|
||||
module_param_cb(expected_manager_hash, &expected_hash_ops, &expected_manager_hash, 0644);
|
||||
|
||||
#endif
|
||||
|
||||
bool is_manager_apk(char *path)
|
||||
@@ -333,5 +381,13 @@ bool is_manager_apk(char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
|
||||
// set debug info to print size and hash to kernel log
|
||||
pr_info("%s: expected size: %u, expected hash: %s\n",
|
||||
path, expected_manager_size, expected_manager_hash);
|
||||
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
return check_v2_signature(path, EXPECTED_MANAGER_SIZE, EXPECTED_MANAGER_HASH);
|
||||
#else
|
||||
return check_v2_signature(path, expected_manager_size, expected_manager_hash);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -47,10 +47,6 @@
|
||||
#include "throne_tracker.h"
|
||||
#include "kernel_compat.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_COMPAT_GET_CRED_RCU)
|
||||
#define KSU_GET_CRED_RCU
|
||||
#endif
|
||||
|
||||
static bool ksu_module_mounted = false;
|
||||
|
||||
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
||||
@@ -259,6 +255,34 @@ static void nuke_ext4_sysfs() {
|
||||
path_put(&path);
|
||||
}
|
||||
|
||||
static bool is_system_bin_su(void)
|
||||
{
|
||||
static const char *su_paths[] = {
|
||||
"/system/bin/su",
|
||||
"/vendor/bin/su",
|
||||
"/product/bin/su",
|
||||
"/system_ext/bin/su",
|
||||
"/odm/bin/su",
|
||||
"/system/xbin/su",
|
||||
"/system_ext/xbin/su"
|
||||
};
|
||||
char path_buf[256];
|
||||
char *pathname;
|
||||
int i;
|
||||
|
||||
struct mm_struct *mm = current->mm;
|
||||
if (mm && mm->exe_file) {
|
||||
pathname = d_path(&mm->exe_file->f_path, path_buf, sizeof(path_buf));
|
||||
if (!IS_ERR(pathname)) {
|
||||
for (i = 0; i < ARRAY_SIZE(su_paths); i++) {
|
||||
if (strcmp(pathname, su_paths[i]) == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
@@ -281,10 +305,18 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
bool from_root = 0 == current_uid().val;
|
||||
bool from_manager = is_manager();
|
||||
|
||||
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||
if (!from_root && !from_manager
|
||||
&& !(is_allow_su() && is_system_bin_su())) {
|
||||
// only root or manager can access this interface
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (!from_root && !from_manager) {
|
||||
// only root or manager can access this interface
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
|
||||
@@ -450,6 +482,32 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||
if (arg2 == CMD_ENABLE_SU) {
|
||||
bool enabled = (arg3 != 0);
|
||||
if (enabled == ksu_su_compat_enabled) {
|
||||
pr_info("cmd enable su but no need to change.\n");
|
||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly
|
||||
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
ksu_sucompat_init();
|
||||
} else {
|
||||
ksu_sucompat_exit();
|
||||
}
|
||||
ksu_su_compat_enabled = enabled;
|
||||
|
||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// all other cmds are for 'root manager'
|
||||
if (!from_manager) {
|
||||
return 0;
|
||||
@@ -503,7 +561,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||
if (arg2 == CMD_ENABLE_SU) {
|
||||
bool enabled = (arg3 != 0);
|
||||
if (enabled == ksu_su_compat_enabled) {
|
||||
@@ -527,6 +585,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -173,3 +173,26 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int ksu_access_ok(const void *addr, unsigned long size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
|
||||
return access_ok(addr, size);
|
||||
#else
|
||||
return access_ok(VERIFY_READ, addr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
|
||||
long count)
|
||||
{
|
||||
long ret = ksu_strncpy_from_user_nofault(dst, unsafe_addr, count);
|
||||
if (likely(ret >= 0))
|
||||
return ret;
|
||||
|
||||
// we faulted! fallback to slow path
|
||||
if (unlikely(!ksu_access_ok(unsafe_addr, count)))
|
||||
return -EFAULT;
|
||||
|
||||
return strncpy_from_user(dst, unsafe_addr, count);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
extern long ksu_strncpy_from_user_nofault(char *dst,
|
||||
const void __user *unsafe_addr,
|
||||
long count);
|
||||
extern long ksu_strncpy_from_user_retry(char *dst,
|
||||
const void __user *unsafe_addr,
|
||||
long count);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||
extern struct key *init_session_keyring;
|
||||
|
||||
@@ -58,12 +58,11 @@ static void stop_input_hook();
|
||||
static struct work_struct stop_vfs_read_work;
|
||||
static struct work_struct stop_execve_hook_work;
|
||||
static struct work_struct stop_input_hook_work;
|
||||
#endif
|
||||
|
||||
#else
|
||||
bool ksu_vfs_read_hook __read_mostly = true;
|
||||
bool ksu_execveat_hook __read_mostly = true;
|
||||
bool ksu_input_hook __read_mostly = true;
|
||||
|
||||
#endif
|
||||
|
||||
u32 ksu_devpts_sid;
|
||||
|
||||
@@ -197,12 +196,11 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||
if (p && !IS_ERR(p)) {
|
||||
char first_arg[16];
|
||||
ksu_strncpy_from_user_nofault(
|
||||
ksu_strncpy_from_user_retry(
|
||||
first_arg, p, sizeof(first_arg));
|
||||
pr_info("/system/bin/init first arg: %s\n",
|
||||
first_arg);
|
||||
if (!strcmp(first_arg, "second_stage") ||
|
||||
(argc == 2 && !strcmp(first_arg, ""))) {
|
||||
if (!strcmp(first_arg, "second_stage")) {
|
||||
pr_info("/system/bin/init second_stage executed\n");
|
||||
apply_kernelsu_rules();
|
||||
init_second_stage_executed = true;
|
||||
@@ -223,7 +221,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||
if (p && !IS_ERR(p)) {
|
||||
char first_arg[16];
|
||||
ksu_strncpy_from_user_nofault(
|
||||
ksu_strncpy_from_user_retry(
|
||||
first_arg, p, sizeof(first_arg));
|
||||
pr_info("/init first arg: %s\n", first_arg);
|
||||
if (!strcmp(first_arg, "--second-stage")) {
|
||||
@@ -248,7 +246,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||
}
|
||||
char env[256];
|
||||
// Reading environment variable strings from user space
|
||||
if (ksu_strncpy_from_user_nofault(
|
||||
if (ksu_strncpy_from_user_retry(
|
||||
env, p, sizeof(env)) < 0)
|
||||
continue;
|
||||
// Parsing environment variable names and values
|
||||
@@ -489,10 +487,12 @@ __maybe_unused int ksu_handle_execve_ksud(const char __user *filename_user,
|
||||
struct filename filename_in, *filename_p;
|
||||
char path[32];
|
||||
|
||||
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||
// return early if disabled.
|
||||
if (!ksu_execveat_hook) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!filename_user)
|
||||
return 0;
|
||||
|
||||
@@ -179,23 +179,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
||||
if (unlikely(!filename_user))
|
||||
return 0;
|
||||
|
||||
// nofault variant fails probably due to pagefault_disable
|
||||
// some cpus dont really have that good speculative execution
|
||||
// substitute set_fs, check if pointer is valid
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||
if (!access_ok(VERIFY_READ, *filename_user, sizeof(path)))
|
||||
return 0;
|
||||
#else
|
||||
if (!access_ok(*filename_user, sizeof(path)))
|
||||
return 0;
|
||||
#endif
|
||||
// success = returns number of bytes and should be less than path
|
||||
long len = strncpy_from_user(path, *filename_user, sizeof(path));
|
||||
if (len <= 0 || len > sizeof(path))
|
||||
return 0;
|
||||
|
||||
// strncpy_from_user_nofault does this too
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
memset(path, 0, sizeof(path));
|
||||
ksu_strncpy_from_user_retry(path, *filename_user, sizeof(path));
|
||||
|
||||
if (likely(memcmp(path, su, sizeof(su))))
|
||||
return 0;
|
||||
|
||||
3
manager/.gitignore
vendored
3
manager/.gitignore
vendored
@@ -7,5 +7,4 @@ build
|
||||
captures
|
||||
.cxx
|
||||
local.properties
|
||||
key.jks
|
||||
setup.sh
|
||||
key.jks
|
||||
@@ -16,11 +16,12 @@ object Natives {
|
||||
// 10946: add capabilities
|
||||
// 10977: change groups_count and groups to avoid overflow write
|
||||
// 11071: Fix the issue of failing to set a custom SELinux type.
|
||||
const val MINIMAL_SUPPORTED_KERNEL = 11071
|
||||
// 12797: zygisk query and get manager uid.
|
||||
const val MINIMAL_SUPPORTED_KERNEL = 12797
|
||||
|
||||
// 11640: Support query working mode, LKM or GKI
|
||||
// when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant.
|
||||
const val MINIMAL_SUPPORTED_KERNEL_LKM = 11648
|
||||
const val MINIMAL_SUPPORTED_KERNEL_LKM = 12797
|
||||
|
||||
// 12404: Support disable sucompat mode
|
||||
const val MINIMAL_SUPPORTED_SU_COMPAT = 12404
|
||||
@@ -119,6 +120,9 @@ object Natives {
|
||||
return version < MINIMAL_SUPPORTED_KERNEL
|
||||
}
|
||||
|
||||
val KSU_WORK_DIR = "/data/adb/ksu/"
|
||||
val GLOBAL_NAMESPACE_FILE = KSU_WORK_DIR + ".global_mnt"
|
||||
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Keep
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.rifsxd.ksunext.ui.screen
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
@@ -67,6 +68,9 @@ import com.rifsxd.ksunext.R
|
||||
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
||||
import com.rifsxd.ksunext.ui.component.ConfirmResult
|
||||
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
|
||||
import com.rifsxd.ksunext.ui.theme.ORANGE
|
||||
import com.rifsxd.ksunext.ui.theme.GREEN
|
||||
import com.rifsxd.ksunext.ui.theme.RED
|
||||
import com.rifsxd.ksunext.ui.util.FlashResult
|
||||
import com.rifsxd.ksunext.ui.util.LkmSelection
|
||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||
@@ -80,9 +84,6 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import android.app.Activity
|
||||
|
||||
enum class FlashingStatus {
|
||||
FLASHING,
|
||||
SUCCESS,
|
||||
@@ -408,6 +409,11 @@ private fun TopBar(
|
||||
),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
fontWeight = FontWeight.Black,
|
||||
color = when (status) {
|
||||
FlashingStatus.FLASHING -> ORANGE
|
||||
FlashingStatus.SUCCESS -> GREEN
|
||||
FlashingStatus.FAILED -> RED
|
||||
}
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
|
||||
@@ -650,7 +650,7 @@ private fun InfoCard(autoExpand: Boolean = false) {
|
||||
|
||||
val suSFS = getSuSFS()
|
||||
if (suSFS == "Supported") {
|
||||
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
|
||||
val isSUS_SU = hasSuSFs_SUS_SU() == "Supported"
|
||||
val susSUMode = if (isSUS_SU) {
|
||||
val mode = susfsSUS_SU_Mode()
|
||||
val modeString =
|
||||
|
||||
@@ -150,6 +150,10 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
viewModel.sortZToA = prefs.getBoolean("module_sort_z_to_a", false)
|
||||
viewModel.sortSizeLowToHigh = prefs.getBoolean("module_sort_size_low_to_high", false)
|
||||
viewModel.sortSizeHighToLow = prefs.getBoolean("module_sort_size_high_to_low", false)
|
||||
viewModel.sortEnabledFirst = prefs.getBoolean("module_sort_enabled_first", false)
|
||||
viewModel.sortActionFirst = prefs.getBoolean("module_sort_action_first", false)
|
||||
viewModel.sortWebUiFirst = prefs.getBoolean("module_sort_webui_first", false)
|
||||
|
||||
if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) {
|
||||
viewModel.fetchModuleList()
|
||||
}
|
||||
@@ -233,11 +237,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortActionFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_a_to_z", viewModel.sortAToZ)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
@@ -257,11 +267,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortActionFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_z_to_a", viewModel.sortZToA)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
@@ -281,11 +297,17 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortActionFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_size_low_to_high", viewModel.sortSizeLowToHigh)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
@@ -305,11 +327,104 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortActionFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_size_high_to_low", viewModel.sortSizeHighToLow)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.module_sort_enabled_first))
|
||||
},
|
||||
trailingIcon = {
|
||||
Checkbox(checked = viewModel.sortEnabledFirst, onCheckedChange = null)
|
||||
},
|
||||
onClick = {
|
||||
viewModel.sortEnabledFirst = !viewModel.sortEnabledFirst
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortActionFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_enabled_first", viewModel.sortEnabledFirst)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.module_sort_action_first))
|
||||
},
|
||||
trailingIcon = {
|
||||
Checkbox(checked = viewModel.sortActionFirst, onCheckedChange = null)
|
||||
},
|
||||
onClick = {
|
||||
viewModel.sortActionFirst = !viewModel.sortActionFirst
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortWebUiFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_action_first", viewModel.sortActionFirst)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_webui_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.module_sort_webui_first))
|
||||
},
|
||||
trailingIcon = {
|
||||
Checkbox(checked = viewModel.sortWebUiFirst, onCheckedChange = null)
|
||||
},
|
||||
onClick = {
|
||||
viewModel.sortWebUiFirst = !viewModel.sortWebUiFirst
|
||||
viewModel.sortAToZ = false
|
||||
viewModel.sortZToA = false
|
||||
viewModel.sortSizeLowToHigh = false
|
||||
viewModel.sortSizeHighToLow = false
|
||||
viewModel.sortEnabledFirst = false
|
||||
viewModel.sortActionFirst = false
|
||||
prefs.edit()
|
||||
.putBoolean("module_sort_webui_first", viewModel.sortWebUiFirst)
|
||||
.putBoolean("module_sort_a_to_z", false)
|
||||
.putBoolean("module_sort_z_to_a", false)
|
||||
.putBoolean("module_sort_size_low_to_high", false)
|
||||
.putBoolean("module_sort_size_high_to_low", false)
|
||||
.putBoolean("module_sort_enabled_first", false)
|
||||
.putBoolean("module_sort_action_first", false)
|
||||
.apply()
|
||||
scope.launch {
|
||||
viewModel.fetchModuleList()
|
||||
|
||||
@@ -88,6 +88,8 @@ import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
|
||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||
import com.rifsxd.ksunext.ui.util.getBugreportFile
|
||||
import com.rifsxd.ksunext.ui.util.*
|
||||
import com.rifsxd.ksunext.ui.util.isGlobalNamespaceEnabled
|
||||
import com.rifsxd.ksunext.ui.util.setGlobalNamespaceEnabled
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@@ -101,6 +103,8 @@ import java.time.format.DateTimeFormatter
|
||||
fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
val snackBarHost = LocalSnackbarHost.current
|
||||
var isGlobalNamespaceEnabled by rememberSaveable { mutableStateOf(false) }
|
||||
isGlobalNamespaceEnabled = isGlobalNamespaceEnabled()
|
||||
|
||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||
val ksuVersion = if (isManager) Natives.version else null
|
||||
@@ -196,14 +200,31 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.Engineering,
|
||||
title = stringResource(id = R.string.settings_global_namespace_mode),
|
||||
summary = stringResource(id = R.string.settings_global_namespace_mode_summary),
|
||||
checked = isGlobalNamespaceEnabled,
|
||||
onCheckedChange = {
|
||||
setGlobalNamespaceEnabled(
|
||||
if (isGlobalNamespaceEnabled) {
|
||||
"0"
|
||||
} else {
|
||||
"1"
|
||||
}
|
||||
)
|
||||
isGlobalNamespaceEnabled = it
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
val suSFS = getSuSFS()
|
||||
val isSUS_SU = getSuSFSFeatures()
|
||||
val isSUS_SU = hasSuSFs_SUS_SU() == "Supported"
|
||||
if (suSFS == "Supported") {
|
||||
if (isSUS_SU == "CONFIG_KSU_SUSFS_SUS_SU") {
|
||||
if (isSUS_SU) {
|
||||
var isEnabled by rememberSaveable {
|
||||
mutableStateOf(susfsSUS_SU_Mode() == "2")
|
||||
}
|
||||
|
||||
@@ -12,4 +12,9 @@ val SECONDARY_DARK = Color(0xFFF5BDE6) // Catppuccin Pink
|
||||
val AMOLED_BLACK = Color(0xFF000000) // Pure black for AMOLED
|
||||
|
||||
val DARK_PURPLE = Color(0xFF6E6CB6) // Catppuccin Mauve (dark purple)
|
||||
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)
|
||||
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)
|
||||
|
||||
val GREEN = Color(0xFF4CAF50) // Green
|
||||
val RED = Color(0xFFF44336) // Red
|
||||
val YELLOW = Color(0xFFFFEB3B) // Yellow
|
||||
val ORANGE = Color(0xFFFF9800) // Orange
|
||||
@@ -103,7 +103,10 @@ fun Uri.getFileName(context: Context): String? {
|
||||
|
||||
fun createRootShell(globalMnt: Boolean = false): Shell {
|
||||
Shell.enableVerboseLogging = BuildConfig.DEBUG
|
||||
val builder = Shell.Builder.create()
|
||||
val builder = Shell.Builder.create().apply {
|
||||
setFlags(Shell.FLAG_MOUNT_MASTER)
|
||||
}
|
||||
|
||||
return try {
|
||||
if (globalMnt) {
|
||||
builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
|
||||
@@ -403,6 +406,22 @@ fun hasMagisk(): Boolean {
|
||||
return result.isSuccess
|
||||
}
|
||||
|
||||
fun isGlobalNamespaceEnabled(): Boolean {
|
||||
val shell = getRootShell()
|
||||
val result =
|
||||
ShellUtils.fastCmd(shell, "nsenter --mount=/proc/1/ns/mnt cat ${Natives.GLOBAL_NAMESPACE_FILE}")
|
||||
Log.i(TAG, "is global namespace enabled: $result")
|
||||
return result == "1"
|
||||
}
|
||||
|
||||
fun setGlobalNamespaceEnabled(value: String) {
|
||||
getRootShell().newJob()
|
||||
.add("nsenter --mount=/proc/1/ns/mnt echo $value > ${Natives.GLOBAL_NAMESPACE_FILE}")
|
||||
.submit { result ->
|
||||
Log.i(TAG, "setGlobalNamespaceEnabled result: ${result.isSuccess} [${result.out}]")
|
||||
}
|
||||
}
|
||||
|
||||
fun isSepolicyValid(rules: String?): Boolean {
|
||||
if (rules == null) {
|
||||
return true
|
||||
@@ -591,12 +610,19 @@ fun getSuSFSVariant(): String {
|
||||
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} variant")
|
||||
return result
|
||||
}
|
||||
|
||||
fun getSuSFSFeatures(): String {
|
||||
val shell = getRootShell()
|
||||
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features")
|
||||
return result
|
||||
}
|
||||
|
||||
fun hasSuSFs_SUS_SU(): String {
|
||||
val shell = getRootShell()
|
||||
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su support")
|
||||
return result
|
||||
}
|
||||
|
||||
fun susfsSUS_SU_0(): String {
|
||||
val shell = getRootShell()
|
||||
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su 0")
|
||||
|
||||
@@ -67,9 +67,15 @@ class ModuleViewModel : ViewModel() {
|
||||
var sortZToA by mutableStateOf(false)
|
||||
var sortSizeLowToHigh by mutableStateOf(false)
|
||||
var sortSizeHighToLow by mutableStateOf(false)
|
||||
var sortEnabledFirst by mutableStateOf(false)
|
||||
var sortActionFirst by mutableStateOf(false)
|
||||
var sortWebUiFirst by mutableStateOf(false)
|
||||
|
||||
val moduleList by derivedStateOf {
|
||||
val comparator = when {
|
||||
sortWebUiFirst -> compareByDescending<ModuleInfo> { it.hasWebUi }
|
||||
sortEnabledFirst -> compareByDescending<ModuleInfo> { it.enabled }
|
||||
sortActionFirst -> compareByDescending<ModuleInfo> { it.hasActionScript }
|
||||
sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() }
|
||||
sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() }
|
||||
sortSizeLowToHigh -> compareBy<ModuleInfo> { it.size }
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.rifsxd.ksunext.ui.webui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AppIconUtil {
|
||||
private static final Map<String, Bitmap> iconCache = new HashMap<>();
|
||||
|
||||
public static Bitmap loadAppIconSync(Context context, String packageName, int sizePx) {
|
||||
Bitmap cached = iconCache.get(packageName);
|
||||
if (cached != null) return cached;
|
||||
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
|
||||
Drawable drawable = pm.getApplicationIcon(appInfo);
|
||||
Bitmap raw = drawableToBitmap(drawable, sizePx);
|
||||
Bitmap icon = Bitmap.createScaledBitmap(raw, sizePx, sizePx, true);
|
||||
iconCache.put(packageName, icon);
|
||||
return icon;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap drawableToBitmap(Drawable drawable, int size) {
|
||||
if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap();
|
||||
|
||||
int width = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : size;
|
||||
int height = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : size;
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bmp);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
return bmp;
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,23 @@ class WebUIActivity : ComponentActivity() {
|
||||
view: WebView,
|
||||
request: WebResourceRequest
|
||||
): WebResourceResponse? {
|
||||
return webViewAssetLoader.shouldInterceptRequest(request.url)
|
||||
val url = request.url
|
||||
|
||||
//POC: Handle ksu://icon/[packageName] to serve app icon via WebView
|
||||
if (url.scheme.equals("ksu", ignoreCase = true) && url.host.equals("icon", ignoreCase = true)) {
|
||||
val packageName = url.path?.substring(1)
|
||||
if (!packageName.isNullOrEmpty()) {
|
||||
val icon = AppIconUtil.loadAppIconSync(this@WebUIActivity, packageName, 512)
|
||||
if (icon != null) {
|
||||
val stream = java.io.ByteArrayOutputStream()
|
||||
icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 100, stream)
|
||||
val inputStream = java.io.ByteArrayInputStream(stream.toByteArray())
|
||||
return WebResourceResponse("image/png", null, inputStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return webViewAssetLoader.shouldInterceptRequest(url)
|
||||
}
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
@@ -119,4 +135,4 @@ class WebUIActivity : ComponentActivity() {
|
||||
super.onDestroy()
|
||||
runCatching { rootShell?.close() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,4 +230,9 @@
|
||||
<string name="home_module_count_singular">وحدة</string>
|
||||
<string name="home_module_count_plural">وحدات</string>
|
||||
<string name="module_backup_message">نسخ احتياطي للوحدات المثبتة حالياً.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Модул</string>
|
||||
<string name="home_module_count_plural">Модули</string>
|
||||
<string name="module_backup_message">Архивиране на текущо инсталираните модули.</string>
|
||||
<string name="module_sort_enabled_first">Сортиране (първо активирани)</string>
|
||||
<string name="module_sort_action_first">Сортиране (първо действие)</string>
|
||||
<string name="module_sort_webui_first">Сортиране (първо WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Режим на глобално пространство от имена</string>
|
||||
<string name="settings_global_namespace_mode_summary">Всички сесии на root използват глобалното пространство от имена за монтиране</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Backup currently installed modules.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<string name="issue_report_title">Haben Sie Schwierigkeiten?</string>
|
||||
<string name="issue_report_body">Sind Sie auf einen Fehler gestoßen, oder wollen Sie eine Rückmeldung geben?</string>
|
||||
<string name="issue_report_body_2">Melden Sie es so schnell wie möglich!</string>
|
||||
<string name="issue_report_github">Bericht über GitHub</string>
|
||||
<string name="issue_report_github">Meldung über GitHub</string>
|
||||
<string name="issue_report_telegram">Kontakt über Telegram</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
@@ -12,8 +12,8 @@
|
||||
<string name="home">Hauptseite</string>
|
||||
<string name="home_not_installed">Nicht installiert</string>
|
||||
<string name="home_click_to_install">Klicke zum Installieren</string>
|
||||
<string name="lkm_mode_deprecated">Der LKM -Modus ist jetzt veraltet!</string>
|
||||
<string name="lkm_alternative_suggestion">Installieren Sie den GKI Kernel oder integrieren Sie KernelSU Next in Ihrem Gerät.</string>
|
||||
<string name="lkm_mode_deprecated">Der LKM-Modus ist jetzt veraltet!</string>
|
||||
<string name="lkm_alternative_suggestion">Installieren Sie den GKI-Kernel oder integrieren Sie KernelSU Next in Ihrem Gerät.</string>
|
||||
<string name="home_working">Funktioniert</string>
|
||||
<string name="home_working_version">Version: %d</string>
|
||||
<string name="home_module_update_count">Aktualisierungen: %d</string>
|
||||
@@ -178,7 +178,7 @@
|
||||
<string name="settings_check_update">Nach Aktualisierungen suchen</string>
|
||||
<string name="settings_check_update_summary">Automatische Suche nach Updates beim Öffnen der App</string>
|
||||
<string name="grant_root_failed">Root-Zugriff konnte nicht gewährt werden!</string>
|
||||
<string name="action">Aktivität</string>
|
||||
<string name="action">Aktion</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Öffnen</string>
|
||||
<string name="enable_web_debugging">WebView-Debugging einschalten</string>
|
||||
@@ -222,10 +222,15 @@
|
||||
<string name="developer">Entwickler</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT DEAKTIVIERT</string>
|
||||
<string name="zygisk_required">Zygisk erforderlich</string>
|
||||
<string name="zygisk_status">Zygisk Einbindung</string>
|
||||
<string name="zygisk_status">Zygisk-Einbindung</string>
|
||||
<string name="home_superuser_count_singular">Superuser</string>
|
||||
<string name="home_superuser_count_plural">Superusers</string>
|
||||
<string name="home_module_count_singular">Modul</string>
|
||||
<string name="home_module_count_plural">Module</string>
|
||||
<string name="module_backup_message">Sicherung der aktuell installierten Module.</string>
|
||||
<string name="module_sort_enabled_first">Sortierung (aktivierte zuerst)</string>
|
||||
<string name="module_sort_action_first">Sortierung (Aktion zuerst)</string>
|
||||
<string name="module_sort_webui_first">Sortierung (WebUI zuerst)</string>
|
||||
<string name="settings_global_namespace_mode">Globaler Namensraum-Modus</string>
|
||||
<string name="settings_global_namespace_mode_summary">Alle Root-Sitzungen verwenden den globalen Mount-Namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<string name="home_working">Funcionando</string>
|
||||
<string name="home_working_version">Versión: %d</string>
|
||||
<string name="home_module_update_count">Actualizaciones: %d</string>
|
||||
<string name="home_failure">¡No se encontró la firma de KernelSU Next v2 en el kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure">¡Firma v2 de KernelSU Next no encontrada en el kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">¡Pídele a tu desarrollador de kernel que integre KernelSU Next!</string>
|
||||
<string name="home_kernel">Versión del kernel</string>
|
||||
<string name="hook_mode">Método de intercepción</string>
|
||||
@@ -119,7 +119,7 @@
|
||||
<string name="profile_template">Plantilla</string>
|
||||
<string name="profile_custom">Personalizado</string>
|
||||
<string name="profile_name">Nombre de perfil</string>
|
||||
<string name="profile_namespace">Espacio de nombres de montaje</string>
|
||||
<string name="profile_namespace">Espacio de montaje aislado</string>
|
||||
<string name="profile_namespace_inherited">Heredado</string>
|
||||
<string name="profile_namespace_global">Global</string>
|
||||
<string name="profile_namespace_individual">Individual</string>
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Módulo</string>
|
||||
<string name="home_module_count_plural">Módulos</string>
|
||||
<string name="module_backup_message">Respaldar los módulos actualmente instalados.</string>
|
||||
<string name="module_sort_enabled_first">Ordenar (Activados Primero)</string>
|
||||
<string name="module_sort_action_first">Ordenar (Accionables primero)</string>
|
||||
<string name="module_sort_webui_first">Ordenar (WrbUI primero)</string>
|
||||
<string name="settings_global_namespace_mode">Usar el Espacio de Montaje Aislado Global</string>
|
||||
<string name="settings_global_namespace_mode_summary">Todas las sesiones root usan el espacio de montaje aislado global</string>
|
||||
</resources>
|
||||
|
||||
@@ -229,4 +229,9 @@
|
||||
<string name="home_module_count_singular">ماژول</string>
|
||||
<string name="home_module_count_plural">ماژول ها</string>
|
||||
<string name="module_backup_message">از ماژولهای نصبشدهی فعلی پشتیبان تهیه کنید.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<string name="home_working">En fonctionnement</string>
|
||||
<string name="home_working_version">Version : %d</string>
|
||||
<string name="home_module_update_count">Mises à jour : %d</string>
|
||||
<string name="home_failure">KernelSU La signature v2 suivante est introuvable dans le noyau! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure">La signature suivante de la v2 KernelSU Next est introuvable dans le noyau! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Demandez à votre développeur de noyau d\'intégrer KernelSU Next !</string>
|
||||
<string name="home_kernel">Version du noyau</string>
|
||||
<string name="hook_mode">Méthode d\'interception</string>
|
||||
@@ -230,4 +230,9 @@
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Sauvegarder les modules actuellement installés.</string>
|
||||
<string name="module_sort_enabled_first">Trier (Activé en premier)</string>
|
||||
<string name="module_sort_action_first">Trier (Action en premier)</string>
|
||||
<string name="module_sort_webui_first">Trier (WebUI en premier)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="home_click_to_install">इंस्टॉल करने के लिए क्लिक करें</string>
|
||||
<string name="lkm_mode_deprecated">LKM मोड अब अप्रचलित हो गया है!</string>
|
||||
<string name="lkm_alternative_suggestion">GKI कर्नल अधिष्ठापित करें या KernelSU Next को अपने डिवाइस पर इन्स्टॉल करें।</string>
|
||||
<string name="home_working">कार्य जारी</string>
|
||||
<string name="home_working">काम कर रहा है</string>
|
||||
<string name="home_working_version">वर्जन: %d</string>
|
||||
<string name="home_module_update_count">अपडेट्स: %d</string>
|
||||
<string name="home_failure">KernelSU Next v2 सिग्नेचर कर्नेल में नहीं मिला!
|
||||
@@ -44,10 +44,10 @@
|
||||
<string name="module_empty">कोई मॉड्यूल इंस्टाल नहीं हुआ |</string>
|
||||
<string name="module">मॉड्यूल</string>
|
||||
<string name="module_install_prompt_with_name">निम्नलिखित मॉड्यूल इंस्टाल किए जाएंगे: %1$s</string>
|
||||
<string name="module_sort_a_to_z">सॉर्ट (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">सॉर्ट (Z → A)</string>
|
||||
<string name="module_size_low_to_high">सॉर्ट (Low → High)</string>
|
||||
<string name="module_size_high_to_low">सॉर्ट (High → Low)</string>
|
||||
<string name="module_sort_a_to_z">क्रमबद्ध करें (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">क्रमबद्ध करें (Z → A)</string>
|
||||
<string name="module_size_low_to_high">क्रमबद्ध करें (न्यूनतम → उच्चतम)</string>
|
||||
<string name="module_size_high_to_low">क्रमबद्ध करें (उच्चतम → न्यूनतम)</string>
|
||||
<string name="uninstall">अनइंस्टॉल करें</string>
|
||||
<string name="restore">पहले जैसा करें</string>
|
||||
<string name="module_install">इंस्टॉल करें</string>
|
||||
@@ -90,7 +90,7 @@
|
||||
<string name="use_overlay_fs">OverlayFS का उपयोग करें</string>
|
||||
<string name="use_overlay_fs_summary">Toggle between using OverlayFS over Magic Mount for KernelSU Next\'s mount system.</string>
|
||||
<string name="reboot_required">रिबूट करना जरूरी है!</string>
|
||||
<string name="reboot_message">The changes will take effect after the system restart. Do you want to reboot now?</string>
|
||||
<string name="reboot_message">सिस्टम रीस्टार्ट के बाद यह परिवर्तन प्रभावी होगा। क्या आप अभी रीबूट करना चाहते हैं?</string>
|
||||
<string name="module_restore">Restore module</string>
|
||||
<string name="module_restore_message">Restore modules from recent backup.</string>
|
||||
<string name="backup_restore">बैकअप & रिस्टोर</string>
|
||||
@@ -108,7 +108,7 @@
|
||||
<string name="home_next_kernelsu">🔥 Next build</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ Experimental development warning!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ प्रायोगिक विकास की चेतावनी!</string>
|
||||
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||
<string name="home_experimental_kernelsu_body">KernelSU Next एक गैर-आधिकारिक संस्करण है जो हमेशा सक्रिय प्रयोगात्मक विकास के अंतर्गत रहता है। इसे वैसे ही उपलब्ध कराया जाता है, जिसमें स्थिरता, प्रदर्शन या विश्वसनीयता की कोई गारंटी नहीं होती।</string>
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • अपने जोखिम पर उपयोग करें: क्रैश, अप्रत्याशित व्यवहार या सिस्टम समस्याएं हो सकती हैं।</string>
|
||||
@@ -126,13 +126,14 @@
|
||||
<string name="profile_namespace_individual">विशिष्ट</string>
|
||||
<string name="profile_groups">ग्रुप्स</string>
|
||||
<string name="profile_capabilities">क्षमताएं</string>
|
||||
<string name="profile_selinux_context">SELinux context</string>
|
||||
<string name="profile_selinux_context">SELinux कॉन्टेक्स्ट</string>
|
||||
<string name="profile_umount_modules">मॉड्यूल्स यूमाउंट करें</string>
|
||||
<string name="failed_to_update_app_profile">%s के लिए ऐप प्रोफ़ाइल अपडेट करने में विफल</string>
|
||||
<string name="require_kernel_version">मैनेजर के ठीक से काम करने के लिए वर्तमान KernelSU Next वर्जन %1$d बहुत कम है। कृपया वर्जन %2$d या उच्चतर में अपग्रेड करें!</string>
|
||||
<string name="settings_umount_modules_default">मॉड्यूल्स यूमाउंट करें</string>
|
||||
<string name="settings_umount_modules_default_summary">ऐप प्रोफाइल में \"अनमाउंट मॉड्यूल\" के लिए ग्लोबल डिफ़ॉल्ट वैल्यू। यदि चालू किया गया है, तो यह एप्लीकेशंस के लिऐ सिस्टम के सभी मॉड्यूल मोडिफिकेशन को हटा देगा जिनकी प्रोफ़ाइल सेट नहीं है।</string>
|
||||
<string name="settings_susfs_toggle">Hide kprobes hook</string>
|
||||
<string name="settings_susfs_toggle">Kprobes हुक को छिपाएं
|
||||
</string>
|
||||
<string name="settings_susfs_toggle_summary">यह विकल्प KSU द्वारा निर्मित kprobes हुक को निष्क्रिय कर देता है, तथा इसके स्थान पर एम्बेडेड non-kprobes हुक को सक्रिय कर देता है, तथा उसी कार्यक्षमता को क्रियान्वित करता है जो non-GKI कर्नल पर लागू होती है, जो kprobe का समर्थन नहीं करता है।</string>
|
||||
<string name="profile_umount_modules_summary">इस विकल्प को चालू करने से KernelSU Next इस एप्लिकेशन के लिए मॉड्यूल द्वारा किसी भी मोडिफाइड फ़ाइल को रिस्टोर कर सकता है।</string>
|
||||
<string name="profile_selinux_domain">डोमेन</string>
|
||||
@@ -147,67 +148,67 @@
|
||||
<string name="close">बंद</string>
|
||||
<string name="force_stop_app">ज़बरदस्ती रोकें</string>
|
||||
<string name="restart_app">रिस्टार्ट करें</string>
|
||||
<string name="settings_amoled_mode">AMOLED mode</string>
|
||||
<string name="settings_amoled_mode">AMOLED मोड</string>
|
||||
<string name="settings_amoled_mode_summary">आंखों पर पड़ने वाले तनाव को कम करने और बैटरी बचाने के लिए AMOLED स्क्रीन के लिए उपयोगी काले रंग की थीम को सक्षम करें।</string>
|
||||
<string name="restart_required">पुनः आरंभ की आवश्यकता है</string>
|
||||
<string name="restart_app_message">The app needs to restart for this change to take effect.</string>
|
||||
<string name="restart_app_message">इस बदलाव के लिए ऐप को दोबारा शुरू करना होगा।</string>
|
||||
<string name="failed_to_update_sepolicy">%s के लिए SELinux नियमों को अपटेड करने में विफल</string>
|
||||
<string name="su_not_allowed">%s को सुपरयूज़र एक्सेस नहीं दिया जा सका</string>
|
||||
<string name="module_changelog">चेंजलॉग</string>
|
||||
<string name="settings_profile_template">App Profile template</string>
|
||||
<string name="settings_profile_template_summary">Manage local and online template of App Profile</string>
|
||||
<string name="settings_profile_template">ऐप प्रोफ़ाइल नमूना</string>
|
||||
<string name="settings_profile_template_summary">ऐप प्रोफ़ाइल के स्थानीय और ऑनलाइन नमूनों का प्रबंधन करें</string>
|
||||
<string name="app_profile_template_create">नया टेम्प्लेट बनाएं</string>
|
||||
<string name="app_profile_template_edit">टेम्पलेट एडिट करें</string>
|
||||
<string name="app_profile_template_id">आइडी</string>
|
||||
<string name="app_profile_template_id_invalid">Invalid template ID</string>
|
||||
<string name="app_profile_template_id_invalid">अमान्य नमूना ID</string>
|
||||
<string name="app_profile_template_name">नाम</string>
|
||||
<string name="app_profile_template_description">विवरण</string>
|
||||
<string name="app_profile_template_save">सेव</string>
|
||||
<string name="app_profile_template_delete">डिलीट</string>
|
||||
<string name="app_profile_template_view">View template</string>
|
||||
<string name="app_profile_template_view">नमूना देखें</string>
|
||||
<string name="app_profile_template_readonly">केवल पढ़ने के लिए</string>
|
||||
<string name="app_profile_template_id_exist">Template ID already exists!</string>
|
||||
<string name="app_profile_template_id_exist">नमूना ID पहले से मौजूद है!</string>
|
||||
<string name="app_profile_import_export">आयात/निर्यात</string>
|
||||
<string name="app_profile_import_from_clipboard">क्लिपबोर्ड से इम्पोर्ट करें</string>
|
||||
<string name="app_profile_export_to_clipboard">क्लिपबोर्ड को निर्यात करें</string>
|
||||
<string name="app_profile_template_export_empty">Cannot find local template to export!</string>
|
||||
<string name="app_profile_template_export_empty">एक्सपोर्ट करने के लिए कोई स्थानीय नमूना नहीं मिला!</string>
|
||||
<string name="app_profile_template_import_success">सफलतापूर्वक आयात किया गया</string>
|
||||
<string name="app_profile_template_sync">Sync online templates</string>
|
||||
<string name="app_profile_template_save_failed">Failed to save template</string>
|
||||
<string name="app_profile_template_sync">ऑनलाइन नमूने सिंक करें</string>
|
||||
<string name="app_profile_template_save_failed">नमूना सहेजने में विफल रहा</string>
|
||||
<string name="app_profile_template_import_empty">क्लिपबोर्ड खाली है!</string>
|
||||
<string name="module_changelog_failed">Fetch changelog failed: %s</string>
|
||||
<string name="settings_check_update">अपडेट के लिए चेक करें</string>
|
||||
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
|
||||
<string name="grant_root_failed">Failed to grant root!</string>
|
||||
<string name="settings_check_update_summary">ऐप खोलने पर अपने आप अपडेट जांचें</string>
|
||||
<string name="grant_root_failed">रूट एक्सेस देने में विफल!</string>
|
||||
<string name="action">एक्शन</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">खोलें</string>
|
||||
<string name="enable_web_debugging">Enable WebView debugging</string>
|
||||
<string name="enable_web_debugging"></string>
|
||||
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
|
||||
<string name="direct_install">Direct install (Recommended)</string>
|
||||
<string name="direct_install">सीधा इंस्टॉल करें (सिफारिश की जाती है)</string>
|
||||
<string name="select_file">फाइल चुनें</string>
|
||||
<string name="install_inactive_slot">Install to inactive slot (After OTA)</string>
|
||||
<string name="install_inactive_slot">निष्क्रिय स्लॉट में इंस्टॉल करें (OTA के बाद)</string>
|
||||
<string name="install_inactive_slot_warning">Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue?</string>
|
||||
<string name="install_next">अगला</string>
|
||||
<string name="select_file_tip">%1$s partition image is recommended</string>
|
||||
<string name="select_kmi">Select KMI</string>
|
||||
<string name="select_file_tip">%1$s partition image की सिफारिश की जाती है</string>
|
||||
<string name="select_kmi">KMI चुनें</string>
|
||||
<string name="shrink_sparse_image">Minimize sparse image</string>
|
||||
<string name="shrink_sparse_image_message">Resize the sparse image where the module is located to its actual size. Note that this may cause the module to work abnormally, so please only use when necessary (Such as for backup).</string>
|
||||
<string name="settings_uninstall">अनइंस्टॉल करें</string>
|
||||
<string name="settings_uninstall_temporary">Uninstall temporarily</string>
|
||||
<string name="settings_uninstall_permanent">Uninstall permanently</string>
|
||||
<string name="settings_uninstall_temporary">कुछ समय के लिए हटाएं</string>
|
||||
<string name="settings_uninstall_permanent">हमेशा के लिए हटाएं</string>
|
||||
<string name="settings_restore_stock_image">Restore stock image</string>
|
||||
<string name="settings_uninstall_temporary_message">Temporarily uninstall KernelSU Next, restore to original state after next reboot.</string>
|
||||
<string name="settings_uninstall_permanent_message">Uninstalling KernelSU Next (Root and all modules) completely and permanently.</string>
|
||||
<string name="settings_uninstall_temporary_message">KernelSU Next को अभी के लिए हटाया जाएगा, अगली बार डिवाइस चालू होने पर यह वापस आ जाएगा।</string>
|
||||
<string name="settings_uninstall_permanent_message">KernelSU Next को रूट और सभी मॉड्यूल के साथ पूरी तरह से हमेशा के लिए हटाया जा रहा है।</string>
|
||||
<string name="settings_restore_stock_image_message">Restore the stock factory image (If a backup exists), usually used before OTA; if you need to uninstall KernelSU Next, please use \"Uninstall permanently\".</string>
|
||||
<string name="flashing">फ़्लैश हो रहा है</string>
|
||||
<string name="flash_success">Flash success</string>
|
||||
<string name="flash_failed">Flash failed</string>
|
||||
<string name="selected_lkm">Selected LKM: %s</string>
|
||||
<string name="flash_success">फ्लैश सफल रहा</string>
|
||||
<string name="flash_failed">फ्लैश असफल रहा</string>
|
||||
<string name="selected_lkm">चुना गया LKM: %s</string>
|
||||
<string name="save_log">लॉग सहेजें</string>
|
||||
<string name="log_saved">Logs saved</string>
|
||||
<string name="send_log">लॉग शेयर करें</string>
|
||||
<string name="settings_disable_su">Disable su compatibility</string>
|
||||
<string name="settings_disable_su">SU compatibility अस्थायी रूप से बंद करें</string>
|
||||
<string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (Existing root processes won\'t be affected).</string>
|
||||
<string name="settings_language">भाषा</string>
|
||||
<string name="system_default">सिस्टम डिफ़ॉल्ट</string>
|
||||
@@ -215,7 +216,7 @@
|
||||
<string name="settings_legacyui_summary">Switch to the previous user interface style.</string>
|
||||
<string name="settings_banner">Enable banners</string>
|
||||
<string name="settings_banner_summary">Show background banners for modules.</string>
|
||||
<string name="use_webuix">Use WebUI X</string>
|
||||
<string name="use_webuix">WebUI X का उपयोग करें</string>
|
||||
<string name="use_webuix_summary">WebUI के बजाय WebUI X का उपयोग करें, जो अधिक API का समर्थन करता है।</string>
|
||||
<string name="use_webuix_eruda">Eruda को WebUI X में इंजेक्ट करें</string>
|
||||
<string name="use_webuix_eruda_summary">डीबगिंग को आसान बनाने के लिए WebUI X में डीबग कंसोल इंजेक्ट करें। वेब डीबगिंग चालू होना आवश्यक है।</string>
|
||||
@@ -223,10 +224,15 @@
|
||||
<string name="developer">डेवलपर</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT DISABLED</string>
|
||||
<string name="zygisk_required">Zygisk आवश्यक है!</string>
|
||||
<string name="zygisk_status">Zygisk injection</string>
|
||||
<string name="zygisk_status">Zygisk इंजेक्शन</string>
|
||||
<string name="home_superuser_count_singular">सुपरयूजर</string>
|
||||
<string name="home_superuser_count_plural">सुपरयूजरस</string>
|
||||
<string name="home_module_count_singular">मॉड्यूल</string>
|
||||
<string name="home_module_count_plural">मॉड्यूलस</string>
|
||||
<string name="module_backup_message">Backup currently installed modules.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Backup currently installed modules.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="issue_report_title">Ada kendala?</string>
|
||||
<string name="issue_report_body">Menemukan bug atau memiliki umpan balik?</string>
|
||||
<string name="issue_report_body_2">Laporkan sesegera mungkin!</string>
|
||||
<string name="issue_report_title">Memiliki kendala?</string>
|
||||
<string name="issue_report_body">Mengalami kesalahan atau memiliki umpan balik?</string>
|
||||
<string name="issue_report_body_2">Laporkan secepatnya!</string>
|
||||
<string name="issue_report_github">Laporkan di GitHub</string>
|
||||
<string name="issue_report_telegram">Hubungi melalui Telegram</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">Konfirmasi</string>
|
||||
<string name="confirm">Ya</string>
|
||||
<string name="app_name">KernelSU Next</string>
|
||||
<string name="home">Beranda</string>
|
||||
<string name="home_not_installed">Tidak terpasang</string>
|
||||
<string name="home_click_to_install">Klik untuk memasang</string>
|
||||
<string name="home_not_installed">Tidak terinstal</string>
|
||||
<string name="home_click_to_install">Klik untuk menginstal</string>
|
||||
<string name="lkm_mode_deprecated">Mode LKM sekarang sudah tidak digunakan lagi!</string>
|
||||
<string name="lkm_alternative_suggestion">Pasang kernel GKI atau integrasikan KernelSU Next ke perangkat anda.</string>
|
||||
<string name="home_working">Berfungsi</string>
|
||||
@@ -30,9 +30,9 @@
|
||||
<string name="home_susfs_version">Versi SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Versi android</string>
|
||||
<string name="home_manager_version">Versi manager</string>
|
||||
<string name="home_manager_version">Versi manajer</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">Status SElinux</string>
|
||||
<string name="home_selinux_status">SELinux status</string>
|
||||
<string name="selinux_status_disabled">Nonaktif</string>
|
||||
<string name="selinux_status_enforcing">Enforcing</string>
|
||||
<string name="selinux_status_permissive">Permissive</string>
|
||||
@@ -42,7 +42,7 @@
|
||||
<string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string>
|
||||
<string name="module_empty">Tidak ada modul yang terpasang</string>
|
||||
<string name="module">Modul</string>
|
||||
<string name="module_install_prompt_with_name">Modul berikut akan dipasang: %1$s</string>
|
||||
<string name="module_install_prompt_with_name">Modul yang akan diinstal: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Urutkan (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Urutkan (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Urutkan (Kecil → Besar)</string>
|
||||
@@ -229,4 +229,9 @@
|
||||
<string name="home_module_count_singular">Modul</string>
|
||||
<string name="home_module_count_plural">Modul</string>
|
||||
<string name="module_backup_message">Cadangkan modul yang terinstal saat ini.</string>
|
||||
<string name="module_sort_enabled_first">Urutkan (Diaktifkan lebih dulu)</string>
|
||||
<string name="module_sort_action_first">Urutkan (Aksi lebih dulu)</string>
|
||||
<string name="module_sort_webui_first">Urutkan (WebUI lebih dulu)</string>
|
||||
<string name="settings_global_namespace_mode">Mode Namespace Universal</string>
|
||||
<string name="settings_global_namespace_mode_summary">Semua sesi root menggunakan mount namespace universal</string>
|
||||
</resources>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">Conferma</string>
|
||||
<string name="app_name">KernelSU Next</string>
|
||||
<string name="home">Casa</string>
|
||||
<string name="home">Home</string>
|
||||
<string name="home_not_installed">Non installato</string>
|
||||
<string name="home_click_to_install">Clicca per installare</string>
|
||||
<string name="lkm_mode_deprecated">La modalità LKM è ora obsoleta!</string>
|
||||
@@ -17,10 +17,10 @@
|
||||
<string name="home_working">In esecuzione</string>
|
||||
<string name="home_working_version">Versione: %d</string>
|
||||
<string name="home_module_update_count">Aggiornamenti: %d</string>
|
||||
<string name="home_failure">KernelSU Next firma v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure">Firma v2 di KernelSU Next non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel d\'integrare KernelSU Next!</string>
|
||||
<string name="home_kernel">Versione kernel</string>
|
||||
<string name="hook_mode">Modalità Hook</string>
|
||||
<string name="hook_mode">Modalità hook</string>
|
||||
<string name="enable">Abilita</string>
|
||||
<string name="disable">Disabilita</string>
|
||||
<string name="enabled">Abilitato</string>
|
||||
@@ -30,14 +30,14 @@
|
||||
<string name="home_susfs_version">Versione SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Versione Android</string>
|
||||
<string name="home_manager_version">Versione Manager</string>
|
||||
<string name="home_manager_version">Versione manager</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">Stato SELinux</string>
|
||||
<string name="selinux_status_disabled">Disabilitato</string>
|
||||
<string name="selinux_status_enforcing">Enforcing</string>
|
||||
<string name="selinux_status_permissive">Permissive</string>
|
||||
<string name="selinux_status_unknown">Sconosciuto</string>
|
||||
<string name="superuser">Superutente</string>
|
||||
<string name="superuser">Accesso root</string>
|
||||
<string name="module_failed_to_enable">Impossibile abilitare il modulo: %s</string>
|
||||
<string name="module_failed_to_disable">Impossibile disabilitare il modulo: %s</string>
|
||||
<string name="module_empty">Nessun modulo installato</string>
|
||||
@@ -103,7 +103,7 @@
|
||||
<string name="proceed">Procedi</string>
|
||||
<string name="cancel">Annulla</string>
|
||||
<string name="later">Più tardi</string>
|
||||
<string name="lkm_warning_message">La patch LKM si basa su codici vuoi continuare?</string>
|
||||
<string name="lkm_warning_message">La patch LKM si basa su componenti closed source. Vuoi continuare?</string>
|
||||
<string name="home_next_kernelsu">🔥 Prossima build</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Prossimo branch sperimentale. Provalo su GitHub!</string>
|
||||
@@ -176,8 +176,8 @@
|
||||
<string name="app_profile_template_import_empty">Gli appunti sono vuoti!</string>
|
||||
<string name="module_changelog_failed">Recupero del changelog non riuscito: %s</string>
|
||||
<string name="settings_check_update">Controlla aggiornamenti</string>
|
||||
<string name="settings_check_update_summary">Cerca automaticamente gli aggiornamenti all\'apertura dell\'applicazione.</string>
|
||||
<string name="grant_root_failed">Impossibile concedere i permessi root! </string>
|
||||
<string name="settings_check_update_summary">Cerca automaticamente gli aggiornamenti all\'apertura dell\'applicazione</string>
|
||||
<string name="grant_root_failed">Impossibile concedere i permessi root!</string>
|
||||
<string name="action">Azione</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Apri</string>
|
||||
@@ -187,7 +187,7 @@
|
||||
<string name="select_file">Seleziona un file</string>
|
||||
<string name="install_inactive_slot">Installa nello slot inattivo (dopo un aggiornamento OTA)</string>
|
||||
<string name="install_inactive_slot_warning">Dopo il riavvio, il dispositivo sarà FORZATO ad avviarsi nello slot attualmente inattivo!\nUtilizza questa opzione solo dopo aver completato l\'aggiornamento OTA.\nVuoi continuare?</string>
|
||||
<string name="install_next"></string>
|
||||
<string name="install_next">Next</string>
|
||||
<string name="select_file_tip">Immagine partizione %1$s consigliata</string>
|
||||
<string name="select_kmi">Seleziona KMI</string>
|
||||
<string name="shrink_sparse_image">Minimizza l\'immagine sparsa</string>
|
||||
@@ -207,7 +207,7 @@
|
||||
<string name="log_saved">Log salvati</string>
|
||||
<string name="send_log">Condividi i log</string>
|
||||
<string name="settings_disable_su">Disattiva la compatibilità su</string>
|
||||
<string name="settings_disable_su_summary">Disattiva temporaneamente la capacità di ogni applicazione di ottenere i permessi di root tramite il comando su (le sessioni di root esistenti non subiranno modifiche).</string>
|
||||
<string name="settings_disable_su_summary">Disattiva temporaneamente la capacità di ogni applicazione di ottenere i permessi root tramite il comando su (le sessioni di root esistenti non subiranno modifiche).</string>
|
||||
<string name="settings_language">Lingua</string>
|
||||
<string name="system_default">Default di sistema</string>
|
||||
<string name="settings_legacyui">Usa lo stile d\'interfaccia precedente</string>
|
||||
@@ -223,9 +223,14 @@
|
||||
<string name="sucompat_disabled">SUCOMPAT DISABILITATO</string>
|
||||
<string name="zygisk_required">Zygisk richiesto</string>
|
||||
<string name="zygisk_status">Iniezione Zygisk</string>
|
||||
<string name="home_superuser_count_singular">Superutente</string>
|
||||
<string name="home_superuser_count_plural">Superutenti</string>
|
||||
<string name="home_superuser_count_singular">Accesso root</string>
|
||||
<string name="home_superuser_count_plural">Accessi root</string>
|
||||
<string name="home_module_count_singular">Modulo</string>
|
||||
<string name="home_module_count_plural">Moduli</string>
|
||||
<string name="module_backup_message">Esegue il backup dei moduli attualmente esistenti.</string>
|
||||
<string name="module_sort_enabled_first">Ordina (prima Abilitato)</string>
|
||||
<string name="module_sort_action_first">Ordina (prima Azione)</string>
|
||||
<string name="module_sort_webui_first">Ordina (prima WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Modalità Namespace globale</string>
|
||||
<string name="settings_global_namespace_mode_summary">Tutte le sessioni root usano lo spazio di montaggio globale</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">モジュール</string>
|
||||
<string name="home_module_count_plural">モジュール</string>
|
||||
<string name="module_backup_message">現在インストールされているモジュールをバックアップします。</string>
|
||||
<string name="module_sort_enabled_first">並べ替え (有効を優先)</string>
|
||||
<string name="module_sort_action_first">並べ替え (実行可能を優先)</string>
|
||||
<string name="module_sort_webui_first">並べ替え (WebUIを優先)</string>
|
||||
<string name="settings_global_namespace_mode">グローバル名前空間モード</string>
|
||||
<string name="settings_global_namespace_mode_summary">すべての root セッションがグローバルマウント名前空間を使用します</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">모듈</string>
|
||||
<string name="home_module_count_plural">모듈</string>
|
||||
<string name="module_backup_message">현재 설치된 모듈을 백업</string>
|
||||
<string name="module_sort_enabled_first">정렬 (활성화됨 우선)</string>
|
||||
<string name="module_sort_action_first">정렬 (동작 우선)</string>
|
||||
<string name="module_sort_webui_first">정렬 (WebUI 우선)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
<string name="module_install_prompt_with_name">Następujące moduły zostaną zainstalowane: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Sortuj (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Sortuj (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Sortuj (Najmniejszy → Największy)</string>
|
||||
<string name="module_size_high_to_low">Sortuj (Największy → Najmniejszy)</string>
|
||||
<string name="module_size_low_to_high">Sortuj (Małe → Duże)</string>
|
||||
<string name="module_size_high_to_low">Sortuj (Duże → Małe)</string>
|
||||
<string name="uninstall">Odinstaluj</string>
|
||||
<string name="restore">Przywróć</string>
|
||||
<string name="module_install">Zainstaluj</string>
|
||||
@@ -216,16 +216,21 @@
|
||||
<string name="settings_banner_summary">Wyświetlaj banery modułów w tle.</string>
|
||||
<string name="use_webuix">Używaj WebUI X</string>
|
||||
<string name="use_webuix_summary">Używaj WebUI X zamiast WebUI, który obsługuje więcej interfejsów API.</string>
|
||||
<string name="use_webuix_eruda">Wstrzyknij Eruda do WebUI X</string>
|
||||
<string name="use_webuix_eruda">Wstrzykiwanie Eruda do WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Wstrzyknij konsolę debugowania do WebUI X, aby ułatwić debugowanie. Wymagane jest aktywne debugowanie WebView.</string>
|
||||
<string name="customization">Personalizacja</string>
|
||||
<string name="developer">Programista</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT NIEAKTYWNY</string>
|
||||
<string name="zygisk_required">Wymagany Zygisk</string>
|
||||
<string name="zygisk_status">Wstrzyknięcie Zygisk</string>
|
||||
<string name="zygisk_status">Wstrzykiwanie Zygisk</string>
|
||||
<string name="home_superuser_count_singular">Superuser</string>
|
||||
<string name="home_superuser_count_plural">Superuserzy</string>
|
||||
<string name="home_module_count_singular">Moduł</string>
|
||||
<string name="home_module_count_plural">Moduły</string>
|
||||
<string name="module_backup_message">Utwórz kopię zapasową obecnie zainstalowanych modułów.</string>
|
||||
<string name="module_sort_enabled_first">Sortuj (najpierw włączone)</string>
|
||||
<string name="module_sort_action_first">Sortuj (najpierw z Akcją)</string>
|
||||
<string name="module_sort_webui_first">Sortuj (najpierw z WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Tryb globalnej przestrzeni nazw</string>
|
||||
<string name="settings_global_namespace_mode_summary">Wszystkie sesje roota używają globalnej przestrzeni nazw montowania</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,157 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="issue_report_title">Está com problema?</string>
|
||||
<string name="issue_report_body">Encontrou algum bug ou tem algum feedback?</string>
|
||||
<string name="issue_report_body_2">Relate o mais rápido possível</string>
|
||||
<string name="issue_report_github">Enviei um relatório no Github</string>
|
||||
<string name="issue_report_telegram">Contato via telegram</string>
|
||||
<string name="issue_report_title">Precisa de ajuda?</string>
|
||||
<string name="issue_report_body">Encontrou uma falha ou tem alguma sugestão?</string>
|
||||
<string name="issue_report_body_2">Reporte o mais rápido possível!</string>
|
||||
<string name="issue_report_github">Reportar no GitHub</string>
|
||||
<string name="issue_report_telegram">Contato via Telegram</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="app_name">KernelSU Next</string>
|
||||
<string name="home">Início</string>
|
||||
<string name="home">KSU</string>
|
||||
<string name="home_not_installed">Não instalado</string>
|
||||
<string name="home_click_to_install">Clique para instalar</string>
|
||||
<string name="lkm_mode_deprecated">O modo LKM está agora obsoleto!</string>
|
||||
<string name="lkm_mode_deprecated">O modo LKM agora está obsoleto!</string>
|
||||
<string name="lkm_alternative_suggestion">Instale o kernel GKI ou integre o KernelSU Next ao seu dispositivo.</string>
|
||||
<string name="home_working">Rodando</string>
|
||||
<string name="home_working_version">Versão</string>
|
||||
<string name="home_module_update_count">Atualizações</string>
|
||||
<string name="home_failure">Assinatura do KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || tamanho/hash diferente ]</string>
|
||||
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next! </string>
|
||||
<string name="home_working">Em execução</string>
|
||||
<string name="home_working_version">Versão: %d</string>
|
||||
<string name="home_module_update_count">Atualizações: %d</string>
|
||||
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [!KSU_NEXT || != size/hash]</string>
|
||||
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
|
||||
<string name="home_kernel">Versão do kernel</string>
|
||||
<string name="hook_mode">Modo hook</string>
|
||||
<string name="enable">Habilitar</string>
|
||||
<string name="disable">Desabilitado</string>
|
||||
<string name="enabled">Habilitado </string>
|
||||
<string name="disabled">Desabilitando</string>
|
||||
<string name="hook_mode">Modo do hook</string>
|
||||
<string name="enable">Ativar</string>
|
||||
<string name="disable">Desativar</string>
|
||||
<string name="enabled">Ativado</string>
|
||||
<string name="disabled">Desativado</string>
|
||||
<string name="susfs_supported">Suportado</string>
|
||||
<string name="home_susfs">SuSFS</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">Versão do SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Versão do Android</string>
|
||||
<string name="home_manager_version">Versão do gerenciador</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">SELinux status</string>
|
||||
<string name="selinux_status_disabled">Desabilitado</string>
|
||||
<string name="home_selinux_status">Status do SELinux</string>
|
||||
<string name="selinux_status_disabled">Desativado</string>
|
||||
<string name="selinux_status_enforcing">Impondo</string>
|
||||
<string name="selinux_status_permissive">Permissivo</string>
|
||||
<string name="selinux_status_unknown">Desconhecido</string>
|
||||
<string name="superuser">Superusuário</string>
|
||||
<string name="module_failed_to_enable">Falha a o habilitar modulo</string>
|
||||
<string name="module_failed_to_disable">Falha a o desabilitar modulo</string>
|
||||
<string name="module_empty">Nenhum modulo instalado</string>
|
||||
<string name="module">Mudulo</string>
|
||||
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalado</string>
|
||||
<string name="superuser">SuperUsuário</string>
|
||||
<string name="module_failed_to_enable">Não foi possível ativar o módulo %s</string>
|
||||
<string name="module_failed_to_disable">Não foi possível desativar o módulo %s</string>
|
||||
<string name="module_empty">Nenhum módulo instalado</string>
|
||||
<string name="module">Módulos</string>
|
||||
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalados: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Ordenar (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Ordenar (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Ordenar (baixo → cima)</string>
|
||||
<string name="module_size_high_to_low">Ordenar (Cima → baixo)</string>
|
||||
<string name="module_sort_z_to_a">Organizar (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Organizar (Menor → Maior)</string>
|
||||
<string name="module_size_high_to_low">Ordenar (Maior → Menor)</string>
|
||||
<string name="uninstall">Desinstalar</string>
|
||||
<string name="restore">Restaurar</string>
|
||||
<string name="module_install">Desinstalar</string>
|
||||
<string name="module_install">Instalar</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="uninstalled">Desinstalado</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="settings">Ajustes</string>
|
||||
<string name="reboot_userspace">Reiniciar</string>
|
||||
<string name="reboot_recovery">Reiniciar em modo recovery</string>
|
||||
<string name="reboot_bootloader">Reiniciar em modo bootloader</string>
|
||||
<string name="reboot_download">Reiniciar em modo download</string>
|
||||
<string name="reboot_recovery">Reiniciar em modo Recovery</string>
|
||||
<string name="reboot_bootloader">Reiniciar em modo Bootloader</string>
|
||||
<string name="reboot_download">Reiniciar em modo Download</string>
|
||||
<string name="reboot_edl">Reiniciar em modo EDL</string>
|
||||
<string name="about">Sobre</string>
|
||||
<string name="module_uninstall_confirm">Tem certeza que deseja desinstalar o módulo?</string>
|
||||
<string name="module_uninstall_success">Desinstalado</string>
|
||||
<string name="module_uninstall_failed">Falha a o desinstalar</string>
|
||||
<string name="module_restore_confirm">Tem certeza que deseja restaurar o módulo?</string>
|
||||
<string name="module_restore_success">Restaurado</string>
|
||||
<string name="module_restore_failed">Falha ao restaurar</string>
|
||||
<string name="module_uninstall_confirm">Tem certeza que deseja desinstalar o módulo %s?</string>
|
||||
<string name="module_uninstall_success">%s desinstalado</string>
|
||||
<string name="module_uninstall_failed">Falha ao desinstalar %s</string>
|
||||
<string name="module_restore_confirm">Tem certeza que deseja restaurar o módulo %s?</string>
|
||||
<string name="module_restore_success">%s restaurado</string>
|
||||
<string name="module_restore_failed">Falha ao restaurar %s</string>
|
||||
<string name="module_version">Versão</string>
|
||||
<string name="module_author">Autor</string>
|
||||
<string name="module_id">ID</string>
|
||||
<string name="module_version_code">Código</string>
|
||||
<string name="module_update_json">AtualizarJson</string>
|
||||
<string name="module_update_json">UpdateJson</string>
|
||||
<string name="module_update_json_empty">Vazio</string>
|
||||
<string name="enable_developer_options">Habilitar opções do desenvolvedor</string>
|
||||
<string name="enable_developer_options_summary">Mostrar configurações ocultas e informações de debug relevantes apena para desenvolvedores.</string>
|
||||
<string name="module_overlay_fs_not_available">Os módulos não estão disponíveis porque o OverlayFS está desabilitado pelo kernel!</string>
|
||||
<string name="enable_developer_options">Ativar opções do desenvolvedor</string>
|
||||
<string name="enable_developer_options_summary">Exibe ajustes ocultos e informações de depuração relevantes apenas para desenvolvedores.</string>
|
||||
<string name="module_overlay_fs_not_available">Os módulos estão indisponíveis porque OverlayFS está desabilitado pelo kernel!</string>
|
||||
<string name="refresh">Atualizar</string>
|
||||
<string name="show_system_apps">Mostrar aplicativos do sistema</string>
|
||||
<string name="hide_system_apps">Ocultar aplicativos do sistema</string>
|
||||
<string name="export_log">Exportar logs</string>
|
||||
<string name="safe_mode">Modo seguro</string>
|
||||
<string name="reboot_to_apply">Reinicie para aplicar as alterações</string>
|
||||
<string name="module_magisk_conflict">Os módulos não estão disponíveis devido a um conflito com o Magisk!</string>
|
||||
<string name="home_mount_system">Montagem sistema</string>
|
||||
<string name="home_magic_mount">Montagem magisk</string>
|
||||
<string name="show_system_apps">Mostrar apps do sistema</string>
|
||||
<string name="hide_system_apps">Ocultar apps do sistema</string>
|
||||
<string name="export_log">Exportar registros</string>
|
||||
<string name="safe_mode">Modo de segurança</string>
|
||||
<string name="reboot_to_apply">Reinicie para entrar em vigor</string>
|
||||
<string name="module_magisk_conflict">Os módulos estão indisponíveis devido a um conflito com Magisk!</string>
|
||||
<string name="home_mount_system">Sistema de montagem</string>
|
||||
<string name="home_magic_mount">Magic Mount</string>
|
||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||
<string name="unavailable">Indisponível</string>
|
||||
<string name="use_overlay_fs">Usar OverlayFS</string>
|
||||
<string name="use_overlay_fs_summary">Alternar entre usar OverlayFS ou montar magisk no sistema de montagem do KernelSU Next.</string>
|
||||
<string name="reboot_required">Requer reinicialização</string>
|
||||
<string name="reboot_message">As mudanças serão aplicadas após reinicialização. Quer reiniciar agora?</string>
|
||||
<string name="use_overlay_fs_summary">Alterne entre usar OverlayFS sobre Magic Mount para o sistema de montagem do KernelSU Next.</string>
|
||||
<string name="reboot_required">Reinicialização necessária</string>
|
||||
<string name="reboot_message">As alterações entrarão em vigor após a reinicialização do sistema. Deseja reiniciar agora?</string>
|
||||
<string name="module_restore">Restaurar módulo</string>
|
||||
<string name="module_restore_message">Restaurar módulos do backup recente.</string>
|
||||
<string name="backup_restore">Backup e restaure</string>
|
||||
<string name="module_backup">Backup módulo</string>
|
||||
<string name="allowlist_restore">Restaurar lista de permissão</string>
|
||||
<string name="allowlist_restore_message">Restaurar permissões do backup recente.</string>
|
||||
<string name="allowlist_backup">Backup de permissões</string>
|
||||
<string name="allowlist_backup_message">Fazer backup da lista de permissões atual.</string>
|
||||
<string name="warning">Perigo</string>
|
||||
<string name="warning_message">Este recurso ainda está em beta e em desenvolvimento. Certifique-se de fazer backup dos seus módulos antes de prosseguir. Use este recurso somente se você compreender os riscos potenciais.
|
||||
Prossiga com cautela.</string>
|
||||
<string name="module_restore_message">Restaure os módulos de um backup recente.</string>
|
||||
<string name="backup_restore">Backup e restauração</string>
|
||||
<string name="module_backup">Backup do módulo</string>
|
||||
<string name="allowlist_restore">Restaurar lista de permissões</string>
|
||||
<string name="allowlist_restore_message">Restaure a lista de permissões de um backup recente.</string>
|
||||
<string name="allowlist_backup">Backup da lista de permissões</string>
|
||||
<string name="allowlist_backup_message">Faça backup da lista de permissões atual.</string>
|
||||
<string name="warning">Aviso</string>
|
||||
<string name="warning_message">Este recurso ainda está em beta e em desenvolvimento. Certifique-se de fazer backup de seus módulos antes de continuar. Use esse recurso somente se você compreender os riscos potenciais. Proceda com cautela.</string>
|
||||
<string name="proceed">Prosseguir</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="later">Depois</string>
|
||||
<string name="later">Mais tarde</string>
|
||||
<string name="lkm_warning_message">O patch LKM depende de componentes de código fechado. Deseja continuar?</string>
|
||||
<string name="home_next_kernelsu">Nova atualização</string>
|
||||
<string name="home_next_kernelsu">🔥 Compilação next</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Novo branch. Experimental confira no Github!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ Aviso: recurso em desenvolvimento experimental!</string>
|
||||
<string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ Aviso de desenvolvimento experimental!</string>
|
||||
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||
<string name="home_experimental_kernelsu_body">KernelSU Next é uma versão não oficial que está sempre em desenvolvimento experimental ativo. É fornecida como está, sem garantias de estabilidade, desempenho ou confiabilidade.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_1"> Use por sua conta e risco: podem ocorrer travamentos, comportamentos inesperados ou problemas no sistema.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> Sem garantia: os desenvolvedores não se responsabilizam por qualquer perda de dados, danos ao sistema ou outras consequências decorrentes do uso.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> Somente para fins de teste: destinado a usuários que entendem os riscos e se sentem confortáveis em solucionar problemas.</string>
|
||||
<string name="about_source_code">Ver código-fonte em %1$s</string>
|
||||
<string name="profile">Perfil do aplicativo</string>
|
||||
<string name="home_experimental_kernelsu_body">KernelSU Next é uma versão não oficial que está sempre em desenvolvimento experimental ativo. É fornecido no estado em que se encontra, sem garantias de estabilidade, desempenho ou confiabilidade.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • Use por sua conta e risco: podem ocorrer travamentos, comportamento inesperado ou problemas no sistema.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • Sem garantia: os desenvolvedores não são responsáveis por qualquer perda de dados, danos ao sistema ou outras consequências resultantes de seu uso.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> • Apenas para fins de teste: destinado a usuários que entendem os riscos e se sentem confortáveis em solucionar problemas.</string>
|
||||
<string name="about_source_code">Veja o código-fonte no %1$s</string>
|
||||
<string name="profile">Perfil do Aplicativo</string>
|
||||
<string name="profile_default">Padrão</string>
|
||||
<string name="profile_template">Templete</string>
|
||||
<string name="profile_custom">Customizado</string>
|
||||
<string name="profile_template">Modelo</string>
|
||||
<string name="profile_custom">Personalizado</string>
|
||||
<string name="profile_name">Nome do perfil</string>
|
||||
<string name="profile_namespace">Montar nomespaço</string>
|
||||
<string name="profile_namespace">Montar namespace</string>
|
||||
<string name="profile_namespace_inherited">Herdado</string>
|
||||
<string name="profile_namespace_global">Global</string>
|
||||
<string name="profile_namespace_individual">Individual</string>
|
||||
<string name="profile_groups">Grupos </string>
|
||||
<string name="profile_capabilities">Recursos</string>
|
||||
<string name="profile_selinux_context">SELinux contexto</string>
|
||||
<string name="profile_groups">Grupos</string>
|
||||
<string name="profile_capabilities">Capacidades</string>
|
||||
<string name="profile_selinux_context">Contexto do SELinux</string>
|
||||
<string name="profile_umount_modules">Desmontar módulos</string>
|
||||
<string name="failed_to_update_app_profile">Falha ao atualizar o perfil do aplicativo para %s</string>
|
||||
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito antiga para que o gerenciador funcione corretamente. Atualize para a versão %2$d ou superior!</string>
|
||||
<string name="settings_umount_modules_default">Desmontar módulos </string>
|
||||
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" no Perfil do Aplicativo. Se ativado, removerá todas as modificações de módulos no sistema para os aplicativos que não possuem um perfil definido.</string>
|
||||
<string name="failed_to_update_app_profile">Failed to update App Profile for %s</string>
|
||||
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string>
|
||||
<string name="settings_umount_modules_default">Desmontar módulos</string>
|
||||
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string>
|
||||
<string name="settings_susfs_toggle">Ocultar hook kprobes</string>
|
||||
<string name="settings_susfs_toggle_summary">Essa opção desativa o hook do kprobes criado pelo ksu e, em vez disso, ativa o hook embutido sem kprobes, implementando a mesma funcionalidade aplicada a um kernel não-GKI, que não oferece suporte a kprobes.</string>
|
||||
<string name="profile_umount_modules_summary">Ativar essa opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este aplicativo.</string>
|
||||
<string name="settings_susfs_toggle_summary">Esta opção desativa os hook kprobes criados pelo ksu e, em vez disso, ativa os hooks embutidos não-kprobes, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string>
|
||||
<string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string>
|
||||
<string name="profile_selinux_domain">Domínio</string>
|
||||
<string name="profile_selinux_rules">Regras</string>
|
||||
<string name="module_update">atualizar</string>
|
||||
<string name="module_update">Atualizar</string>
|
||||
<string name="module_update_available">Atualizar</string>
|
||||
<string name="module_updated">Atualizado</string>
|
||||
<string name="module_downloading">Baixando modulo</string>
|
||||
<string name="module_start_downloading">Download iniciado</string>
|
||||
<string name="new_version_available">Nova versão disponível, clique para atualizar</string>
|
||||
<string name="launch_app">Lançar</string>
|
||||
<string name="module_downloading">Baixando módulo %s</string>
|
||||
<string name="module_start_downloading">Começando a baixar %s</string>
|
||||
<string name="new_version_available">Nova versão %s está disponível, clique para atualizar.</string>
|
||||
<string name="launch_app">Iniciar</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="force_stop_app">Forçar parada</string>
|
||||
<string name="restart_app">Reiniciar</string>
|
||||
<string name="settings_amoled_mode">Modo AMOLED</string>
|
||||
<string name="settings_amoled_mode_summary">Ativar tema pure black útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
|
||||
<string name="restart_required">Requer reinicialização</string>
|
||||
<string name="restart_app_message">O aplicativo precisa ser reiniciado para que as mudanças sejam aplicadas</string>
|
||||
<string name="failed_to_update_sepolicy">Falha a o atualizar SELinux para</string>
|
||||
<string name="settings_amoled_mode_summary">Ative um tema preto puro útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
|
||||
<string name="restart_required">Reinicialização necessária</string>
|
||||
<string name="restart_app_message">O app precisa ser reiniciado para que essa alteração entre em vigor.</string>
|
||||
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para %s</string>
|
||||
<string name="su_not_allowed">Não foi possível conceder acesso de Superusuário a %s</string>
|
||||
<string name="module_changelog">Lista de alterações</string>
|
||||
<string name="settings_profile_template">Modelo de perfil de aplicativo</string>
|
||||
@@ -229,4 +228,9 @@ Prossiga com cautela.</string>
|
||||
<string name="home_module_count_singular">Módulo</string>
|
||||
<string name="home_module_count_plural">Módulos</string>
|
||||
<string name="module_backup_message">Fazer backup dos módulos instalados.</string>
|
||||
<string name="module_sort_enabled_first">Ordenar (Habilitado primeiro)</string>
|
||||
<string name="module_sort_action_first">Ordenar (exceto primeiro)</string>
|
||||
<string name="module_sort_webui_first">Ordenar (WebUI primeiro)</string>
|
||||
<string name="settings_global_namespace_mode">Modo de namespace global</string>
|
||||
<string name="settings_global_namespace_mode_summary">Todas as sessões raiz usam o namespace de montagem global</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="issue_report_title">Возникли проблемы?</string>
|
||||
<string name="issue_report_body">Обнаружена ошибка или есть обратная связь?</string>
|
||||
<string name="issue_report_body">Заметили ошибку или есть предложения?</string>
|
||||
<string name="issue_report_body_2">Сообщите об этом как можно скорее!</string>
|
||||
<string name="issue_report_github">Сообщить на GitHub</string>
|
||||
<string name="issue_report_telegram">Связаться через Telegram</string>
|
||||
@@ -17,7 +17,7 @@
|
||||
<string name="home_working">Работает</string>
|
||||
<string name="home_working_version">Версия драйвера: %d</string>
|
||||
<string name="home_module_update_count">Обновлений: %d</string>
|
||||
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре!</string>
|
||||
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Напишите разработчику своего ядра, для интеграции KernelSU Next!</string>
|
||||
<string name="home_kernel">Версия ядра</string>
|
||||
<string name="hook_mode">Режим хуков</string>
|
||||
@@ -45,8 +45,8 @@
|
||||
<string name="module_install_prompt_with_name">Следующие модули будут установлены: %1$s</string>
|
||||
<string name="module_sort_a_to_z">По имени (А → Я)</string>
|
||||
<string name="module_sort_z_to_a">По имени (Я → А)</string>
|
||||
<string name="module_size_low_to_high">Сортировать (Меньше → Больше)</string>
|
||||
<string name="module_size_high_to_low">Сортировать (Больше → Меньше)</string>
|
||||
<string name="module_size_low_to_high">По размеру (Меньше → Больше)</string>
|
||||
<string name="module_size_high_to_low">По размеру (Больше → Меньше)</string>
|
||||
<string name="uninstall">Удалить</string>
|
||||
<string name="restore">Восстановить</string>
|
||||
<string name="module_install">Установить</string>
|
||||
@@ -96,11 +96,11 @@
|
||||
<string name="module_backup">Бэкап модулей</string>
|
||||
<string name="allowlist_restore">Восстановить список прав</string>
|
||||
<string name="allowlist_restore_message">Восстановить список прав из последней резервной копии.</string>
|
||||
<string name="allowlist_backup">Бэкап списка разрешений</string>
|
||||
<string name="allowlist_backup">Бэкап списка прав</string>
|
||||
<string name="allowlist_backup_message">Резервное копирование текущего списка разрешений.</string>
|
||||
<string name="warning">Предупреждение</string>
|
||||
<string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string>
|
||||
<string name="proceed">В процессе</string>
|
||||
<string name="proceed">Продолжить</string>
|
||||
<string name="cancel">Отмена</string>
|
||||
<string name="later">Позже</string>
|
||||
<string name="lkm_warning_message">Патч LKM использует компоненты с закрытым исходным кодом. Хотите продолжить?</string>
|
||||
@@ -126,14 +126,14 @@
|
||||
<string name="profile_groups">Группы</string>
|
||||
<string name="profile_capabilities">Возможности</string>
|
||||
<string name="profile_selinux_context">Контекст SELinux</string>
|
||||
<string name="profile_umount_modules">Отключить модули</string>
|
||||
<string name="profile_umount_modules">Размонтировать модули</string>
|
||||
<string name="failed_to_update_app_profile">Не удалось обновить Профиль Приложения для %s</string>
|
||||
<string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string>
|
||||
<string name="settings_umount_modules_default">Отключить модули</string>
|
||||
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в Профиле Приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string>
|
||||
<string name="settings_umount_modules_default">Размонтировать модули</string>
|
||||
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для параметра \"Размонтировать модули\" в Профиле Приложения. Если этот параметр включён, то все изменения, внесённые модулями, будут скрыты для приложений без установленного профиля или root-доступа.</string>
|
||||
<string name="settings_susfs_toggle">Скрыть хук kprobes</string>
|
||||
<string name="settings_susfs_toggle_summary">Эта опция отключает хук kprobes, созданный ksu, и вместо него активирует встроенный хук без использования kprobes, реализующий ту же функциональность, которая применяется к ядрам без GKI, не поддерживающим kprobe.</string>
|
||||
<string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string>
|
||||
<string name="profile_umount_modules_summary">Если этот параметр включен, то все модификации, внесённые модулями, будут скрыты для данного приложения.</string>
|
||||
<string name="profile_selinux_domain">Домен</string>
|
||||
<string name="profile_selinux_rules">Правила</string>
|
||||
<string name="module_update">Обновить</string>
|
||||
@@ -153,8 +153,8 @@
|
||||
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для %s</string>
|
||||
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
|
||||
<string name="module_changelog">Журнал изменений</string>
|
||||
<string name="settings_profile_template">Шаблон Профиля Приложений</string>
|
||||
<string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами Профилей Приложений</string>
|
||||
<string name="settings_profile_template">Шаблоны root-доступа</string>
|
||||
<string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами root-доступа.</string>
|
||||
<string name="app_profile_template_create">Создать шаблон</string>
|
||||
<string name="app_profile_template_edit">Изменить шаблон</string>
|
||||
<string name="app_profile_template_id">ID</string>
|
||||
@@ -176,7 +176,7 @@
|
||||
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
|
||||
<string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string>
|
||||
<string name="settings_check_update">Проверять обновления</string>
|
||||
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения</string>
|
||||
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
|
||||
<string name="grant_root_failed">Не удалось выдать root!</string>
|
||||
<string name="action">Скрипт</string>
|
||||
<string name="webui">WebUI</string>
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Модуль</string>
|
||||
<string name="home_module_count_plural">Модулей</string>
|
||||
<string name="module_backup_message">Резервное копирование текущих установленных модулей.</string>
|
||||
<string name="module_sort_enabled_first">По статусу (Сначала включённые)</string>
|
||||
<string name="module_sort_action_first">По статусу (Сначала со скриптом)</string>
|
||||
<string name="module_sort_webui_first">По статусу (Сначала с WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Общее пространство монтирования</string>
|
||||
<string name="settings_global_namespace_mode_summary">Все сессии root используют одну файловую систему.</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Backup currently installed modules.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Backup currently installed modules.</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="issue_report_title">Sorun mu yaşıyorsunuz?</string>
|
||||
<string name="issue_report_body">Hata veya öneri mi bildirmek istiyorsunuz?</string>
|
||||
<string name="issue_report_body_2">Hemen bildirin!</string>
|
||||
<string name="issue_report_github">GitHub\'de bildirin</string>
|
||||
<string name="issue_report_telegram">Telegram ile iletişim kurun</string>
|
||||
<string name="issue_report_body">Bir hatayla mı karşılaştınız veya geri bildiriminiz mi var?</string>
|
||||
<string name="issue_report_body_2">Mümkün olan en kısa sürede bildirin!</string>
|
||||
<string name="issue_report_github">GitHub’da bildirin</string>
|
||||
<string name="issue_report_telegram">Telegram üzerinden iletişim kurun</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">Onayla</string>
|
||||
<string name="app_name">KernelSU Next</string>
|
||||
<string name="home">Ana Ekran</string>
|
||||
<string name="home_not_installed">Yüklenmedi</string>
|
||||
<string name="home_click_to_install">Yüklemek için dokunun</string>
|
||||
<string name="lkm_mode_deprecated">LKM modu kullanımdan kaldırıldı!</string>
|
||||
<string name="lkm_alternative_suggestion">GKI kernel yükleyin veya KernelSU Next\'i cihazınıza entegre edin.</string>
|
||||
<string name="home_not_installed">Yüklü değil</string>
|
||||
<string name="home_click_to_install">Yüklemek için tıklayın</string>
|
||||
<string name="lkm_mode_deprecated">LKM modu artık kullanımdan kaldırıldı!</string>
|
||||
<string name="lkm_alternative_suggestion">GKI çekirdeğini yükleyin veya KernelSU Next\'i cihazınıza entegre edin.</string>
|
||||
<string name="home_working">Çalışıyor</string>
|
||||
<string name="home_working_version">Sürüm: %d</string>
|
||||
<string name="home_module_update_count">Güncellemeler: %d</string>
|
||||
<string name="home_failure">KernelSU Next v2 imzası kernelde bulunamadı! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure">KernelSU Next v2 imzası çekirdekte bulunamadı! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmelerini isteyin!</string>
|
||||
<string name="home_kernel">Kernel sürümü</string>
|
||||
<string name="hook_mode">Hook modu</string>
|
||||
<string name="home_kernel">Çekirdek sürümü</string>
|
||||
<string name="hook_mode">Kanca modu</string>
|
||||
<string name="enable">Etkinleştir</string>
|
||||
<string name="disable">Devre dışı bırak</string>
|
||||
<string name="enabled">Etkinleştir</string>
|
||||
<string name="disabled">Devre dışı bırak</string>
|
||||
<string name="enabled">Etkin</string>
|
||||
<string name="disabled">Devre dışı</string>
|
||||
<string name="susfs_supported">Destekleniyor</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">SuSFS sürümü</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Android sürümü</string>
|
||||
<string name="home_manager_version">Uygulama sürümü</string>
|
||||
<string name="home_manager_version">Yönetici sürümü</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">SELinux durumu</string>
|
||||
<string name="selinux_status_disabled">Devre dışı</string>
|
||||
<string name="selinux_status_enforcing">Zorlanıyor</string>
|
||||
<string name="selinux_status_permissive">Etkin değil</string>
|
||||
<string name="selinux_status_permissive">Permissive (Serbest)</string>
|
||||
<string name="selinux_status_unknown">Bilinmiyor</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="superuser">Süper Kullanıcı</string>
|
||||
<string name="module_failed_to_enable">Modül etkinleştirilemedi: %s</string>
|
||||
<string name="module_failed_to_disable">Modül devre dışı bırakılamadı: %s</string>
|
||||
<string name="module_empty">Yüklenmiş modül yok</string>
|
||||
<string name="module_empty">Yüklü modül yok</string>
|
||||
<string name="module">Modül</string>
|
||||
<string name="module_install_prompt_with_name">Bu modüller yüklenecektir: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Sırala (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Sırala (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Sırala (Low → High)</string>
|
||||
<string name="module_size_high_to_low">Sırala (High → Low)</string>
|
||||
<string name="module_size_low_to_high">Sırala (Düşük → Yüksek)</string>
|
||||
<string name="module_size_high_to_low">Sırala (Yüksek → Düşük)</string>
|
||||
<string name="uninstall">Kaldır</string>
|
||||
<string name="restore">Geri yükle</string>
|
||||
<string name="module_install">Yükle</string>
|
||||
@@ -63,9 +63,9 @@
|
||||
<string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinize emin misiniz?</string>
|
||||
<string name="module_uninstall_success">%s kaldırıldı</string>
|
||||
<string name="module_uninstall_failed">Kaldırma başarısız oldu: %s</string>
|
||||
<string name="module_restore_confirm">%s modülünü geri getirmek istediğinize emin misiniz?</string>
|
||||
<string name="module_restore_success">%s geri getirildi</string>
|
||||
<string name="module_restore_failed">Geri getirme başarısız oldu: %s</string>
|
||||
<string name="module_restore_confirm">%s modülünü geri yüklemek istediğinize emin misiniz?</string>
|
||||
<string name="module_restore_success">%s geri yüklendi</string>
|
||||
<string name="module_restore_failed">Geri yükleme başarısız oldu: %s</string>
|
||||
<string name="module_version">Sürüm</string>
|
||||
<string name="module_author">Geliştirici</string>
|
||||
<string name="module_id">Kimlik</string>
|
||||
@@ -74,7 +74,7 @@
|
||||
<string name="module_update_json_empty">Boş</string>
|
||||
<string name="enable_developer_options">Geliştirici seçeneklerini etkinleştir</string>
|
||||
<string name="enable_developer_options_summary">Yalnızca geliştiricilere yönelik gizli ayarları ve hata ayıklama bilgilerini göster.</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS çekirdek tarafından devre dışı bırakıldığından modüller kullanılamaz!</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS çekirdek tarafından devre dışı bırakıldığı için modüller kullanılamıyor!</string>
|
||||
<string name="refresh">Yenile</string>
|
||||
<string name="show_system_apps">Sistem uygulamalarını göster</string>
|
||||
<string name="hide_system_apps">Sistem uygulamalarını gizle</string>
|
||||
@@ -90,28 +90,28 @@
|
||||
<string name="use_overlay_fs_summary">KernelSU Next\'in bağlama sistemi için Magic Mount üzerinden OverlayFS kullanımı arasında geçiş yapın.</string>
|
||||
<string name="reboot_required">Yeniden başlatma gerekli</string>
|
||||
<string name="reboot_message">Değişiklikler sistem yeniden başlatıldıktan sonra geçerli olacaktır. Şimdi yeniden başlatmak istiyor musunuz?</string>
|
||||
<string name="module_restore">Modülü geri getir</string>
|
||||
<string name="module_restore_message">En yeni yedeklemeden modülleri geri getir.</string>
|
||||
<string name="module_restore">Modülü geri yükle</string>
|
||||
<string name="module_restore_message">Modülleri son yedeklemeden geri yükleyin.</string>
|
||||
<string name="backup_restore">Yedekle & Geri Getir</string>
|
||||
<string name="module_backup">Modülü yedekle</string>
|
||||
<string name="allowlist_restore">İzin verilen listesini geri yükle</string>
|
||||
<string name="allowlist_restore_message">En yeni yedeklemeden modülleri geri getir.</string>
|
||||
<string name="allowlist_backup">İzin verilen listesini yedekle</string>
|
||||
<string name="allowlist_restore">İzin listesini geri yükle</string>
|
||||
<string name="allowlist_restore_message">İzin listesini son yedeklemeden geri yükleyin.</string>
|
||||
<string name="allowlist_backup">İzin listesini yedekle</string>
|
||||
<string name="allowlist_backup_message">Şu anda yapılandırılmış izin listesini yedekleyin.</string>
|
||||
<string name="warning">Uyarı!</string>
|
||||
<string name="warning">Uyarı</string>
|
||||
<string name="warning_message">Bu özellik hala beta aşamasındadır ve geliştirilme aşamasındadır. Lütfen devam etmeden önce modüllerinizi yedeklediğinizden emin olun. Bu özelliği yalnızca potansiyel riskleri anlıyorsanız kullanın. Dikkatli bir şekilde ilerleyin.</string>
|
||||
<string name="proceed">Devam et</string>
|
||||
<string name="cancel">İptal et</string>
|
||||
<string name="later">Sonra</string>
|
||||
<string name="lkm_warning_message">LKM yamaları kapalı kaynak kodludur. Devam etmek istiyor musunuz?</string>
|
||||
<string name="home_next_kernelsu">🔥 Sıradaki yapı</string>
|
||||
<string name="lkm_warning_message">LKM yaması kapalı kaynak bileşenlerine dayanır. Devam etmek istiyor musunuz?</string>
|
||||
<string name="home_next_kernelsu">🔥 Next Yapımı</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next deneysel sürümü. GitHub\'da göz atın!</string>
|
||||
<string name="home_next_kernelsu_body">Next deneysel dalı. GitHub\'da göz atın!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ Deneysel geliştirme uyarısı!</string>
|
||||
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||
<string name="home_experimental_kernelsu_body">KernelSU Next, sürekli geliştirme aşamasında olan resmi olmayan bir sürümdür. Kararlılık, performans veya güvenilirlik garantisi olmadan olduğu gibi sunulur.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • Risk size aittir: çökmeler, beklenmedik davranışlar veya sistem sorunları meydana gelebilir.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • Garantili değil: geliştiriciler; kullanımından kaynaklı veri kaybı, sistem hasarı gibi sonuçlardan sorumlu değildir.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • Garanti yok: geliştiriciler herhangi bir veri kaybından, sistem hasarından veya kullanımından kaynaklanan diğer sonuçlardan sorumlu değildir.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> • Sadece test amaçlı: riskleri anlayan ve sorun giderme konusunda uzman olan kullanıcılar içindir.</string>
|
||||
<string name="about_source_code">Kaynak kodunu görüntüleyin: %1$s</string>
|
||||
<string name="profile">Uygulama Profili</string>
|
||||
@@ -121,42 +121,42 @@
|
||||
<string name="profile_name">Profil ismi</string>
|
||||
<string name="profile_namespace">Bağlama alanadı</string>
|
||||
<string name="profile_namespace_inherited">Inherited</string>
|
||||
<string name="profile_namespace_global">Global</string>
|
||||
<string name="profile_namespace_individual">Bireysel</string>
|
||||
<string name="profile_namespace_global">Genel</string>
|
||||
<string name="profile_namespace_individual">Özel</string>
|
||||
<string name="profile_groups">Gruplar</string>
|
||||
<string name="profile_capabilities">Yetenekler</string>
|
||||
<string name="profile_capabilities">Kabiliyetler</string>
|
||||
<string name="profile_selinux_context">SELinux bağlamı</string>
|
||||
<string name="profile_umount_modules">Modüllerin bağlantısını kes</string>
|
||||
<string name="failed_to_update_app_profile">Uygulama profil güncellemesi %s için başarısız oldu</string>
|
||||
<string name="require_kernel_version">Mecvut KernelSU Next sürümü %1$d, uygulamanın doğru çalışması için çok düşük. Lütfen %2$d ya da daha yüksek bir sürüme yükseltin!</string>
|
||||
<string name="failed_to_update_app_profile">%s için Uygulama Profili güncellenemedi</string>
|
||||
<string name="require_kernel_version">Geçerli KernelSU Next sürümü %1$d, yöneticinin düzgün çalışması için çok düşük. Lütfen %2$d veya daha yüksek bir sürüme yükseltin!</string>
|
||||
<string name="settings_umount_modules_default">Modüllerin bağlantısını kes</string>
|
||||
<string name="settings_umount_modules_default_summary">Uygulama profilinde \"Modüllerin bağlantısını kes\" ayarı için genel varsayılan değer. Etkinleştirilirse, profili ayarlanmamış tüm uygulamalar için sistemdeki tüm modül değişikliklerini kaldırır.</string>
|
||||
<string name="settings_susfs_toggle">kprobes kancasını gizle</string>
|
||||
<string name="settings_susfs_toggle_summary">Bu seçenek, ksu tarafından oluşturulan kprobes kancasını devre dışı bırakır ve bunun yerine gömülü kprobes olmayan kancayı etkinleştirir ve kprobe desteklemeyip GKI olmayan bir çekirdeğe uygulanacak aynı işlevi uygular.</string>
|
||||
<string name="profile_umount_modules_summary">Bu seçeneği etkinleştirmek, KernelSU Next\'in bu uygulama için modüller tarafından değiştirilen dosyaları geri yüklemesine izin verecektir.</string>
|
||||
<string name="settings_susfs_toggle_summary">Bu seçenek, ksu tarafından oluşturulan kprobes kancasını devre dışı bırakır ve bunun yerine, kprobe\'u desteklemeyen GKI olmayan bir çekirdeğe uygulanacak aynı işlevselliği uygulayan gömülü kprobes olmayan kancayı etkinleştirir.</string>
|
||||
<string name="profile_umount_modules_summary">Bu seçeneğin etkinleştirilmesi, KernelSU Next\'in bu uygulama için modüller tarafından değiştirilen tüm dosyaları geri yüklemesine izin verecektir.</string>
|
||||
<string name="profile_selinux_domain">Alan adı</string>
|
||||
<string name="profile_selinux_rules">Kurallar</string>
|
||||
<string name="module_update">Güncelleme</string>
|
||||
<string name="module_update">Güncelle</string>
|
||||
<string name="module_update_available">Güncelleme mevcut</string>
|
||||
<string name="module_updated">Güncellendi</string>
|
||||
<string name="module_downloading">Modül indiriliyor: %s</string>
|
||||
<string name="module_start_downloading">İndirme başlıyor: %s</string>
|
||||
<string name="new_version_available">Yeni sürüm %s mevcut, güncellemek için dokunun.</string>
|
||||
<string name="launch_app">Aç</string>
|
||||
<string name="new_version_available">Yeni sürüm %s mevcut, güncellemek için tıklayın.</string>
|
||||
<string name="launch_app">Başlat</string>
|
||||
<string name="close">Kapat</string>
|
||||
<string name="force_stop_app">Durmaya zorla</string>
|
||||
<string name="restart_app">Yeniden başlat</string>
|
||||
<string name="settings_amoled_mode">AMOLED modu</string>
|
||||
<string name="settings_amoled_mode_summary">AMOLED ekranlar için göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için kullanışlı saf siyah temayı etkinleştirin.</string>
|
||||
<string name="settings_amoled_mode_summary">Göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için AMOLED ekranlar için kullanışlı olan saf siyah temayı etkinleştirin.</string>
|
||||
<string name="restart_required">Yeniden başlatma gerekli</string>
|
||||
<string name="restart_app_message">Uygulamanın bu değişikliği uygulaması için yeniden başlatılması gerekiyor.</string>
|
||||
<string name="restart_app_message">Bu değişikliğin etkili olması için uygulamanın yeniden başlatılması gerekiyor.</string>
|
||||
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi</string>
|
||||
<string name="su_not_allowed">%s\'ye Superuser izni verilemedi</string>
|
||||
<string name="su_not_allowed">%s\'ye süper kullanıcı izni verilemedi</string>
|
||||
<string name="module_changelog">Değişiklik Notları</string>
|
||||
<string name="settings_profile_template">Uygulama Profili şablonu</string>
|
||||
<string name="settings_profile_template_summary">Uygulama Profil Şablonunu yerel ve çevrimiçi olarak yönetin</string>
|
||||
<string name="settings_profile_template_summary">Uygulama Profilinin yerel ve çevrimiçi şablonunu yönetme</string>
|
||||
<string name="app_profile_template_create">Şablon oluştur</string>
|
||||
<string name="app_profile_template_edit">Şablonu Düzenle</string>
|
||||
<string name="app_profile_template_edit">Şablonu düzenle</string>
|
||||
<string name="app_profile_template_id">Kimlik</string>
|
||||
<string name="app_profile_template_id_invalid">Geçersiz şablon kimliği</string>
|
||||
<string name="app_profile_template_name">Ad</string>
|
||||
@@ -164,12 +164,12 @@
|
||||
<string name="app_profile_template_save">Kaydet</string>
|
||||
<string name="app_profile_template_delete">Sil</string>
|
||||
<string name="app_profile_template_view">Şablonu görüntüle</string>
|
||||
<string name="app_profile_template_readonly">Sadece okunabilir</string>
|
||||
<string name="app_profile_template_readonly">Salt okunur</string>
|
||||
<string name="app_profile_template_id_exist">Şablon kimliği zaten mevcut!</string>
|
||||
<string name="app_profile_import_export">İçe Aktar / Dışa Aktar</string>
|
||||
<string name="app_profile_import_from_clipboard">Pano\'dan içe aktar</string>
|
||||
<string name="app_profile_export_to_clipboard">Panoya çıkar</string>
|
||||
<string name="app_profile_template_export_empty">Dışa aktarmak için yerel şablon bulunamadı!</string>
|
||||
<string name="app_profile_import_from_clipboard">Panodan içe aktar</string>
|
||||
<string name="app_profile_export_to_clipboard">Panoya aktar</string>
|
||||
<string name="app_profile_template_export_empty">Dışa aktarılacak yerel şablon bulunamıyor!</string>
|
||||
<string name="app_profile_template_import_success">Başarıyla içe aktarıldı</string>
|
||||
<string name="app_profile_template_sync">Çevrimiçi şablonları senkronize et</string>
|
||||
<string name="app_profile_template_save_failed">Şablon kaydedilemedi</string>
|
||||
@@ -177,35 +177,35 @@
|
||||
<string name="module_changelog_failed">Değişiklik günlüğü alınamadı: %s</string>
|
||||
<string name="settings_check_update">Güncellemeleri kontrol et</string>
|
||||
<string name="settings_check_update_summary">Uygulamayı açarken güncellemeleri otomatik denetle</string>
|
||||
<string name="grant_root_failed">Kök yetkisi verilemedi!</string>
|
||||
<string name="action">İşlem</string>
|
||||
<string name="grant_root_failed">Kök izni verilemedi!</string>
|
||||
<string name="action">Eylem</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Aç</string>
|
||||
<string name="enable_web_debugging">WebView hata ayıklama etkinleştir</string>
|
||||
<string name="enable_web_debugging_summary">WebUI\'yi hata ayıklamak için kullanılabilir. Sadece ihtiyaç duyulduğunda etkinleştirin.</string>
|
||||
<string name="enable_web_debugging">WebView hata ayıklamayı etkinleştir</string>
|
||||
<string name="enable_web_debugging_summary">WebUI\'de hata ayıklamak için kullanılabilir. Lütfen yalnızca gerektiğinde etkinleştirin.</string>
|
||||
<string name="direct_install">Doğrudan kurulum (Önerilen)</string>
|
||||
<string name="select_file">Bir dosya seçin</string>
|
||||
<string name="install_inactive_slot">Aktif olmayan yuvaya kur (OTA sonrası)</string>
|
||||
<string name="install_inactive_slot_warning">Cihazınız **ZORUNLU** olarak aktif olmayan yuvadan yeniden başlatılacaktır!\nBunu sadece OTA tamamlandıktan sonra kullanın\nDevam etmek istiyor musunuz?</string>
|
||||
<string name="install_next">Sıradaki</string>
|
||||
<string name="install_inactive_slot_warning">Cihazınız yeniden başlatıldıktan sonra mevcut etkin olmayan yuvaya önyükleme yapmak için **ZORUNLU** olacaktır.\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam?</string>
|
||||
<string name="install_next">Sonraki</string>
|
||||
<string name="select_file_tip">%1$s bölüm imajı önerilir</string>
|
||||
<string name="select_kmi">KMI seçin</string>
|
||||
<string name="shrink_sparse_image">Sparse imajını küçültün</string>
|
||||
<string name="shrink_sparse_image_message">Modülün bulunduğu sparse imajını gerçek boyutuna yeniden boyutlandırın. Bunun modülün anormal çalışmasına neden olabileceğini unutmayın, bu nedenle lütfen yalnızca gerekli olduğunda kullanın (yedekleme gibi).</string>
|
||||
<string name="shrink_sparse_image_message">Modülün bulunduğu sparse imajını gerçek boyutuna yeniden boyutlandırın. Bunun modülün anormal çalışmasına neden olabileceğini unutmayın, bu nedenle lütfen yalnızca gerekli olduğunda kullanın (Yedekleme gibi).</string>
|
||||
<string name="settings_uninstall">Kaldır</string>
|
||||
<string name="settings_uninstall_temporary">Geçici olarak kaldır</string>
|
||||
<string name="settings_uninstall_permanent">Kalıcı olarak kaldır</string>
|
||||
<string name="settings_restore_stock_image">Stok imajı geri yükle</string>
|
||||
<string name="settings_uninstall_temporary_message">KernelSU\'yu geçici olarak kaldırın, bir sonraki yeniden başlatmadan sonra orijinal duruma geri dönün.</string>
|
||||
<string name="settings_uninstall_permanent_message">KernelSU Next\'i (Root ve tüm modüller) tamamen ve kalıcı olarak kaldırın.</string>
|
||||
<string name="settings_uninstall_permanent_message">KernelSU Next\'i (Kök ve tüm modüller) tamamen ve kalıcı olarak kaldırın.</string>
|
||||
<string name="settings_restore_stock_image_message">Stok fabrika imajını geri yükler (eğer yedek varsa), genellikle OTA\'dan önce kullanılır; KernelSU\'yu kaldırmanız gerekiyorsa, lütfen \"Kalıcı olarak kaldır\" seçeneğini kullanın.</string>
|
||||
<string name="flashing">Kuruluyor</string>
|
||||
<string name="flash_success">Kurulum başarılı</string>
|
||||
<string name="flash_failed">Kurulum başarısız</string>
|
||||
<string name="selected_lkm">Seçili LKM: %s</string>
|
||||
<string name="save_log">Logları kaydet</string>
|
||||
<string name="log_saved">Loglar kaydedildi</string>
|
||||
<string name="send_log">Logları paylaş</string>
|
||||
<string name="save_log">Günlükleri kaydet</string>
|
||||
<string name="log_saved">Günlükler kaydedildi</string>
|
||||
<string name="send_log">Günlükleri paylaş</string>
|
||||
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
|
||||
<string name="settings_disable_su_summary">Geçici olarak uygulamaların su komutu ile kök erişimi kazanmasını devre dışı bırakın (Zaten kök erişimi bulunan işlemler etkilenmez).</string>
|
||||
<string name="settings_language">Dil</string>
|
||||
@@ -223,9 +223,14 @@
|
||||
<string name="sucompat_disabled">SUCOMPAT DEVRE DIŞI</string>
|
||||
<string name="zygisk_required">Zygisk gerekli</string>
|
||||
<string name="zygisk_status">Zygisk enjeksiyonu</string>
|
||||
<string name="home_superuser_count_singular">Superuser</string>
|
||||
<string name="home_superuser_count_plural">Superusers</string>
|
||||
<string name="home_superuser_count_singular">Süper Kullanıcı</string>
|
||||
<string name="home_superuser_count_plural">Süper Kullanıcılar</string>
|
||||
<string name="home_module_count_singular">Modül</string>
|
||||
<string name="home_module_count_plural">Modüller</string>
|
||||
<string name="module_backup_message">Şu anda kurulu olan modülleri yedekleyin.</string>
|
||||
<string name="module_sort_enabled_first">Sırala (Önce etkin)</string>
|
||||
<string name="module_sort_action_first">Sırala (Önce eylem)</string>
|
||||
<string name="module_sort_webui_first">Sırala (Önce WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Küresel Ad Alanı Modu</string>
|
||||
<string name="settings_global_namespace_mode_summary">Tüm kök oturumları genel bağlama ad alanını kullanır</string>
|
||||
</resources>
|
||||
|
||||
@@ -222,10 +222,15 @@
|
||||
<string name="developer">Для Розробників</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT ВИМКНЕНО</string>
|
||||
<string name="zygisk_required">Потрібно Zygisk</string>
|
||||
<string name="zygisk_status">Zygisk-інджект</string>
|
||||
<string name="home_superuser_count_singular">Суперкористувач</string>
|
||||
<string name="home_superuser_count_plural">Суперкористувачі</string>
|
||||
<string name="zygisk_status">Інжект Zygisk</string>
|
||||
<string name="home_superuser_count_singular">Видано право</string>
|
||||
<string name="home_superuser_count_plural">Видано прав</string>
|
||||
<string name="home_module_count_singular">Модуль</string>
|
||||
<string name="home_module_count_plural">Модулі</string>
|
||||
<string name="module_backup_message">Бекап поточних встановлених модулів.</string>
|
||||
<string name="module_sort_enabled_first">За статусом (Спочатку включені)</string>
|
||||
<string name="module_sort_action_first">За статусом (Спочатку зі скриптом)</string>
|
||||
<string name="module_sort_webui_first">За статусом (Спочатку з WebUI)</string>
|
||||
<string name="settings_global_namespace_mode">Загальний простір імен</string>
|
||||
<string name="settings_global_namespace_mode_summary">Усі сесії користувача root будуть використовувати спільний простір імен</string>
|
||||
</resources>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<string name="home_manager_version">Phiên bản trình quản lý</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">Trạng thái SELinux</string>
|
||||
<string name="selinux_status_disabled">Đã vô hiệu hoá</string>
|
||||
<string name="selinux_status_disabled">Vô hiệu hoá</string>
|
||||
<string name="selinux_status_enforcing">Enforcing</string>
|
||||
<string name="selinux_status_permissive">Permissive</string>
|
||||
<string name="selinux_status_unknown">Không xác định</string>
|
||||
@@ -222,10 +222,15 @@
|
||||
<string name="developer">Nhà phát triển</string>
|
||||
<string name="sucompat_disabled">Vô hiệu hoá lệnh SU</string>
|
||||
<string name="zygisk_required">Yêu cầu Zygisk</string>
|
||||
<string name="zygisk_status">Zygisk Inject</string>
|
||||
<string name="zygisk_status">Triển khai Zygisk</string>
|
||||
<string name="home_superuser_count_singular">Superuser</string>
|
||||
<string name="home_superuser_count_plural">Superusers</string>
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_backup_message">Sao lưu các module hiện đang được cài đặt</string>
|
||||
<string name="module_sort_enabled_first">Sắp xếp (Bật trước)</string>
|
||||
<string name="module_sort_action_first">Sắp xếp (Khởi chạy trước)</string>
|
||||
<string name="module_sort_webui_first">Sắp xếp (WebUI trước)</string>
|
||||
<string name="settings_global_namespace_mode">Chế độ Namespace chung</string>
|
||||
<string name="settings_global_namespace_mode_summary">Tất cả các phiên root đều sử dụng mount namespace chung</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<string name="lkm_mode_deprecated">LKM 模式已弃用!</string>
|
||||
<string name="lkm_alternative_suggestion">安装 GKI 内核或集成 KernelSU 到你的设备。</string>
|
||||
<string name="home_working">工作中</string>
|
||||
<string name="home_working_version">版本:%d</string>
|
||||
<string name="home_working_version">版本: %d</string>
|
||||
<string name="home_module_update_count">%d 个模块可更新!</string>
|
||||
<string name="home_failure">无法在内核中找到 KernelSU Next v2 签名![ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next!</string>
|
||||
@@ -26,27 +26,27 @@
|
||||
<string name="enabled">已启用</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="susfs_supported">支持</string>
|
||||
<string name="home_susfs">SuSFS:%s</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">SuSFS 版本</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Android 版本</string>
|
||||
<string name="home_manager_version">管理器版本</string>
|
||||
<string name="home_abi">接口</string>
|
||||
<string name="home_abi">ABI 类型</string>
|
||||
<string name="home_selinux_status">SELinux 状态</string>
|
||||
<string name="selinux_status_disabled">禁用</string>
|
||||
<string name="selinux_status_enforcing">严格模式</string>
|
||||
<string name="selinux_status_permissive">宽容模式</string>
|
||||
<string name="selinux_status_unknown">未知</string>
|
||||
<string name="superuser">超级用户</string>
|
||||
<string name="module_failed_to_enable">启用模块失败:%s</string>
|
||||
<string name="module_failed_to_disable">禁用模块失败:%s</string>
|
||||
<string name="module_failed_to_enable">无法启用模块: %s</string>
|
||||
<string name="module_failed_to_disable">无法禁用模块: %s</string>
|
||||
<string name="module_empty">未安装任何模块</string>
|
||||
<string name="module">模块</string>
|
||||
<string name="module_install_prompt_with_name">将安装以下模块:%1$s</string>
|
||||
<string name="module_sort_a_to_z">按 A - Z 排序</string>
|
||||
<string name="module_sort_z_to_a">按 Z - A 排序</string>
|
||||
<string name="module_size_low_to_high">按模块大小正序排序</string>
|
||||
<string name="module_size_high_to_low">按模块大小倒序排序</string>
|
||||
<string name="module_install_prompt_with_name">将安装以下模块: %1$s</string>
|
||||
<string name="module_sort_a_to_z">排序 (A -> Z)</string>
|
||||
<string name="module_sort_z_to_a">排序 (Z -> A)</string>
|
||||
<string name="module_size_low_to_high">排序 (按模块从小到大)</string>
|
||||
<string name="module_size_high_to_low">排序 (按模块从大到小)</string>
|
||||
<string name="uninstall">卸载</string>
|
||||
<string name="restore">还原</string>
|
||||
<string name="module_install">安装</string>
|
||||
@@ -62,10 +62,10 @@
|
||||
<string name="about">关于</string>
|
||||
<string name="module_uninstall_confirm">确定要卸载模块 %s 吗?</string>
|
||||
<string name="module_uninstall_success">已卸载 %s</string>
|
||||
<string name="module_uninstall_failed">卸载失败:%s</string>
|
||||
<string name="module_uninstall_failed">卸载失败: %s</string>
|
||||
<string name="module_restore_confirm">确定要还原模块 %s 吗?</string>
|
||||
<string name="module_restore_success">已还原 %s</string>
|
||||
<string name="module_restore_failed">恢复失败:%s</string>
|
||||
<string name="module_restore_failed">恢复失败: %s</string>
|
||||
<string name="module_version">版本</string>
|
||||
<string name="module_author">作者</string>
|
||||
<string name="module_id">模块标识</string>
|
||||
@@ -82,7 +82,7 @@
|
||||
<string name="safe_mode">安全模式</string>
|
||||
<string name="reboot_to_apply">重启生效</string>
|
||||
<string name="module_magisk_conflict">由于与 Magisk 冲突,模块系统不可用!</string>
|
||||
<string name="home_mount_system">模块系统</string>
|
||||
<string name="home_mount_system">挂载系统</string>
|
||||
<string name="home_magic_mount">Magic Mount</string>
|
||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||
<string name="unavailable">不可用</string>
|
||||
@@ -103,10 +103,10 @@
|
||||
<string name="proceed">继续</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="later">稍后</string>
|
||||
<string name="lkm_warning_message">此 LKM 补丁依赖于闭源组件,确认操作代表你知晓因继续使用该功能所导致的一切后果与开发团队无关。</string>
|
||||
<string name="home_next_kernelsu">🔥 Next 构建</string>
|
||||
<string name="lkm_warning_message">LKM 补丁依赖于闭源组件。是否继续?</string>
|
||||
<string name="home_next_kernelsu">🔥 下一个版本</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next 实验性分支。在 GitHub 上查看!</string>
|
||||
<string name="home_next_kernelsu_body">下一个实验性分支。请在 GitHub 上查看!</string>
|
||||
<string name="home_experimental_kernelsu">⚠️ 实验性开发警告!</string>
|
||||
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||
<string name="home_experimental_kernelsu_body">KernelSU Next 是一个非官方版本,一直处于积极的实验开发阶段。它按原样提供,不保证稳定性、性能或可靠性。</string>
|
||||
@@ -139,9 +139,9 @@
|
||||
<string name="module_update">更新</string>
|
||||
<string name="module_update_available">更新可用</string>
|
||||
<string name="module_updated">重启以应用更新</string>
|
||||
<string name="module_downloading">正在下载模块:%s</string>
|
||||
<string name="module_start_downloading">开始下载:%s</string>
|
||||
<string name="new_version_available">发现新版本:%s,点击升级。</string>
|
||||
<string name="module_downloading">正在下载模块: %s</string>
|
||||
<string name="module_start_downloading">开始下载: %s</string>
|
||||
<string name="new_version_available">发现新版本 %s,点击升级。</string>
|
||||
<string name="launch_app">启动</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="force_stop_app">强行停止</string>
|
||||
@@ -174,7 +174,7 @@
|
||||
<string name="app_profile_template_sync">同步在线模板</string>
|
||||
<string name="app_profile_template_save_failed">模版保存失败</string>
|
||||
<string name="app_profile_template_import_empty">剪贴板为空!</string>
|
||||
<string name="module_changelog_failed">获取更新日志失败:%s</string>
|
||||
<string name="module_changelog_failed">获取更新日志失败: %s</string>
|
||||
<string name="settings_check_update">检查更新</string>
|
||||
<string name="settings_check_update_summary">在应用启动后自动检查是否有新版本。</string>
|
||||
<string name="grant_root_failed">获取 root 失败!</string>
|
||||
@@ -202,7 +202,7 @@
|
||||
<string name="flashing">刷写中</string>
|
||||
<string name="flash_success">刷写成功</string>
|
||||
<string name="flash_failed">刷写失败</string>
|
||||
<string name="selected_lkm">选择的 LKM:%s</string>
|
||||
<string name="selected_lkm">选择的 LKM: %s</string>
|
||||
<string name="save_log">保存日志</string>
|
||||
<string name="log_saved">日志已保存</string>
|
||||
<string name="send_log">分享日志</string>
|
||||
@@ -220,7 +220,7 @@
|
||||
<string name="use_webuix_eruda_summary">将调试控制台注入 WebUI X 以使调试更容易。需要启用 Web 调试。</string>
|
||||
<string name="customization">界面设置</string>
|
||||
<string name="developer">开发者选项</string>
|
||||
<string name="sucompat_disabled">SU 兼容被禁用</string>
|
||||
<string name="sucompat_disabled">SU 兼容已禁用</string>
|
||||
<string name="zygisk_required">需要 Zygisk</string>
|
||||
<string name="zygisk_status">Zygisk 注入</string>
|
||||
<string name="home_superuser_count_singular">超级用户</string>
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">模块</string>
|
||||
<string name="home_module_count_plural">模块</string>
|
||||
<string name="module_backup_message">备份当前已安装的模块。</string>
|
||||
<string name="module_sort_enabled_first">排序 (已启用优先)</string>
|
||||
<string name="module_sort_action_first">排序 (可执行优先)</string>
|
||||
<string name="module_sort_webui_first">排序 (支持 WebUI 优先)</string>
|
||||
<string name="settings_global_namespace_mode">全局命名空间模式</string>
|
||||
<string name="settings_global_namespace_mode_summary">所有 Root 会话均使用全局挂载命名空间。</string>
|
||||
</resources>
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
<string name="module_install_prompt_with_name">即將安裝以下模組:%1$s</string>
|
||||
<string name="module_sort_a_to_z">按 A - Z 排序</string>
|
||||
<string name="module_sort_z_to_a">按 Z - A 排序</string>
|
||||
<string name="module_size_low_to_high">按模組大小正序排序</string>
|
||||
<string name="module_size_high_to_low">按模組大小倒序排序</string>
|
||||
<string name="module_size_low_to_high">依模組大小正向排序</string>
|
||||
<string name="module_size_high_to_low">依模組大小反向排序</string>
|
||||
<string name="uninstall">卸載</string>
|
||||
<string name="restore">還原</string>
|
||||
<string name="module_install">安裝</string>
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_module_count_singular">模組</string>
|
||||
<string name="home_module_count_plural">模組</string>
|
||||
<string name="module_backup_message">備份當前已安裝的模組。</string>
|
||||
<string name="module_sort_enabled_first">依啟用狀態優先排序</string>
|
||||
<string name="module_sort_action_first">依支援執行優先排序</string>
|
||||
<string name="module_sort_webui_first">依具備 WebUI 優先排序</string>
|
||||
<string name="settings_global_namespace_mode">全域命名空間模式</string>
|
||||
<string name="settings_global_namespace_mode_summary">所有 Root 工作階段皆使用全域掛載命名空間</string>
|
||||
</resources>
|
||||
|
||||
@@ -228,4 +228,9 @@
|
||||
<string name="home_superuser_count_plural">Superusers</string>
|
||||
<string name="home_module_count_singular">Module</string>
|
||||
<string name="home_module_count_plural">Modules</string>
|
||||
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
|
||||
<string name="module_sort_action_first">Sort (Action first)</string>
|
||||
<string name="module_sort_webui_first">Sort (WebUI first)</string>
|
||||
<string name="settings_global_namespace_mode">Global Namespace Mode</string>
|
||||
<string name="settings_global_namespace_mode_summary">All root sessions use the global mount namespace</string>
|
||||
</resources>
|
||||
|
||||
26
manager/setup.sh
Executable file
26
manager/setup.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
|
||||
> gradle.properties
|
||||
|
||||
{
|
||||
echo 'android.experimental.enableNewResourceShrinker.preciseShrinking=true'
|
||||
echo 'android.enableAppCompileTimeRClass=true'
|
||||
echo 'android.useAndroidX=true'
|
||||
echo KEYSTORE_PASSWORD=$MY_KEYSTORE_PASSWORD
|
||||
echo KEY_ALIAS=$MY_KEY_ALIAS
|
||||
echo KEY_PASSWORD=$MY_KEY_PASSWORD
|
||||
echo KEYSTORE_FILE='key.jks'
|
||||
echo 'org.gradle.parallel=true'
|
||||
echo 'org.gradle.vfs.watch=true'
|
||||
echo 'org.gradle.jvmargs=-Xmx2048m'
|
||||
echo 'android.native.buildOutput=verbose'
|
||||
} >> gradle.properties
|
||||
|
||||
./gradlew clean assembleRelease
|
||||
|
||||
> gradle.properties
|
||||
|
||||
{
|
||||
echo 'android.experimental.enableNewResourceShrinker.preciseShrinking=true'
|
||||
echo 'android.enableAppCompileTimeRClass=true'
|
||||
echo 'android.useAndroidX=true'
|
||||
} >> gradle.properties
|
||||
@@ -25,4 +25,15 @@ find . -type f -exec sed -i \
|
||||
-e "s/com\/rifsxd\/ksunext/$word1\/$word2\/$word3/g" \
|
||||
-e "s/com_rifsxd_ksunext/${word1}_${word2}_${word3}/g" {} +
|
||||
|
||||
echo "Done."
|
||||
# Append '-spoofed' to managerVersionName in build.gradle.kts
|
||||
if [ -f "./build.gradle.kts" ]; then
|
||||
sed -i 's/\(val managerVersionName by extra(getVersionName())\)/\1\nval managerVersionNameSpoofed = "${managerVersionName}-spoofed"/' ./build.gradle.kts
|
||||
sed -i 's/\(versionName = managerVersionName\)/versionName = managerVersionNameSpoofed/' ./build.gradle.kts
|
||||
fi
|
||||
|
||||
if [ -f "./app/build.gradle.kts" ]; then
|
||||
sed -i '/val managerVersionName:/a val managerVersionNameSpoofed = "${managerVersionName}-spoofed"' ./app/build.gradle.kts
|
||||
sed -i 's/outputFileName = "KernelSU_Next_${managerVersionName}_${managerVersionCode}-\$name.apk"/outputFileName = "KernelSU_Next_${managerVersionNameSpoofed}_${managerVersionCode}-\$name.apk"/' ./app/build.gradle.kts
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
_ __ _ ____ _ _
|
||||
| |/ /___ _ __ _ __ ___| / ___|| | | |
|
||||
| ' // _ \ '__| '_ \ / _ \ \___ \| | | |
|
||||
| . \ __/ | | | | | __/ |___) | |_| |
|
||||
|_|\_\___|_| |_| |_|\___|_|____/ \___/
|
||||
| \ | | _____ _| |_
|
||||
| \| |/ _ \ \/ / __|
|
||||
| |\ | __/> <| |_
|
||||
|_| \_|\___/_/\_\\__|
|
||||
@@ -310,7 +310,7 @@ pub fn restore(
|
||||
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
|
||||
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?;
|
||||
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?;
|
||||
|
||||
println!("- Unpacking boot image");
|
||||
let status = Command::new(&magiskboot)
|
||||
@@ -323,21 +323,21 @@ pub fn restore(
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
// let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let no_vendor_init_boot = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("ramdisk.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_init_boot =
|
||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_ramdisk =
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
is_kernelsu_patched || is_kernelsu_patched_vendor_init_boot || is_kernelsu_patched_vendor_ramdisk,
|
||||
is_kernelsu_patched
|
||||
|| is_kernelsu_patched_vendor_init_boot
|
||||
|| is_kernelsu_patched_vendor_ramdisk,
|
||||
"boot image is not patched by KernelSU Next"
|
||||
);
|
||||
|
||||
@@ -349,7 +349,7 @@ pub fn restore(
|
||||
do_cpio_cmd(
|
||||
&magiskboot,
|
||||
workdir,
|
||||
&format!("extract {0} {0}", BACKUP_FILENAME),
|
||||
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
|
||||
let sha = String::from_utf8(sha)?;
|
||||
@@ -371,41 +371,78 @@ pub fn restore(
|
||||
}
|
||||
|
||||
if new_boot.is_none() {
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
// vendor init_boot restore
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_init_boot)?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
// vendor ramdisk restore
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !no_ramdisk {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Restoring /vendor_ramdisk/init_boot");
|
||||
println!("- Removing /vendor_ramdisk/init_boot/kernelsu.ko");
|
||||
// vendor init_boot restore
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
println!("- Checking if init.real exists");
|
||||
let status =
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/init_boot/init.real to init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/init_boot.cpio");
|
||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_init_boot)?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk");
|
||||
println!("- Removing /vendor_ramdisk/ramdisk/kernelsu.ko");
|
||||
// vendor ramdisk restore
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk/init.real to init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/ramdisk.cpio");
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
} else {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
@@ -483,8 +520,6 @@ fn do_patch(
|
||||
magiskboot_path: Option<PathBuf>,
|
||||
kmi: Option<String>,
|
||||
) -> Result<()> {
|
||||
println!(include_str!("banner"));
|
||||
|
||||
let patch_file = image.is_some();
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -516,7 +551,7 @@ fn do_patch(
|
||||
match get_current_kmi() {
|
||||
Ok(value) => value,
|
||||
Err(e) => {
|
||||
println!("- {}", e);
|
||||
println!("- {e}");
|
||||
if let Some(image_path) = &image {
|
||||
println!(
|
||||
"- Trying to auto detect KMI version for {}",
|
||||
@@ -539,7 +574,7 @@ fn do_patch(
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
|
||||
let (bootimage, bootdevice) =
|
||||
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;
|
||||
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir, &magiskboot)?;
|
||||
|
||||
let bootimage = bootimage.display().to_string();
|
||||
|
||||
@@ -585,20 +620,19 @@ fn do_patch(
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("ramdisk.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
if no_ramdisk && no_vendor_init_boot && no_vendor_ramdisk {
|
||||
bail!("No compatible ramdisk found.");
|
||||
println!("- No compatible ramdisk found.");
|
||||
println!("- Will create our own ramdisk!");
|
||||
}
|
||||
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_init_boot =
|
||||
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_ramdisk =
|
||||
is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_ramdisk = is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
!is_magisk_patched || !is_magisk_patched_vendor_init_boot || !is_magisk_patched_vendor_ramdisk,
|
||||
!is_magisk_patched
|
||||
|| !is_magisk_patched_vendor_init_boot
|
||||
|| !is_magisk_patched_vendor_ramdisk,
|
||||
"Cannot work with Magisk patched image"
|
||||
);
|
||||
|
||||
@@ -610,41 +644,59 @@ fn do_patch(
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
|
||||
let mut need_backup = false;
|
||||
if !is_kernelsu_patched || (no_ramdisk && !is_kernelsu_patched_vendor_init_boot) || (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|
||||
if (no_ramdisk && !is_kernelsu_patched_vendor_init_boot)
|
||||
|| (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|
||||
|| !is_kernelsu_patched
|
||||
{
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
// vendor init_boot patching
|
||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
// vendor ramdisk patching
|
||||
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
if !no_ramdisk {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Checking if /vendor_ramdisk/init_boot/init exists");
|
||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/init_boot/init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Checking if /vendor_ramdisk/ramdisk/init exists");
|
||||
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/ramdisk/init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
}
|
||||
}
|
||||
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_ramdisk {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
if !no_ramdisk {
|
||||
println!("- Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Patching /vendor_ramdisk/init_boot");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Patching /vendor_ramdisk/ramdisk");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
|
||||
} else {
|
||||
println!("- Creating and Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
@@ -714,7 +766,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
|
||||
}
|
||||
|
||||
let result = hasher.finalize();
|
||||
Ok(format!("{:x}", result))
|
||||
Ok(format!("{result:x}"))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -730,7 +782,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
do_cpio_cmd(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&format!("add 0755 {0} {0}", BACKUP_FILENAME),
|
||||
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
println!("- Stock image has been backup to");
|
||||
println!("- {target}");
|
||||
@@ -740,7 +792,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
#[cfg(target_os = "android")]
|
||||
fn clean_backup(sha1: &str) -> Result<()> {
|
||||
println!("- Clean up backup");
|
||||
let backup_name = format!("{}{}", KSU_BACKUP_FILE_PREFIX, sha1);
|
||||
let backup_name = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
|
||||
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
|
||||
for entry in dir.flatten() {
|
||||
let path = entry.path();
|
||||
@@ -803,16 +855,17 @@ fn find_boot_image(
|
||||
ota: bool,
|
||||
is_replace_kernel: bool,
|
||||
workdir: &Path,
|
||||
magiskboot: &Path,
|
||||
) -> Result<(PathBuf, Option<String>)> {
|
||||
let bootimage;
|
||||
let mut bootdevice = None;
|
||||
if let Some(ref image) = *image {
|
||||
ensure!(image.exists(), "boot image not found");
|
||||
ensure!(image.exists(), "- Boot image not found");
|
||||
bootimage = std::fs::canonicalize(image)?;
|
||||
} else {
|
||||
if cfg!(not(target_os = "android")) {
|
||||
println!("- Current OS is not android, refusing auto bootimage/bootdevice detection");
|
||||
bail!("Please specify a boot image");
|
||||
bail!("- Please specify a boot image");
|
||||
}
|
||||
let mut slot_suffix =
|
||||
utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
|
||||
@@ -825,27 +878,104 @@ fn find_boot_image(
|
||||
}
|
||||
};
|
||||
|
||||
let init_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
|
||||
let vendor_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
|
||||
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/init_boot{slot_suffix}")
|
||||
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
|
||||
} else {
|
||||
format!("/dev/block/by-name/boot{slot_suffix}")
|
||||
};
|
||||
let init_boot_partition = format!("/dev/block/by-name/init_boot{slot_suffix}");
|
||||
let vendor_boot_partition = format!("/dev/block/by-name/vendor_boot{slot_suffix}");
|
||||
let boot_partition = format!("/dev/block/by-name/boot{slot_suffix}");
|
||||
|
||||
println!("- Bootdevice: {boot_partition}");
|
||||
let init_boot_exist = Path::new(&init_boot_partition).exists();
|
||||
let vendor_boot_exist = Path::new(&vendor_boot_partition).exists();
|
||||
|
||||
// helper: unpack a partition and check for a ramdisk and init
|
||||
fn unpack_and_check_init(
|
||||
magiskboot: &Path,
|
||||
workdir: &Path,
|
||||
partition: &str,
|
||||
ramdisk_cpio: &str,
|
||||
) -> Result<bool> {
|
||||
let tmp_img = workdir.join("probe.img");
|
||||
dd(partition, &tmp_img)?;
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("unpack")
|
||||
.arg(&tmp_img)
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
return Ok(false);
|
||||
}
|
||||
let ramdisk_path = workdir.join(ramdisk_cpio);
|
||||
let has_init = if ramdisk_path.exists() {
|
||||
Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(ramdisk_cpio)
|
||||
.arg("exists init")
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Clean up
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
let _ = std::fs::remove_file(workdir.join("ramdisk.cpio"));
|
||||
let _ = std::fs::remove_dir_all(workdir.join("vendor_ramdisk"));
|
||||
Ok(has_init)
|
||||
}
|
||||
|
||||
let mut selected_partition = &boot_partition;
|
||||
|
||||
if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
// try init_boot/ramdisk.cpio
|
||||
if unpack_and_check_init(magiskboot, workdir, &init_boot_partition, "ramdisk.cpio")? {
|
||||
println!("- Using init_boot partition (ramdisk.cpio).");
|
||||
selected_partition = &init_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/init_boot.cpio
|
||||
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
if unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/init_boot.cpio",
|
||||
)? {
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/init_boot.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/ramdisk.cpio
|
||||
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
if unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/ramdisk.cpio",
|
||||
)? {
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/ramdisk.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
if selected_partition == &boot_partition {
|
||||
println!("- Using boot partition (ramdisk.cpio).");
|
||||
}
|
||||
|
||||
println!("- Bootdevice: {selected_partition}");
|
||||
let tmp_boot_path = workdir.join("boot.img");
|
||||
|
||||
dd(&boot_partition, &tmp_boot_path)?;
|
||||
dd(selected_partition, &tmp_boot_path)?;
|
||||
|
||||
ensure!(tmp_boot_path.exists(), "boot image not found");
|
||||
ensure!(tmp_boot_path.exists(), "- Tmp boot image not found");
|
||||
|
||||
bootimage = tmp_boot_path;
|
||||
bootdevice = Some(boot_partition);
|
||||
bootdevice = Some(selected_partition.to_string());
|
||||
};
|
||||
Ok((bootimage, bootdevice))
|
||||
}
|
||||
|
||||
@@ -370,13 +370,13 @@ pub fn run() -> Result<()> {
|
||||
Commands::BootInfo { command } => match command {
|
||||
BootInfo::CurrentKmi => {
|
||||
let kmi = crate::boot_patch::get_current_kmi()?;
|
||||
println!("{}", kmi);
|
||||
println!("{kmi}");
|
||||
// return here to avoid printing the error message
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::SupportedKmi => {
|
||||
let kmi = crate::assets::list_supported_kmi()?;
|
||||
kmi.iter().for_each(|kmi| println!("{}", kmi));
|
||||
kmi.iter().for_each(|kmi| println!("{kmi}"));
|
||||
return Ok(());
|
||||
}
|
||||
},
|
||||
@@ -388,7 +388,7 @@ pub fn run() -> Result<()> {
|
||||
};
|
||||
|
||||
if let Err(e) = &result {
|
||||
log::error!("Error: {:?}", e);
|
||||
log::error!("Error: {e:?}");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ fn set_kernel_param(uid: u32) -> Result<()> {
|
||||
fn get_pkg_uid(pkg: &str) -> Result<u32> {
|
||||
// stat /data/data/<pkg>
|
||||
let uid = rustix::fs::stat(format!("/data/data/{pkg}"))
|
||||
.with_context(|| format!("stat /data/data/{}", pkg))?
|
||||
.with_context(|| format!("stat /data/data/{pkg}"))?
|
||||
.st_uid;
|
||||
Ok(uid)
|
||||
}
|
||||
|
||||
@@ -44,3 +44,5 @@ pub const NO_TMPFS_PATH: &str = concatcp!(WORKING_DIR, ".notmpfs");
|
||||
pub const NO_MOUNT_PATH: &str = concatcp!(WORKING_DIR, ".nomount");
|
||||
|
||||
pub const MOUNT_SYSTEM: &str = "Magic_Mount";
|
||||
|
||||
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
} else {
|
||||
// Then exec common post-fs-data scripts
|
||||
if let Err(e) = crate::module::exec_common_scripts("post-fs-data.d", true) {
|
||||
warn!("exec common post-fs-data scripts failed: {}", e);
|
||||
warn!("exec common post-fs-data scripts failed: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,21 +41,21 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
if safe_mode {
|
||||
warn!("safe mode, skip post-fs-data scripts and disable all modules!");
|
||||
if let Err(e) = crate::module::disable_all_modules() {
|
||||
warn!("disable all modules failed: {}", e);
|
||||
warn!("disable all modules failed: {e}");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Err(e) = prune_modules() {
|
||||
warn!("prune modules failed: {}", e);
|
||||
warn!("prune modules failed: {e}");
|
||||
}
|
||||
|
||||
if let Err(e) = handle_updated_modules() {
|
||||
warn!("handle updated modules failed: {}", e);
|
||||
warn!("handle updated modules failed: {e}");
|
||||
}
|
||||
|
||||
if let Err(e) = restorecon::restorecon() {
|
||||
warn!("restorecon failed: {}", e);
|
||||
warn!("restorecon failed: {e}");
|
||||
}
|
||||
|
||||
// load sepolicy.rule
|
||||
@@ -64,13 +64,13 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
}
|
||||
|
||||
if let Err(e) = crate::profile::apply_sepolies() {
|
||||
warn!("apply root profile sepolicy failed: {}", e);
|
||||
warn!("apply root profile sepolicy failed: {e}");
|
||||
}
|
||||
|
||||
// mount temp dir
|
||||
if !Path::new(NO_TMPFS_PATH).exists() {
|
||||
if let Err(e) = mount(KSU_MOUNT_SOURCE, TEMP_DIR, "tmpfs", MountFlags::empty(), "") {
|
||||
warn!("do temp dir mount failed: {}", e);
|
||||
warn!("do temp dir mount failed: {e}");
|
||||
}
|
||||
} else {
|
||||
info!("no tmpfs requested");
|
||||
@@ -79,18 +79,18 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
// exec modules post-fs-data scripts
|
||||
// TODO: Add timeout
|
||||
if let Err(e) = crate::module::exec_stage_script("post-fs-data", true) {
|
||||
warn!("exec post-fs-data scripts failed: {}", e);
|
||||
warn!("exec post-fs-data scripts failed: {e}");
|
||||
}
|
||||
|
||||
// load system.prop
|
||||
if let Err(e) = crate::module::load_system_prop() {
|
||||
warn!("load system.prop failed: {}", e);
|
||||
warn!("load system.prop failed: {e}");
|
||||
}
|
||||
|
||||
// mount module systemlessly by magic mount
|
||||
if !Path::new(NO_MOUNT_PATH).exists() {
|
||||
if let Err(e) = mount_modules_systemlessly() {
|
||||
warn!("do systemless mount failed: {}", e);
|
||||
warn!("do systemless mount failed: {e}");
|
||||
}
|
||||
} else {
|
||||
info!("no mount requested");
|
||||
@@ -180,7 +180,7 @@ fn catch_bootlog(logname: &str, command: Vec<&str>) -> Result<()> {
|
||||
};
|
||||
|
||||
if let Err(e) = result {
|
||||
warn!("Failed to start logcat: {:#}", e);
|
||||
warn!("Failed to start logcat: {e:#}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -416,14 +416,14 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
|
||||
|
||||
pub fn magic_mount() -> Result<()> {
|
||||
if let Some(root) = collect_module_files()? {
|
||||
log::debug!("collected: {:#?}", root);
|
||||
log::debug!("collected: {root:#?}");
|
||||
let tmp_dir = PathBuf::from(MAGIC_MOUNT_WORK_DIR);
|
||||
ensure_dir_exists(&tmp_dir)?;
|
||||
mount(KSU_MOUNT_SOURCE, &tmp_dir, "tmpfs", MountFlags::empty(), "").context("mount tmp")?;
|
||||
mount_change(&tmp_dir, MountPropagationFlags::PRIVATE).context("make tmp private")?;
|
||||
let result = do_magic_mount("/", &tmp_dir, root, false);
|
||||
if let Err(e) = unmount(&tmp_dir, UnmountFlags::DETACH) {
|
||||
log::error!("failed to unmount tmp {}", e);
|
||||
log::error!("failed to unmount tmp {e}");
|
||||
}
|
||||
fs::remove_dir(tmp_dir).ok();
|
||||
result
|
||||
|
||||
@@ -258,7 +258,7 @@ pub fn prune_modules() -> Result<()> {
|
||||
let uninstaller = module.join("uninstall.sh");
|
||||
if uninstaller.exists() {
|
||||
if let Err(e) = exec_script(uninstaller, true) {
|
||||
warn!("Failed to exec uninstaller: {}", e);
|
||||
warn!("Failed to exec uninstaller: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,9 +301,6 @@ pub fn install_module(zip: &str) -> Result<()> {
|
||||
fn inner(zip: &str) -> Result<()> {
|
||||
ensure_boot_completed()?;
|
||||
|
||||
// print banner
|
||||
println!(include_str!("banner"));
|
||||
|
||||
assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?;
|
||||
|
||||
// first check if working dir is usable
|
||||
@@ -323,7 +320,7 @@ pub fn install_module(zip: &str) -> Result<()> {
|
||||
module_prop.insert(k, v);
|
||||
},
|
||||
)?;
|
||||
info!("module prop: {:?}", module_prop);
|
||||
info!("module prop: {module_prop:?}");
|
||||
|
||||
let Some(module_id) = module_prop.get("id") else {
|
||||
bail!("module id not found in module.prop!");
|
||||
@@ -401,7 +398,7 @@ pub fn restore_module(id: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_action(id: &str) -> Result<()> {
|
||||
let action_script_path = format!("/data/adb/modules/{}/action.sh", id);
|
||||
let action_script_path = format!("/data/adb/modules/{id}/action.sh");
|
||||
exec_script(&action_script_path, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ pub fn apply_sepolies() -> Result<()> {
|
||||
};
|
||||
let sepolicy = sepolicy.path();
|
||||
if sepolicy::apply_file(&sepolicy).is_ok() {
|
||||
log::info!("profile sepolicy applied: {:?}", sepolicy);
|
||||
log::info!("profile sepolicy applied: {sepolicy:?}");
|
||||
} else {
|
||||
log::info!("profile sepolicy apply failed: {:?}", sepolicy);
|
||||
log::info!("profile sepolicy apply failed: {sepolicy:?}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -697,7 +697,7 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>, strict: bool) -> Resul
|
||||
|
||||
for policy in policies {
|
||||
if !rustix::process::ksu_set_policy(&FfiPolicy::from(policy)) {
|
||||
log::warn!("apply rule: {:?} failed.", statement);
|
||||
log::warn!("apply rule: {statement:?} failed.");
|
||||
if strict {
|
||||
return Err(anyhow::anyhow!("apply rule {:?} failed.", statement));
|
||||
}
|
||||
|
||||
@@ -261,7 +261,9 @@ pub fn root_shell() -> Result<()> {
|
||||
|
||||
// switch to global mount namespace
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
if mount_master {
|
||||
let global_namespace_enable =
|
||||
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE).unwrap_or("0".to_string());
|
||||
if global_namespace_enable.trim() == "1" || mount_master {
|
||||
let _ = utils::switch_mnt_ns(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,12 +104,12 @@ pub fn is_safe_mode() -> bool {
|
||||
|| getprop("ro.sys.safemode")
|
||||
.filter(|prop| prop == "1")
|
||||
.is_some();
|
||||
log::info!("safemode: {}", safemode);
|
||||
log::info!("safemode: {safemode}");
|
||||
if safemode {
|
||||
return true;
|
||||
}
|
||||
let safemode = ksucalls::check_kernel_safemode();
|
||||
log::info!("kernel_safemode: {}", safemode);
|
||||
log::info!("kernel_safemode: {safemode}");
|
||||
safemode
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
_ __ _ ____ _ _
|
||||
| |/ /___ _ __ _ __ ___| / ___|| | | |
|
||||
| ' // _ \ '__| '_ \ / _ \ \___ \| | | |
|
||||
| . \ __/ | | | | | __/ |___) | |_| |
|
||||
|_|\_\___|_| |_| |_|\___|_|____/ \___/
|
||||
| \ | | _____ _| |_
|
||||
| \| |/ _ \ \/ / __|
|
||||
| |\ | __/> <| |_
|
||||
|_| \_|\___/_/\_\\__|
|
||||
@@ -310,7 +310,7 @@ pub fn restore(
|
||||
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
|
||||
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?;
|
||||
let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?;
|
||||
|
||||
println!("- Unpacking boot image");
|
||||
let status = Command::new(&magiskboot)
|
||||
@@ -323,21 +323,21 @@ pub fn restore(
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
// let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let no_vendor_init_boot = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("ramdisk.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_init_boot =
|
||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_ramdisk =
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
is_kernelsu_patched || is_kernelsu_patched_vendor_init_boot || is_kernelsu_patched_vendor_ramdisk,
|
||||
is_kernelsu_patched
|
||||
|| is_kernelsu_patched_vendor_init_boot
|
||||
|| is_kernelsu_patched_vendor_ramdisk,
|
||||
"boot image is not patched by KernelSU Next"
|
||||
);
|
||||
|
||||
@@ -349,7 +349,7 @@ pub fn restore(
|
||||
do_cpio_cmd(
|
||||
&magiskboot,
|
||||
workdir,
|
||||
&format!("extract {0} {0}", BACKUP_FILENAME),
|
||||
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
|
||||
let sha = String::from_utf8(sha)?;
|
||||
@@ -371,41 +371,78 @@ pub fn restore(
|
||||
}
|
||||
|
||||
if new_boot.is_none() {
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
// vendor init_boot restore
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_init_boot)?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
// vendor ramdisk restore
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !no_ramdisk {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Restoring /vendor_ramdisk/init_boot");
|
||||
println!("- Removing /vendor_ramdisk/init_boot/kernelsu.ko");
|
||||
// vendor init_boot restore
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
println!("- Checking if init.real exists");
|
||||
let status =
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/init_boot/init.real to init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/init_boot.cpio");
|
||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_init_boot)?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk");
|
||||
println!("- Removing /vendor_ramdisk/ramdisk/kernelsu.ko");
|
||||
// vendor ramdisk restore
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk/init.real to init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/ramdisk.cpio");
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
} else {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
@@ -483,8 +520,6 @@ fn do_patch(
|
||||
magiskboot_path: Option<PathBuf>,
|
||||
kmi: Option<String>,
|
||||
) -> Result<()> {
|
||||
println!(include_str!("banner"));
|
||||
|
||||
let patch_file = image.is_some();
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -516,7 +551,7 @@ fn do_patch(
|
||||
match get_current_kmi() {
|
||||
Ok(value) => value,
|
||||
Err(e) => {
|
||||
println!("- {}", e);
|
||||
println!("- {e}");
|
||||
if let Some(image_path) = &image {
|
||||
println!(
|
||||
"- Trying to auto detect KMI version for {}",
|
||||
@@ -539,7 +574,7 @@ fn do_patch(
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
|
||||
let (bootimage, bootdevice) =
|
||||
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;
|
||||
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir, &magiskboot)?;
|
||||
|
||||
let bootimage = bootimage.display().to_string();
|
||||
|
||||
@@ -585,20 +620,19 @@ fn do_patch(
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("ramdisk.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
if no_ramdisk && no_vendor_init_boot && no_vendor_ramdisk {
|
||||
bail!("No compatible ramdisk found.");
|
||||
println!("- No compatible ramdisk found.");
|
||||
println!("- Will create our own ramdisk!");
|
||||
}
|
||||
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_init_boot =
|
||||
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_ramdisk =
|
||||
is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_ramdisk = is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
!is_magisk_patched || !is_magisk_patched_vendor_init_boot || !is_magisk_patched_vendor_ramdisk,
|
||||
!is_magisk_patched
|
||||
|| !is_magisk_patched_vendor_init_boot
|
||||
|| !is_magisk_patched_vendor_ramdisk,
|
||||
"Cannot work with Magisk patched image"
|
||||
);
|
||||
|
||||
@@ -610,41 +644,59 @@ fn do_patch(
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
|
||||
let mut need_backup = false;
|
||||
if !is_kernelsu_patched || (no_ramdisk && !is_kernelsu_patched_vendor_init_boot) || (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|
||||
if (no_ramdisk && !is_kernelsu_patched_vendor_init_boot)
|
||||
|| (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|
||||
|| !is_kernelsu_patched
|
||||
{
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
// vendor init_boot patching
|
||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
// vendor ramdisk patching
|
||||
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
if !no_ramdisk {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Checking if /vendor_ramdisk/init_boot/init exists");
|
||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/init_boot/init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Checking if /vendor_ramdisk/ramdisk/init exists");
|
||||
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/ramdisk/init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
}
|
||||
}
|
||||
|
||||
if no_ramdisk {
|
||||
if !no_vendor_init_boot {
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_ramdisk {
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
if !no_ramdisk {
|
||||
println!("- Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Patching /vendor_ramdisk/init_boot");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Patching /vendor_ramdisk/ramdisk");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
|
||||
} else {
|
||||
println!("- Creating and Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
@@ -714,7 +766,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
|
||||
}
|
||||
|
||||
let result = hasher.finalize();
|
||||
Ok(format!("{:x}", result))
|
||||
Ok(format!("{result:x}"))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -730,7 +782,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
do_cpio_cmd(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&format!("add 0755 {0} {0}", BACKUP_FILENAME),
|
||||
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
println!("- Stock image has been backup to");
|
||||
println!("- {target}");
|
||||
@@ -740,7 +792,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
#[cfg(target_os = "android")]
|
||||
fn clean_backup(sha1: &str) -> Result<()> {
|
||||
println!("- Clean up backup");
|
||||
let backup_name = format!("{}{}", KSU_BACKUP_FILE_PREFIX, sha1);
|
||||
let backup_name = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
|
||||
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
|
||||
for entry in dir.flatten() {
|
||||
let path = entry.path();
|
||||
@@ -803,16 +855,17 @@ fn find_boot_image(
|
||||
ota: bool,
|
||||
is_replace_kernel: bool,
|
||||
workdir: &Path,
|
||||
magiskboot: &Path,
|
||||
) -> Result<(PathBuf, Option<String>)> {
|
||||
let bootimage;
|
||||
let mut bootdevice = None;
|
||||
if let Some(ref image) = *image {
|
||||
ensure!(image.exists(), "boot image not found");
|
||||
ensure!(image.exists(), "- Boot image not found");
|
||||
bootimage = std::fs::canonicalize(image)?;
|
||||
} else {
|
||||
if cfg!(not(target_os = "android")) {
|
||||
println!("- Current OS is not android, refusing auto bootimage/bootdevice detection");
|
||||
bail!("Please specify a boot image");
|
||||
bail!("- Please specify a boot image");
|
||||
}
|
||||
let mut slot_suffix =
|
||||
utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
|
||||
@@ -825,27 +878,104 @@ fn find_boot_image(
|
||||
}
|
||||
};
|
||||
|
||||
let init_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
|
||||
let vendor_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
|
||||
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/init_boot{slot_suffix}")
|
||||
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
|
||||
} else {
|
||||
format!("/dev/block/by-name/boot{slot_suffix}")
|
||||
};
|
||||
let init_boot_partition = format!("/dev/block/by-name/init_boot{slot_suffix}");
|
||||
let vendor_boot_partition = format!("/dev/block/by-name/vendor_boot{slot_suffix}");
|
||||
let boot_partition = format!("/dev/block/by-name/boot{slot_suffix}");
|
||||
|
||||
println!("- Bootdevice: {boot_partition}");
|
||||
let init_boot_exist = Path::new(&init_boot_partition).exists();
|
||||
let vendor_boot_exist = Path::new(&vendor_boot_partition).exists();
|
||||
|
||||
// helper: unpack a partition and check for a ramdisk and init
|
||||
fn unpack_and_check_init(
|
||||
magiskboot: &Path,
|
||||
workdir: &Path,
|
||||
partition: &str,
|
||||
ramdisk_cpio: &str,
|
||||
) -> Result<bool> {
|
||||
let tmp_img = workdir.join("probe.img");
|
||||
dd(partition, &tmp_img)?;
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("unpack")
|
||||
.arg(&tmp_img)
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
return Ok(false);
|
||||
}
|
||||
let ramdisk_path = workdir.join(ramdisk_cpio);
|
||||
let has_init = if ramdisk_path.exists() {
|
||||
Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(ramdisk_cpio)
|
||||
.arg("exists init")
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Clean up
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
let _ = std::fs::remove_file(workdir.join("ramdisk.cpio"));
|
||||
let _ = std::fs::remove_dir_all(workdir.join("vendor_ramdisk"));
|
||||
Ok(has_init)
|
||||
}
|
||||
|
||||
let mut selected_partition = &boot_partition;
|
||||
|
||||
if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
// try init_boot/ramdisk.cpio
|
||||
if unpack_and_check_init(magiskboot, workdir, &init_boot_partition, "ramdisk.cpio")? {
|
||||
println!("- Using init_boot partition (ramdisk.cpio).");
|
||||
selected_partition = &init_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/init_boot.cpio
|
||||
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
if unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/init_boot.cpio",
|
||||
)? {
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/init_boot.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/ramdisk.cpio
|
||||
if selected_partition == &boot_partition && !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
if unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/ramdisk.cpio",
|
||||
)? {
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/ramdisk.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
if selected_partition == &boot_partition {
|
||||
println!("- Using boot partition (ramdisk.cpio).");
|
||||
}
|
||||
|
||||
println!("- Bootdevice: {selected_partition}");
|
||||
let tmp_boot_path = workdir.join("boot.img");
|
||||
|
||||
dd(&boot_partition, &tmp_boot_path)?;
|
||||
dd(selected_partition, &tmp_boot_path)?;
|
||||
|
||||
ensure!(tmp_boot_path.exists(), "boot image not found");
|
||||
ensure!(tmp_boot_path.exists(), "- Tmp boot image not found");
|
||||
|
||||
bootimage = tmp_boot_path;
|
||||
bootdevice = Some(boot_partition);
|
||||
bootdevice = Some(selected_partition.to_string());
|
||||
};
|
||||
Ok((bootimage, bootdevice))
|
||||
}
|
||||
|
||||
@@ -385,13 +385,13 @@ pub fn run() -> Result<()> {
|
||||
Commands::BootInfo { command } => match command {
|
||||
BootInfo::CurrentKmi => {
|
||||
let kmi = crate::boot_patch::get_current_kmi()?;
|
||||
println!("{}", kmi);
|
||||
println!("{kmi}");
|
||||
// return here to avoid printing the error message
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::SupportedKmi => {
|
||||
let kmi = crate::assets::list_supported_kmi()?;
|
||||
kmi.iter().for_each(|kmi| println!("{}", kmi));
|
||||
kmi.iter().for_each(|kmi| println!("{kmi}"));
|
||||
return Ok(());
|
||||
}
|
||||
},
|
||||
@@ -403,7 +403,7 @@ pub fn run() -> Result<()> {
|
||||
};
|
||||
|
||||
if let Err(e) = &result {
|
||||
log::error!("Error: {:?}", e);
|
||||
log::error!("Error: {e:?}");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ fn set_kernel_param(uid: u32) -> Result<()> {
|
||||
fn get_pkg_uid(pkg: &str) -> Result<u32> {
|
||||
// stat /data/data/<pkg>
|
||||
let uid = rustix::fs::stat(format!("/data/data/{pkg}"))
|
||||
.with_context(|| format!("stat /data/data/{}", pkg))?
|
||||
.with_context(|| format!("stat /data/data/{pkg}"))?
|
||||
.st_uid;
|
||||
Ok(uid)
|
||||
}
|
||||
|
||||
@@ -47,3 +47,5 @@ pub const KSU_BACKUP_FILE_PREFIX: &str = "ksu_backup_";
|
||||
pub const BACKUP_FILENAME: &str = "stock_image.sha1";
|
||||
|
||||
pub const MOUNT_SYSTEM: &str = "OverlayFS";
|
||||
|
||||
pub const GLOBAL_NAMESPACE_FILE: &str = concatcp!(WORKING_DIR, ".global_mnt");
|
||||
|
||||
@@ -83,13 +83,13 @@ pub fn mount_modules_systemlessly(module_dir: &str) -> Result<()> {
|
||||
|
||||
// mount /system first
|
||||
if let Err(e) = mount_partition("system", &system_lowerdir) {
|
||||
warn!("mount system failed: {:#}", e);
|
||||
warn!("mount system failed: {e:#}");
|
||||
}
|
||||
|
||||
// mount other partitions
|
||||
for (k, v) in partition_lowerdir {
|
||||
if let Err(e) = mount_partition(&k, &v) {
|
||||
warn!("mount {k} failed: {:#}", e);
|
||||
warn!("mount {k} failed: {e:#}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
} else {
|
||||
// Then exec common post-fs-data scripts
|
||||
if let Err(e) = crate::module::exec_common_scripts("post-fs-data.d", true) {
|
||||
warn!("exec common post-fs-data scripts failed: {}", e);
|
||||
warn!("exec common post-fs-data scripts failed: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,17 +168,17 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
if safe_mode {
|
||||
warn!("safe mode, skip post-fs-data scripts and disable all modules!");
|
||||
if let Err(e) = crate::module::disable_all_modules() {
|
||||
warn!("disable all modules failed: {}", e);
|
||||
warn!("disable all modules failed: {e}");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Err(e) = prune_modules() {
|
||||
warn!("prune modules failed: {}", e);
|
||||
warn!("prune modules failed: {e}");
|
||||
}
|
||||
|
||||
if let Err(e) = restorecon::restorecon() {
|
||||
warn!("restorecon failed: {}", e);
|
||||
warn!("restorecon failed: {e}");
|
||||
}
|
||||
|
||||
// load sepolicy.rule
|
||||
@@ -187,28 +187,28 @@ pub fn on_post_data_fs() -> Result<()> {
|
||||
}
|
||||
|
||||
if let Err(e) = crate::profile::apply_sepolies() {
|
||||
warn!("apply root profile sepolicy failed: {}", e);
|
||||
warn!("apply root profile sepolicy failed: {e}");
|
||||
}
|
||||
|
||||
// mount temp dir
|
||||
if let Err(e) = mount::mount_tmpfs(utils::get_tmp_path()) {
|
||||
warn!("do temp dir mount failed: {}", e);
|
||||
warn!("do temp dir mount failed: {e}");
|
||||
}
|
||||
|
||||
// exec modules post-fs-data scripts
|
||||
// TODO: Add timeout
|
||||
if let Err(e) = crate::module::exec_stage_script("post-fs-data", true) {
|
||||
warn!("exec post-fs-data scripts failed: {}", e);
|
||||
warn!("exec post-fs-data scripts failed: {e}");
|
||||
}
|
||||
|
||||
// load system.prop
|
||||
if let Err(e) = crate::module::load_system_prop() {
|
||||
warn!("load system.prop failed: {}", e);
|
||||
warn!("load system.prop failed: {e}");
|
||||
}
|
||||
|
||||
// mount module systemlessly by overlay
|
||||
if let Err(e) = mount_modules_systemlessly(module_dir) {
|
||||
warn!("do systemless mount failed: {}", e);
|
||||
warn!("do systemless mount failed: {e}");
|
||||
}
|
||||
|
||||
run_stage("post-mount", true);
|
||||
@@ -298,7 +298,7 @@ fn catch_bootlog(logname: &str, command: Vec<&str>) -> Result<()> {
|
||||
};
|
||||
|
||||
if let Err(e) = result {
|
||||
warn!("Failed to start logcat: {:#}", e);
|
||||
warn!("Failed to start logcat: {e:#}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -274,7 +274,7 @@ pub fn prune_modules() -> Result<()> {
|
||||
let uninstaller = module.join("uninstall.sh");
|
||||
if uninstaller.exists() {
|
||||
if let Err(e) = exec_script(uninstaller, true) {
|
||||
warn!("Failed to exec uninstaller: {}", e);
|
||||
warn!("Failed to exec uninstaller: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,9 +324,6 @@ fn create_module_image(image: &str, image_size: u64) -> Result<()> {
|
||||
fn _install_module(zip: &str) -> Result<()> {
|
||||
ensure_boot_completed()?;
|
||||
|
||||
// print banner
|
||||
println!(include_str!("banner"));
|
||||
|
||||
assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?;
|
||||
|
||||
// first check if workding dir is usable
|
||||
@@ -346,7 +343,7 @@ fn _install_module(zip: &str) -> Result<()> {
|
||||
module_prop.insert(k, v);
|
||||
},
|
||||
)?;
|
||||
info!("module prop: {:?}", module_prop);
|
||||
info!("module prop: {module_prop:?}");
|
||||
|
||||
let Some(module_id) = module_prop.get("id") else {
|
||||
bail!("module id not found in module.prop!");
|
||||
@@ -475,13 +472,13 @@ fn _install_module(zip: &str) -> Result<()> {
|
||||
|
||||
let _dontdrop = mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true)?;
|
||||
|
||||
info!("mounted {} to {}", tmp_module_img, module_update_tmp_dir);
|
||||
info!("mounted {tmp_module_img} to {module_update_tmp_dir}");
|
||||
|
||||
setsyscon(module_update_tmp_dir)?;
|
||||
|
||||
let module_dir = format!("{module_update_tmp_dir}/{module_id}");
|
||||
ensure_clean_dir(&module_dir)?;
|
||||
info!("module dir: {}", module_dir);
|
||||
info!("module dir: {module_dir}");
|
||||
|
||||
// unzip the image and move it to modules_update/<id> dir
|
||||
let file = File::open(zip)?;
|
||||
@@ -673,7 +670,7 @@ pub fn restore_module(id: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_action(id: &str) -> Result<()> {
|
||||
let action_script_path = format!("/data/adb/modules/{}/action.sh", id);
|
||||
let action_script_path = format!("/data/adb/modules/{id}/action.sh");
|
||||
exec_script(&action_script_path, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ pub fn mount_overlayfs(
|
||||
})();
|
||||
|
||||
if let Err(e) = result {
|
||||
warn!("fsopen mount failed: {:#}, fallback to mount", e);
|
||||
warn!("fsopen mount failed: {e:#}, fallback to mount");
|
||||
let mut data = format!("lowerdir={lowerdir_config}");
|
||||
if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) {
|
||||
data = format!("{data},upperdir={upperdir},workdir={workdir}");
|
||||
@@ -246,7 +246,7 @@ fn mount_overlay_child(
|
||||
}
|
||||
// merge modules and stock
|
||||
if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) {
|
||||
warn!("failed: {:#}, fallback to bind mount", e);
|
||||
warn!("failed: {e:#}, fallback to bind mount");
|
||||
bind_mount(stock_root, mount_point)?;
|
||||
}
|
||||
Ok(())
|
||||
@@ -259,7 +259,7 @@ pub fn mount_overlay(
|
||||
workdir: Option<PathBuf>,
|
||||
upperdir: Option<PathBuf>,
|
||||
) -> Result<()> {
|
||||
info!("mount overlay for {}", root);
|
||||
info!("mount overlay for {root}");
|
||||
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
|
||||
let stock_root = ".";
|
||||
|
||||
@@ -290,10 +290,7 @@ pub fn mount_overlay(
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = mount_overlay_child(mount_point, &relative, module_roots, &stock_root) {
|
||||
warn!(
|
||||
"failed to mount overlay for child {}: {:#}, revert",
|
||||
mount_point, e
|
||||
);
|
||||
warn!("failed to mount overlay for child {mount_point}: {e:#}, revert");
|
||||
umount_dir(root).with_context(|| format!("failed to revert {root}"))?;
|
||||
bail!(e);
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ pub fn apply_sepolies() -> Result<()> {
|
||||
};
|
||||
let sepolicy = sepolicy.path();
|
||||
if sepolicy::apply_file(&sepolicy).is_ok() {
|
||||
log::info!("profile sepolicy applied: {:?}", sepolicy);
|
||||
log::info!("profile sepolicy applied: {sepolicy:?}");
|
||||
} else {
|
||||
log::info!("profile sepolicy apply failed: {:?}", sepolicy);
|
||||
log::info!("profile sepolicy apply failed: {sepolicy:?}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -697,7 +697,7 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>, strict: bool) -> Resul
|
||||
|
||||
for policy in policies {
|
||||
if !rustix::process::ksu_set_policy(&FfiPolicy::from(policy)) {
|
||||
log::warn!("apply rule: {:?} failed.", statement);
|
||||
log::warn!("apply rule: {statement:?} failed.");
|
||||
if strict {
|
||||
return Err(anyhow::anyhow!("apply rule {:?} failed.", statement));
|
||||
}
|
||||
|
||||
@@ -261,7 +261,9 @@ pub fn root_shell() -> Result<()> {
|
||||
|
||||
// switch to global mount namespace
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
if mount_master {
|
||||
let global_namespace_enable =
|
||||
std::fs::read_to_string(defs::GLOBAL_NAMESPACE_FILE).unwrap_or("0".to_string());
|
||||
if global_namespace_enable.trim() == "1" || mount_master {
|
||||
let _ = utils::switch_mnt_ns(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,12 +110,12 @@ pub fn is_safe_mode() -> bool {
|
||||
|| getprop("ro.sys.safemode")
|
||||
.filter(|prop| prop == "1")
|
||||
.is_some();
|
||||
log::info!("safemode: {}", safemode);
|
||||
log::info!("safemode: {safemode}");
|
||||
if safemode {
|
||||
return true;
|
||||
}
|
||||
let safemode = ksucalls::check_kernel_safemode();
|
||||
log::info!("kernel_safemode: {}", safemode);
|
||||
log::info!("kernel_safemode: {safemode}");
|
||||
safemode
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ pub fn get_tmp_path() -> &'static str {
|
||||
|
||||
CHOSEN_TMP_PATH.get_or_init(|| {
|
||||
let r = find_temp_path();
|
||||
log::info!("Chosen temp_path: {}", r);
|
||||
log::info!("Chosen temp_path: {r}");
|
||||
r
|
||||
})
|
||||
}
|
||||
@@ -367,7 +367,7 @@ fn copy_xattrs(src_path: impl AsRef<Path>, dest_path: impl AsRef<Path>) -> Resul
|
||||
if let Err(e) =
|
||||
extattr::lsetxattr(dest_path.as_ref(), &xattr, &value, extattr::Flags::empty())
|
||||
{
|
||||
log::warn!("Failed to set xattr: {}", e);
|
||||
log::warn!("Failed to set xattr: {e}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -400,7 +400,7 @@ pub fn copy_module_files(source: impl AsRef<Path>, destination: impl AsRef<Path>
|
||||
std::fs::remove_file(&dest_path).context("Failed to remove file")?;
|
||||
}
|
||||
let target = std::fs::read_link(entry.path()).context("Failed to read symlink")?;
|
||||
log::info!("Symlink: {:?} -> {:?}", dest_path, target);
|
||||
log::info!("Symlink: {dest_path:?} -> {target:?}");
|
||||
std::os::unix::fs::symlink(target, &dest_path).context("Failed to create symlink")?;
|
||||
copy_xattrs(&source_path, &dest_path)?;
|
||||
} else if entry.file_type().is_dir() {
|
||||
|
||||
@@ -1,11 +1,54 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
// This is a simple example. If you want a full-featured "su", please use "/data/adb/ksud debug su".
|
||||
int main(){
|
||||
int32_t result = 0;
|
||||
prctl(0xdeadbeef, 0, 0, 0, &result);
|
||||
system("/system/bin/sh");
|
||||
return 0;
|
||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||
#define CMD_GRANT_ROOT 0
|
||||
#define CMD_ENABLE_SU 15
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
unsigned long result = 0;
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "--disable-sucompat") == 0) {
|
||||
prctl(KERNEL_SU_OPTION, CMD_ENABLE_SU, 0L, 0L, (unsigned long)&result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prctl(KERNEL_SU_OPTION, CMD_GRANT_ROOT, 0L, 0L, (unsigned long)&result);
|
||||
if (result != KERNEL_SU_OPTION) {
|
||||
const char *error = "Access Denied: sucompat not permitted\n";
|
||||
write(STDERR_FILENO, error, strlen(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct termios term;
|
||||
if (ioctl(STDIN_FILENO, TCGETS, &term) == 0) {
|
||||
char tty_path[PATH_MAX];
|
||||
ssize_t len = readlink("/proc/self/fd/0", tty_path, sizeof(tty_path) - 1);
|
||||
if (len > 0) {
|
||||
tty_path[len] = '\0';
|
||||
const char *selinux_ctx = "u:object_r:devpts:s0";
|
||||
setxattr(tty_path, "security.selinux", selinux_ctx, strlen(selinux_ctx) + 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const char *default_args[] = { "/system/bin/su", NULL };
|
||||
if (argc < 1 || !argv) {
|
||||
argv = (char **)default_args;
|
||||
} else {
|
||||
argv[0] = "/system/bin/su";
|
||||
}
|
||||
|
||||
execve("/data/adb/ksud", argv, envp);
|
||||
|
||||
const char *error = "Error: Failed to execve /data/adb/ksud\n";
|
||||
write(STDERR_FILENO, error, strlen(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -104,52 +104,77 @@ int main(int argc, char *argv[]) {
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, enabled_features, bufsize, &error);
|
||||
printf("%s\n", error || !strlen(enabled_features) ? "Unsupported" : "Supported");
|
||||
free(enabled_features);
|
||||
} else if (argc == 3 && !strcmp(argv[1], "sus_su")) {
|
||||
int last_working_mode = 0;
|
||||
int target_working_mode;
|
||||
char* endptr;
|
||||
} else if (argc >= 2 && !strcmp(argv[1], "sus_su")) {
|
||||
if (argc == 3 && strcmp(argv[2], "support") == 0) {
|
||||
char *enabled_features;
|
||||
size_t bufsize = getpagesize() * 2;
|
||||
enabled_features = (char *)malloc(bufsize);
|
||||
if (!enabled_features) {
|
||||
perror("malloc");
|
||||
return -ENOMEM;
|
||||
}
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, enabled_features, bufsize, &error);
|
||||
if (!error && strstr(enabled_features, "CONFIG_KSU_SUSFS_SUS_SU")) {
|
||||
printf("Supported\n");
|
||||
} else {
|
||||
printf("Unsupported\n");
|
||||
}
|
||||
free(enabled_features);
|
||||
return 0;
|
||||
} else if (argc == 3) {
|
||||
int last_working_mode = 0;
|
||||
int target_working_mode;
|
||||
char *endptr;
|
||||
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!strcmp(argv[2], "mode")) {
|
||||
printf("%d\n", last_working_mode);
|
||||
return 0;
|
||||
}
|
||||
target_working_mode = strtol(argv[2], &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
return 1;
|
||||
}
|
||||
if (target_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
bool is_sus_su_ready;
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!is_sus_su_ready) {
|
||||
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
|
||||
return 1;
|
||||
}
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
} else {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
if (!error)
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
}
|
||||
} else if (target_working_mode == SUS_SU_DISABLED) {
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
}
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
}
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!strcmp(argv[2], "mode")) {
|
||||
printf("%d\n", last_working_mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_working_mode = strtol(argv[2], &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (target_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
bool is_sus_su_ready;
|
||||
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!is_sus_su_ready) {
|
||||
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
} else {
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
if (!error)
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
|
||||
}
|
||||
} else if (target_working_mode == SUS_SU_DISABLED) {
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
printf("[-] sus_su is already in mode %d\n", last_working_mode);
|
||||
return 1;
|
||||
}
|
||||
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s sus_su <0|2|mode|support>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user