Compare commits

...

114 Commits

Author SHA1 Message Date
topjohnwu
a34c04f999 Release new canary build 2024-12-01 14:59:57 -08:00
topjohnwu
da43ac89a0 Allow all domains to access tmpfs files
Fix #8457
2024-11-30 23:21:33 -08:00
vvb2060
830fc758b9 init: Use apex dir to determine whether 2SI 2024-11-30 23:03:29 -08:00
vvb2060
0f3cfef278 Revert "init: support 2SI devices with skip_initramfs"
This reverts commit b38fd1ca5f.
2024-11-30 23:03:29 -08:00
topjohnwu
b32d7bfafd Update gradle version 2024-11-21 21:05:35 -08:00
topjohnwu
c0899f2939 Update dependencies 2024-11-19 20:29:15 -08:00
topjohnwu
082330808f Fix building APK 2024-11-19 20:25:10 -08:00
topjohnwu
024da05888 Move several stuff into buildSrc 2024-11-09 20:08:12 -08:00
LoveSy
377b6d0cc2 avoid desugar the Desugar class 2024-11-09 19:41:06 -08:00
Georgi Boiko
c661009b31 docs(ci): update setup action to state correct jdk version 2024-11-04 11:12:01 -08:00
vvb2060
613f2d31c5 app: auto close action fragment only when focus lost 2024-11-04 11:11:41 -08:00
vvb2060
7dbb973db5 daemon: some samsung devices using incorrect mediatek-res path 2024-11-04 11:09:53 -08:00
topjohnwu
f4502f8be8 Add our own API desugaring
Some checks failed
Magisk Build / Build Magisk artifacts (push) Has been cancelled
Magisk Build / Test building on ${{ matrix.os }} (ubuntu-latest) (push) Has been cancelled
Magisk Build / Test building on ${{ matrix.os }} (windows-latest) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 23) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 24) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 25) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 26) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 27) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 28) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 29) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 30) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 31) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 32) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 33) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (, 34) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86_64) (google_apis, 35) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (23) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (24) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (25) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (26) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (27) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (28) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (29) (push) Has been cancelled
Magisk Build / Test API ${{ matrix.version }} (x86) (30) (push) Has been cancelled
Magisk Build / Test ${{ matrix.device }} (aosp-main, aosp_cf_x86_64_phone) (push) Has been cancelled
Magisk Build / Test ${{ matrix.device }} (aosp-main-throttled, aosp_cf_x86_64_phone_pgagnostic) (push) Has been cancelled
Fix #8452
2024-10-29 12:13:22 -07:00
topjohnwu
455b13b83c Fix download URL in stub.apk 2024-10-17 19:42:10 -07:00
topjohnwu
8b98709743 Update dependencies 2024-10-17 13:17:46 -07:00
tzagim
1b12f45f39 Update Hebrew Translation 2024-10-15 15:23:21 -07:00
vvb2060
a5cad532ff ui: fix lock screen orientation 2024-10-12 01:16:24 -07:00
topjohnwu
070719db50 Release new canary build 2024-10-10 02:10:50 -07:00
topjohnwu
28cccdf7aa Release Magisk v28.0 2024-10-10 01:47:00 -07:00
topjohnwu
b7e0986a5c Add v28.0 changelog 2024-10-10 01:40:14 -07:00
topjohnwu
da709745dd Revert #8245 2024-10-09 15:40:23 -07:00
topjohnwu
8b6771d487 Update dependencies 2024-10-08 01:40:09 -07:00
topjohnwu
e1b847fbc5 Find boot image with MagiskInstaller
Fix #8211
2024-10-07 16:52:35 -07:00
topjohnwu
7188de1205 Support unaligned boot image file
Fix #7733
2024-10-06 03:01:08 -07:00
topjohnwu
44fb7dbcbe Update Busybox
Fix #8403
2024-10-06 01:47:13 -07:00
topjohnwu
8086b5933c Update crt0
Fix #8424
2024-10-02 16:37:07 -07:00
topjohnwu
7f675f4bf7 Update dependencies 2024-09-27 14:38:32 -07:00
vvb2060
5e6b53e0da AppMigration: put suManager after installation 2024-09-25 12:34:21 -07:00
残页
5b29fefc65 Replace LOGE with LOGW so the process don't abort
Co-authored-by: 南宫雪珊 <vvb2060@gmail.com>
2024-09-25 11:59:58 -07:00
残页
16a168535d Check sepolicy database version in add_xperm_rule
Fix #8344
2024-09-25 11:59:58 -07:00
Wang Han
33f70f8f6d Update zh-rCN strings 2024-09-17 15:01:10 -07:00
topjohnwu
4f18a66d73 Release new canary build 2024-09-17 01:46:04 -07:00
Wang Han
250dc16007 Fix post-fs-data blocking time in doc
f7d3d1eeaf.
2024-09-17 01:28:01 -07:00
Wang Han
7af273e047 Don't append "start logd" in post-fs-data
This was first done in b13eb3f because magiskd was started in
post-fs stage that time. Among all android versions, logd was all
started before post-fs-data.
2024-09-16 00:30:36 -07:00
Arbri çoçka
e381aebaa0 Update strings.xml Albania (sq) 2024-09-16 00:24:47 -07:00
LoveSy
45d91c9658 Upgrade Gradle 2024-09-15 00:14:15 -07:00
igor
4a9158f667 Update Portuguese translation 2024-09-14 23:08:40 -07:00
niels
0d9ee89e7f magiskboot: cleanup bootconfig and vendor ramdisk dir 2024-09-14 23:08:22 -07:00
topjohnwu
abaff72304 Enable core library desugaring
Fix #8343
2024-09-09 01:59:32 -07:00
topjohnwu
b828e2d0b2 Update dependencies 2024-09-08 03:02:09 -07:00
Wang Han
53d7cbc11b Clarify magiskboot requirements for repacking img 2024-09-08 01:13:46 -07:00
LoveSy
310be7ab47 Return exit value of action.sh 2024-09-08 01:12:30 -07:00
LoveSy
60894e458f Automatically close action fragment when action exits successfully 2024-09-08 01:12:30 -07:00
LoveSy
fbebb6ac10 Add action.sh for user to manually trigger modules' functionality from app 2024-09-08 01:12:30 -07:00
LoveSy
a9f8c20703 Upgrade AGP 2024-09-05 21:50:56 -07:00
vvb2060
ae0b15d197 deps: update gradle to 8.10 2024-09-05 21:50:46 -07:00
vvb2060
869aa62328 ci: fix build 2024-09-05 21:50:46 -07:00
vvb2060
dcd3bc58a3 app: target api 35 2024-09-05 21:50:46 -07:00
Salvo Giangreco
a82f17c594 Disable Samsung PROCA
Signed-off-by: Salvo Giangreco <giangrecosalvo9@gmail.com>
2024-09-04 01:49:02 -07:00
vvb2060
b38fd1ca5f init: support 2SI devices with skip_initramfs 2024-09-03 16:33:57 -07:00
topjohnwu
8e82113bce Release new canary build 2024-08-23 01:07:45 -07:00
vvb2060
f723ef153b zygisk_node: skip magisk32 if 64bit zygote only 2024-08-22 11:58:29 -07:00
topjohnwu
1dc723fb6d Attempt to reuse cache on Windows 2024-08-21 22:06:12 -07:00
topjohnwu
8f271c2575 Custom sccache support in CI 2024-08-21 16:51:30 -07:00
topjohnwu
7cf56b4406 Simplify ramdisk test 2024-08-21 16:46:37 -07:00
Wang Han
c2eb603957 Require GMS to be system app
Fixes https://github.com/topjohnwu/Magisk/issues/8279.
2024-08-20 10:36:14 -07:00
topjohnwu
e6bd2ff60f Fix stock image restore
Fix #8211
2024-08-20 02:23:20 -07:00
topjohnwu
5604074eba Fix module auto install
Fix #8208
2024-08-20 01:09:25 -07:00
topjohnwu
3f061c1a1e Update dependencies 2024-08-19 17:54:02 -07:00
LoveSy
55e78a7b1a BYD XDJA container support 2024-08-19 17:50:16 -07:00
vvb2060
000f1d6041 Revert "Don't support alternative binary paths"
This reverts commit 1eeb2a34a1.
2024-08-19 11:52:55 -07:00
vvb2060
2cbec20238 find_boot_image: test GKI 1.0 2024-08-19 03:05:24 -07:00
vvb2060
4b724c7257 find_boot_image: test previous kernels (<=4.19) 2024-08-19 03:05:24 -07:00
vvb2060
ab04c6ab39 find_boot_image: keep symlink 2024-08-19 03:05:24 -07:00
topjohnwu
821a6c6954 Only save gradle cache on asset build job 2024-08-18 21:42:28 -07:00
topjohnwu
5f27a62221 Use gradle version catalog 2024-08-18 13:12:23 -07:00
topjohnwu
c76cc4c6bd Update cuttlefish hostside tools 2024-08-16 15:58:29 -07:00
𝗦𝗵𝗟𝗲𝗿𝗣
52b75c53b6 Update TR Locales 2024-08-16 11:38:36 -07:00
topjohnwu
9db2e99086 Test 16k on Cuttlefish 2024-08-15 22:51:40 -07:00
LoveSy
e9e2ecf2dd load partition_map only once 2024-08-15 10:10:18 -07:00
LoveSy
9a9e617c35 Use find_if 2024-08-15 10:10:18 -07:00
LoveSy
3a0becc783 Use parse_impl for partition_map 2024-08-15 10:10:18 -07:00
ChsBuffer
1f974cb220 Use androidboot.partition_map as a fallback for matching partition names in the preinit finding. 2024-08-15 10:10:18 -07:00
LoveSy
1db80228e8 Move worker mount to magiskinit 2024-08-15 02:39:51 -07:00
LoveSy
838e1e254d Move devpts mount to magiskinit 2024-08-15 02:39:51 -07:00
topjohnwu
554eda8fe1 Switch to gmake on macOS 2024-08-15 02:37:59 -07:00
topjohnwu
2bdc047c4d Call sqlite3_free only on sqlite3 malloc-ed objects 2024-08-14 13:23:59 -07:00
topjohnwu
e64f59ce5b Make CI faster 2024-08-14 00:21:45 -07:00
topjohnwu
b8140ad4e6 Re-enable Windows CI 2024-08-13 21:12:06 -07:00
LoveSy
5a55483698 Set -fno-threadsafe-statics for crt0
Since crt0 has no pthread support, we don't need lock for statics.
2024-08-12 10:57:45 -07:00
vvb2060
2d341863f5 set MAGISKTMP 2024-08-12 02:05:58 -07:00
LoveSy
278046becb Fix wrong cxx_extern return value
This fix UB
2024-08-12 02:05:26 -07:00
topjohnwu
5c0497354f Temporarily disable Windows CI 2024-08-12 02:04:13 -07:00
topjohnwu
98c258df93 Update AGP 2024-08-11 04:30:01 -07:00
topjohnwu
c578cccfd5 Update to ONDK r27.4 2024-08-11 04:16:19 -07:00
Andrew Gunnerson
07835a3e0e util_functions.sh: Fix syntax error due to missing then
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2024-08-06 01:16:19 -07:00
topjohnwu
09131aca89 Fix find_boot_image
Close #8255
2024-08-05 11:24:30 -07:00
topjohnwu
9ce998a6df Fix arab strings 2024-08-04 01:54:28 -07:00
topjohnwu
ca36b42d79 Update release.sh 2024-08-03 01:55:03 -07:00
topjohnwu
37df39ec37 Address clippy warnings 2024-08-03 01:52:16 -07:00
topjohnwu
1701361a73 Update cargo dependencies 2024-08-03 01:49:14 -07:00
topjohnwu
4c14ae33f5 Properly configure Rust builds 2024-08-03 01:28:53 -07:00
topjohnwu
d4a9ef7b7f Cleanup build.py 2024-08-03 00:05:49 -07:00
topjohnwu
1539cfe888 Support setting custom ABI list
Also stop building riscv64 by default
2024-08-01 14:33:08 -07:00
topjohnwu
9093be1329 Run commands through shell on Windows 2024-07-31 17:21:18 -07:00
topjohnwu
606d076251 Build debug with thin lto 2024-07-31 17:00:01 -07:00
残页
46a34e19bc Check vendor boot ramdisk table size 2024-07-31 16:59:51 -07:00
topjohnwu
5ac7dc0b37 Support vendor boot unpack/repack
Fix #6460, close #6620
2024-07-30 04:00:12 -07:00
topjohnwu
3b27de3715 Output logs to files 2024-07-25 03:48:13 -07:00
topjohnwu
939bfac920 Make sure version is fetched correctly 2024-07-25 03:04:27 -07:00
muhammadbahaa2001
f601bf12d5 Updated Arabic 2024-07-25 03:03:49 -07:00
topjohnwu
0495468d02 Release new canary build 2024-07-24 23:13:21 -07:00
topjohnwu
300a2a242c Add release script 2024-07-24 23:10:57 -07:00
topjohnwu
33aebb5976 Stop embedding executables 2024-07-24 22:49:48 -07:00
pndwal
b3d6809c0b Update README.MD
Remove redundant Canary changelog link
2024-07-24 19:04:50 -07:00
LoveSy
461f7e9f89 Use metadata even if it is f2fs 2024-07-24 19:02:35 -07:00
LoveSy
9cc50b20d8 Correctly handle comments in sepolicy.rule 2024-07-24 19:02:25 -07:00
LoveSy
f488e9df8f Fix sepolicy rule path 2024-07-24 19:02:12 -07:00
LoveSy
0dc596e206 Update Chinese translation 2024-07-24 19:01:59 -07:00
topjohnwu
c3bf03190b Use K2 in kapt 2024-07-24 17:06:41 -07:00
topjohnwu
021ae891a9 Update dependencies 2024-07-24 16:53:15 -07:00
topjohnwu
9c03514eb1 Create :app:clean task 2024-07-24 16:46:47 -07:00
topjohnwu
eb74b266e1 Do not modify args
Close #8242
2024-07-24 16:37:22 -07:00
topjohnwu
80eb6ff25a Update README 2024-07-23 21:37:04 -07:00
105 changed files with 2571 additions and 1255 deletions

View File

@@ -1,44 +1,100 @@
name: Magisk Setup name: Magisk Setup
inputs:
is-asset-build:
required: false
default: false
runs: runs:
using: "composite" using: "composite"
steps: steps:
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: "temurin" distribution: "temurin"
java-version: "17" java-version: "21"
- name: Set up Python 3 - name: Set up Python 3
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
- name: Set up sccache - name: Install GNU make
uses: hendrikmuhs/ccache-action@v1.2 if: runner.os == 'macOS'
shell: bash
run: |
brew install make
echo 'GNUMAKE=gmake' >> "$GITHUB_ENV"
- name: Cache sccache
uses: actions/cache@v4
with: with:
variant: sccache path: .sccache
key: ${{ runner.os }}-${{ github.sha }} key: sccache-${{ runner.os }}-${{ github.sha }}
restore-keys: ${{ runner.os }} restore-keys: sccache-${{ runner.os }}-
max-size: 10000M
- name: Set up sccache
shell: bash
env:
SCCACHE_DIRECT: false
SCCACHE_DIR: ${{ github.workspace }}/.sccache
SCCACHE_CACHE_SIZE: 2G
SCCACHE_IDLE_TIMEOUT: 0
run: |
bash $GITHUB_ACTION_PATH/sccache.sh
sccache --start-server
sccache -z
- name: Show sccache stats
uses: gacts/run-and-post-run@v1
with:
run: sccache -s
post: sccache -s
- name: Set GRADLE_USER_HOME
shell: bash
run: echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/.gradle" >> "$GITHUB_ENV"
- name: Cache Gradle dependencies - name: Cache Gradle dependencies
uses: actions/cache@v4 uses: actions/cache@v4
if: inputs.is-asset-build == 'true'
with: with:
path: | path: |
~/.gradle/caches .gradle/caches
~/.gradle/wrapper .gradle/wrapper
!~/.gradle/caches/build-cache-* !.gradle/caches/build-cache-*
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }} key: gradle-cache-${{ hashFiles('gradle/**') }}
restore-keys: ${{ runner.os }}-gradle- restore-keys: gradle-cache-
- name: Cache build cache - name: Restore Gradle dependencies
uses: actions/cache@v4 uses: actions/cache/restore@v4
if: inputs.is-asset-build == 'false'
with: with:
path: | path: |
~/.gradle/caches/build-cache-* .gradle/caches
key: ${{ runner.os }}-build-cache-${{ github.sha }} .gradle/wrapper
restore-keys: ${{ runner.os }}-build-cache- !.gradle/caches/build-cache-*
key: gradle-cache-${{ hashFiles('gradle/**') }}
restore-keys: gradle-cache-
enableCrossOsArchive: true
- name: Cache Gradle build cache
uses: actions/cache@v4
if: inputs.is-asset-build == 'true'
with:
path: |
.gradle/caches/build-cache-*
key: gradle-build-cache-${{ github.sha }}
restore-keys: gradle-build-cache-
- name: Restore Gradle build cache
uses: actions/cache/restore@v4
if: inputs.is-asset-build == 'false'
with:
path: |
.gradle/caches/build-cache-*
key: gradle-build-cache-${{ github.sha }}
restore-keys: gradle-build-cache-
enableCrossOsArchive: true
- name: Set up NDK - name: Set up NDK
run: python build.py -v ndk
shell: bash shell: bash
run: python build.py -v ndk

25
.github/actions/setup/sccache.sh vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Get latest sccache version
get_sccache_ver() {
curl -sL 'https://api.github.com/repos/mozilla/sccache/releases/latest' | jq -r .name
}
# $1=variant
# $2=install_dir
# $3=exe
install_from_gh() {
local ver=$(curl -sL 'https://api.github.com/repos/mozilla/sccache/releases/latest' | jq -r .name)
local url="https://github.com/mozilla/sccache/releases/download/${ver}/sccache-${ver}-$1.tar.gz"
local dest="$2/$3"
curl -L "$url" | tar xz -O --wildcards "*/$3" > $dest
chmod +x $dest
}
if [ $RUNNER_OS = "macOS" ]; then
brew install sccache
elif [ $RUNNER_OS = "Linux" ]; then
install_from_gh x86_64-unknown-linux-musl /usr/local/bin sccache
elif [ $RUNNER_OS = "Windows" ]; then
install_from_gh x86_64-pc-windows-msvc $USERPROFILE/.cargo/bin sccache.exe
fi

1
.github/ci.prop vendored Normal file
View File

@@ -0,0 +1 @@
abiList=arm64-v8a

View File

@@ -17,9 +17,7 @@ on:
jobs: jobs:
build: build:
name: Build Magisk artifacts name: Build Magisk artifacts
runs-on: ubuntu-latest runs-on: macos-14
env:
SCCACHE_DIRECT: false
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
@@ -27,10 +25,11 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: "recursive" submodules: "recursive"
fetch-depth: 0
- name: Setup environment - name: Setup environment
uses: ./.github/actions/setup uses: ./.github/actions/setup
with:
is-asset-build: true
- name: Build release - name: Build release
run: ./build.py -vr all run: ./build.py -vr all
@@ -58,24 +57,21 @@ jobs:
test-build: test-build:
name: Test building on ${{ matrix.os }} name: Test building on ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env:
SCCACHE_DIRECT: false
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [windows-latest, macos-14] os: [windows-latest, ubuntu-latest]
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: "recursive" submodules: "recursive"
fetch-depth: 0
- name: Setup environment - name: Setup environment
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Build debug - name: Test build
run: python build.py -v all run: python build.py -v -c .github/ci.prop all
- name: Stop gradle daemon - name: Stop gradle daemon
run: ./gradlew --stop run: ./gradlew --stop
@@ -96,8 +92,6 @@ jobs:
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download build artifacts - name: Download build artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -114,9 +108,18 @@ jobs:
- name: Run AVD test - name: Run AVD test
timeout-minutes: 10 timeout-minutes: 10
env: env:
AVD_TEST_VERBOSE: 1 AVD_TEST_LOG: 1
run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }} run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }}
- name: Upload logs on error
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: "avd-logs-${{ matrix.version }}"
path: |
kernel.log
logcat.log
avd-test-32: avd-test-32:
name: Test API ${{ matrix.version }} (x86) name: Test API ${{ matrix.version }} (x86)
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -129,8 +132,6 @@ jobs:
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download build artifacts - name: Download build artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -148,11 +149,20 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
env: env:
FORCE_32_BIT: 1 FORCE_32_BIT: 1
AVD_TEST_VERBOSE: 1 AVD_TEST_LOG: 1
run: scripts/avd_test.sh ${{ matrix.version }} run: scripts/avd_test.sh ${{ matrix.version }}
- name: Upload logs on error
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: "avd32-logs-${{ matrix.version }}"
path: |
kernel.log
logcat.log
cf_test: cf_test:
name: Test ${{ matrix.branch }} (${{ matrix.target }}) name: Test ${{ matrix.device }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: build needs: build
env: env:
@@ -162,13 +172,13 @@ jobs:
matrix: matrix:
include: include:
- branch: "aosp-main" - branch: "aosp-main"
target: "aosp_cf_x86_64_phone-trunk_staging-userdebug" device: "aosp_cf_x86_64_phone"
- branch: "aosp-main-throttled"
device: "aosp_cf_x86_64_phone_pgagnostic"
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download build artifacts - name: Download build artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -179,7 +189,7 @@ jobs:
- name: Setup Cuttlefish environment - name: Setup Cuttlefish environment
run: | run: |
scripts/cuttlefish.sh setup scripts/cuttlefish.sh setup
scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.target }} scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.device }}
- name: Run Cuttlefish test - name: Run Cuttlefish test
timeout-minutes: 10 timeout-minutes: 10
@@ -189,7 +199,7 @@ jobs:
if: ${{ failure() }} if: ${{ failure() }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: "cvd-logs" name: "cvd-logs-${{ matrix.device }}"
path: | path: |
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/logs /home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/logs
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/cuttlefish_config.json /home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/cuttlefish_config.json

2
.gitignore vendored
View File

@@ -13,7 +13,7 @@ native/out
# Android Studio / Gradle # Android Studio / Gradle
*.iml *.iml
.gradle .gradle
.idea
/local.properties /local.properties
/.idea
/build /build
/captures /captures

View File

@@ -21,9 +21,8 @@ Some highlight features:
Click the icon below to download Magisk apk. Click the icon below to download Magisk apk.
[![](https://img.shields.io/badge/Magisk-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0) [![](https://img.shields.io/badge/Magisk-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
[![](https://img.shields.io/badge/Magisk%20Beta-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0) [![](https://img.shields.io/badge/Magisk%20Beta-v28.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v28.0)
[![](https://img.shields.io/badge/Magisk-Canary-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-release.apk) [![](https://img.shields.io/badge/Magisk-Canary-red)](https://github.com/topjohnwu/Magisk/releases/tag/canary-28002)
[![](https://img.shields.io/badge/Magisk-Debug-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)
## Useful Links ## Useful Links
@@ -31,8 +30,6 @@ Click the icon below to download Magisk apk.
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html) - [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/) - [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample) - [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
- [Canary channel changelog](https://github.com/topjohnwu/magisk-files/blob/canary/notes.md)
## Bug Reports ## Bug Reports

View File

@@ -6,63 +6,53 @@ plugins {
id("androidx.navigation.safeargs.kotlin") id("androidx.navigation.safeargs.kotlin")
} }
setupAppCommon() setupMainApk()
kapt { kapt {
correctErrorTypes = true correctErrorTypes = true
useBuildCache = true useBuildCache = true
mapDiagnosticLocations = true mapDiagnosticLocations = true
javacOptions { javacOptions {
option("-Xmaxerrs", 1000) option("-Xmaxerrs", "1000")
} }
} }
android { android {
namespace = "com.topjohnwu.magisk" buildFeatures {
dataBinding = true
}
defaultConfig { compileOptions {
applicationId = "com.topjohnwu.magisk" isCoreLibraryDesugaringEnabled = true
vectorDrawables.useSupportLibrary = true
versionName = Config.version
versionCode = Config.versionCode
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
debugSymbolLevel = "FULL"
}
} }
buildTypes { buildTypes {
release { release {
isMinifyEnabled = true isMinifyEnabled = true
isShrinkResources = true isShrinkResources = true
proguardFiles("proguard-rules.pro")
} }
} }
buildFeatures {
dataBinding = true
}
} }
dependencies { dependencies {
implementation(project(":app:core")) implementation(project(":app:core"))
coreLibraryDesugaring(libs.jdk.libs)
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7") implementation(libs.indeterminate.checkbox)
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0") implementation(libs.rikka.layoutinflater)
implementation("dev.rikka.rikkax.insets:insets:1.3.0") implementation(libs.rikka.insets)
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.2") implementation(libs.rikka.recyclerview)
val vNav = "2.7.7" implementation(libs.navigation.fragment.ktx)
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}") implementation(libs.navigation.ui.ktx)
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation(libs.constraintlayout)
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation(libs.swiperefreshlayout)
implementation("androidx.recyclerview:recyclerview:1.3.2") implementation(libs.recyclerview)
implementation("androidx.transition:transition:1.5.0") implementation(libs.transition)
implementation("androidx.fragment:fragment-ktx:1.8.1") implementation(libs.fragment.ktx)
implementation("androidx.appcompat:appcompat:1.7.0") implementation(libs.appcompat)
implementation("com.google.android.material:material:1.12.0") implementation(libs.material)
// Make sure kapt runs with a proper kotlin-stdlib // Make sure kapt runs with a proper kotlin-stdlib
kapt(kotlin("stdlib")) kapt(kotlin("stdlib"))

View File

@@ -1,13 +1,18 @@
package com.topjohnwu.magisk.dialog package com.topjohnwu.magisk.dialog
import android.widget.Toast
import androidx.core.os.postDelayed
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.core.BuildConfig import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.reboot
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.MagiskInstaller import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.events.DialogBuilder import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.home.HomeViewModel import com.topjohnwu.magisk.ui.home.HomeViewModel
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.superuser.internal.UiThreadHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : DialogBuilder { class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : DialogBuilder {
@@ -27,9 +32,15 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
setCancelable(false) setCancelable(false)
} }
dialog.activity.lifecycleScope.launch { dialog.activity.lifecycleScope.launch {
MagiskInstaller.FixEnv { MagiskInstaller.FixEnv().exec { success ->
dialog.dismiss() dialog.dismiss()
}.exec() context.toast(
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
Toast.LENGTH_LONG
)
if (success)
UiThreadHandler.handler.postDelayed(5000) { reboot() }
}
} }
} }
} }

View File

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.dialog package com.topjohnwu.magisk.dialog
import android.content.Context
import com.topjohnwu.magisk.core.R import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.DownloadEngine import com.topjohnwu.magisk.core.download.DownloadEngine
@@ -7,6 +8,8 @@ import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.core.model.module.OnlineModule import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.ui.flash.FlashFragment import com.topjohnwu.magisk.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Notifications
import kotlinx.parcelize.Parcelize
class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() { class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() {
@@ -17,14 +20,21 @@ class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog
return if (str.length > 1000) str.substring(0, 1000) else str return if (str.length > 1000) str.substring(0, 1000) else str
} }
@Parcelize
class Module(
override val module: OnlineModule,
override val autoLaunch: Boolean,
override val notifyId: Int = Notifications.nextId()
) : Subject.Module() {
override fun pendingIntent(context: Context) = FlashFragment.installIntent(context, file)
}
override fun build(dialog: MagiskDialog) { override fun build(dialog: MagiskDialog) {
super.build(dialog) super.build(dialog)
dialog.apply { dialog.apply {
fun download(install: Boolean) { fun download(install: Boolean) {
val module = Subject.Module(item, install) DownloadEngine.startWithActivity(activity, Module(item, install))
module.piCreator = FlashFragment::installIntent
DownloadEngine.startWithActivity(activity, module)
} }
val title = context.getString(R.string.repo_install_title, val title = context.getString(R.string.repo_install_title,

View File

@@ -1,15 +1,17 @@
package com.topjohnwu.magisk.dialog package com.topjohnwu.magisk.dialog
import android.app.ProgressDialog import android.app.ProgressDialog
import android.content.Context
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.arch.NavigationActivity import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.core.R import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.toast import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.events.DialogBuilder import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.flash.FlashFragment import com.topjohnwu.magisk.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.superuser.Shell import kotlinx.coroutines.launch
class UninstallDialog : DialogBuilder { class UninstallDialog : DialogBuilder {
@@ -19,7 +21,7 @@ class UninstallDialog : DialogBuilder {
setMessage(R.string.uninstall_magisk_msg) setMessage(R.string.uninstall_magisk_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) { setButton(MagiskDialog.ButtonType.POSITIVE) {
text = R.string.restore_img text = R.string.restore_img
onClick { restore(dialog.context) } onClick { restore(dialog.activity) }
} }
setButton(MagiskDialog.ButtonType.NEGATIVE) { setButton(MagiskDialog.ButtonType.NEGATIVE) {
text = R.string.complete_uninstall text = R.string.complete_uninstall
@@ -29,18 +31,20 @@ class UninstallDialog : DialogBuilder {
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun restore(context: Context) { private fun restore(activity: UIActivity<*>) {
val dialog = ProgressDialog(context).apply { val dialog = ProgressDialog(activity).apply {
setMessage(context.getString(R.string.restore_img_msg)) setMessage(activity.getString(R.string.restore_img_msg))
show() show()
} }
Shell.cmd("restore_imgs").submit { result -> activity.lifecycleScope.launch {
dialog.dismiss() MagiskInstaller.Restore().exec { success ->
if (result.isSuccess) { dialog.dismiss()
context.toast(R.string.restore_done, Toast.LENGTH_SHORT) if (success) {
} else { activity.toast(R.string.restore_done, Toast.LENGTH_SHORT)
context.toast(R.string.restore_fail, Toast.LENGTH_LONG) } else {
activity.toast(R.string.restore_fail, Toast.LENGTH_LONG)
}
} }
} }
} }

View File

@@ -71,7 +71,7 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
defaultOrientation = activity?.requestedOrientation ?: -1 defaultOrientation = activity?.requestedOrientation ?: -1
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
if (savedInstanceState == null) { if (savedInstanceState == null) {
viewModel.startFlashing() viewModel.startFlashing()
} }

View File

@@ -0,0 +1,108 @@
package com.topjohnwu.magisk.ui.module
import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.core.view.MenuProvider
import androidx.core.view.isVisible
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding
import com.topjohnwu.magisk.core.R as CoreR
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
override val layoutRes = R.layout.fragment_action_md2
override val viewModel by viewModel<ActionViewModel>()
override val snackbarView: View get() = binding.snackbarContainer
private var defaultOrientation = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.args = ActionFragmentArgs.fromBundle(requireArguments())
}
override fun onStart() {
super.onStart()
activity?.setTitle(viewModel.args.name)
binding.closeBtn.setOnClickListener {
activity?.onBackPressed()
}
viewModel.state.observe(this) {
if (it != ActionViewModel.State.RUNNING) {
binding.closeBtn.apply {
if (!this.isVisible) this.show()
if (!this.isFocused) this.requestFocus()
}
}
if (it != ActionViewModel.State.SUCCESS) return@observe
view?.viewTreeObserver?.addOnWindowFocusChangeListener(
object : ViewTreeObserver.OnWindowFocusChangeListener {
override fun onWindowFocusChanged(hasFocus: Boolean) {
if (hasFocus) return
view?.viewTreeObserver?.removeOnWindowFocusChangeListener(this)
view?.context?.apply {
toast(
getString(CoreR.string.done_action, viewModel.args.name),
Toast.LENGTH_SHORT
)
}
viewModel.back()
}
}
)
}
}
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_flash, menu)
}
override fun onMenuItemSelected(item: MenuItem): Boolean {
return viewModel.onMenuItemClicked(item)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
defaultOrientation = activity?.requestedOrientation ?: -1
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
if (savedInstanceState == null) {
viewModel.startRunAction()
}
}
@SuppressLint("WrongConstant")
override fun onDestroyView() {
if (defaultOrientation != -1) {
activity?.requestedOrientation = defaultOrientation
}
super.onDestroyView()
}
override fun onKeyEvent(event: KeyEvent): Boolean {
return when (event.keyCode) {
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> true
else -> false
}
}
override fun onBackPressed(): Boolean {
if (viewModel.state.value == ActionViewModel.State.RUNNING) return true
return super.onBackPressed()
}
override fun onPreBind(binding: FragmentActionMd2Binding) = Unit
}

View File

@@ -0,0 +1,88 @@
package com.topjohnwu.magisk.ui.module
import android.view.MenuItem
import androidx.databinding.ObservableArrayList
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.ktx.synchronized
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
import com.topjohnwu.magisk.core.ktx.toTime
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.ui.flash.ConsoleItem
import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
class ActionViewModel : BaseViewModel() {
enum class State {
RUNNING, SUCCESS, FAILED
}
private val _state = MutableLiveData(State.RUNNING)
val state: LiveData<State> get() = _state
val items = ObservableArrayList<ConsoleItem>()
lateinit var args: ActionFragmentArgs
private val logItems = mutableListOf<String>().synchronized()
private val outItems = object : CallbackList<String>() {
override fun onAddElement(e: String?) {
e ?: return
items.add(ConsoleItem(e))
logItems.add(e)
}
}
fun startRunAction() = viewModelScope.launch {
onResult(withContext(Dispatchers.IO) {
try {
Shell.cmd("run_action \'${args.id}\'")
.to(outItems, logItems)
.exec().isSuccess
} catch (e: IOException) {
Timber.e(e)
false
}
})
}
private fun onResult(success: Boolean) {
_state.value = if (success) State.SUCCESS else State.FAILED
}
fun onMenuItemClicked(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_save -> savePressed()
}
return true
}
private fun savePressed() = withExternalRW {
viewModelScope.launch(Dispatchers.IO) {
val name = "%s_action_log_%s.log".format(
args.name,
System.currentTimeMillis().toTime(timeFormatStandard)
)
val file = MediaStoreUtils.getFile(name)
file.uri.outputStream().bufferedWriter().use { writer ->
synchronized(logItems) {
logItems.forEach {
writer.write(it)
writer.newLine()
}
}
}
SnackbarEvent(file.toString()).publish()
}
}
}

View File

@@ -25,6 +25,7 @@ class LocalModuleRvItem(
override val layoutRes = R.layout.item_module_md2 override val layoutRes = R.layout.item_module_md2
val showNotice: Boolean val showNotice: Boolean
val showAction: Boolean
val noticeText: TextHolder val noticeText: TextHolder
init { init {
@@ -35,6 +36,7 @@ class LocalModuleRvItem(
showNotice = zygiskUnloaded || showNotice = zygiskUnloaded ||
(Info.isZygiskEnabled && isRiru) || (Info.isZygiskEnabled && isRiru) ||
(!Info.isZygiskEnabled && isZygisk) (!Info.isZygiskEnabled && isZygisk)
showAction = item.hasAction && !showNotice
noticeText = noticeText =
when { when {
zygiskUnloaded -> CoreR.string.zygisk_module_unloaded.asText() zygiskUnloaded -> CoreR.string.zygisk_module_unloaded.asText()

View File

@@ -4,8 +4,10 @@ import android.net.Uri
import androidx.databinding.Bindable import androidx.databinding.Bindable
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.AsyncLoadViewModel import com.topjohnwu.magisk.arch.AsyncLoadViewModel
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.ContentResultCallback import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.model.module.LocalModule import com.topjohnwu.magisk.core.model.module.LocalModule
@@ -96,6 +98,10 @@ class ModuleViewModel : AsyncLoadViewModel() {
} }
} }
fun runAction(id: String, name: String) {
MainDirections.actionActionFragment(id, name).navigate()
}
companion object { companion object {
private val uri = MutableLiveData<Uri?>() private val uri = MutableLiveData<Uri?>()
} }

View File

@@ -78,8 +78,8 @@ class SuperuserViewModel(
this@SuperuserViewModel, policy, this@SuperuserViewModel, policy,
info.packageName, info.packageName,
info.sharedUserId != null, info.sharedUserId != null,
info.applicationInfo.loadIcon(pm), info.applicationInfo?.loadIcon(pm) ?: pm.defaultActivityIcon,
info.applicationInfo.getLabel(pm) info.applicationInfo?.getLabel(pm) ?: info.packageName
) )
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
null null

View File

@@ -111,7 +111,7 @@ class SuRequestViewModel(
// shared UID. We have no way to know where this request comes from. // shared UID. We have no way to know where this request comes from.
icon = pm.defaultActivityIcon icon = pm.defaultActivityIcon
title = "[SharedUID] ${info.sharedUserId}" title = "[SharedUID] ${info.sharedUserId}"
packageName = info.sharedUserId packageName = info.sharedUserId.toString()
} else { } else {
val prefix = if (info.sharedUserId == null) "" else "[SharedUID] " val prefix = if (info.sharedUserId == null) "" else "[SharedUID] "
icon = app.loadIcon(pm) icon = app.loadIcon(pm)

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.topjohnwu.magisk.ui.module.ActionViewModel" />
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/internal_action_bar_size"
app:layout_fitsSystemWindowsInsets="top"
tools:layout_marginTop="@dimen/internal_action_bar_size">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/flash_content"
scrollToLast="@{true}"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
app:fitsSystemWindowsInsets="start|end|bottom"
app:items="@{viewModel.items}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/item_console_md2" />
</HorizontalScrollView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/close_btn"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/l1"
android:layout_marginBottom="@dimen/l1"
android:clickable="true"
android:enabled="true"
android:focusable="true"
android:text="@string/close"
android:textAllCaps="false"
android:textColor="?colorOnPrimary"
android:textStyle="bold"
app:backgroundTint="?colorPrimary"
app:icon="@drawable/ic_close_md2"
app:iconTint="?colorOnPrimary"
app:layout_fitsSystemWindowsInsets="bottom" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/snackbar_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fitsSystemWindowsInsets="top|bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@@ -189,12 +189,32 @@
android:textColor="?colorError" android:textColor="?colorError"
app:layout_constraintBottom_toBottomOf="@+id/module_remove" app:layout_constraintBottom_toBottomOf="@+id/module_remove"
app:layout_constraintEnd_toStartOf="@+id/bottom_bar_barrier" app:layout_constraintEnd_toStartOf="@+id/bottom_bar_barrier"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@id/module_config"
app:layout_constraintTop_toTopOf="@+id/module_remove" app:layout_constraintTop_toTopOf="@+id/module_remove"
tools:lines="2" tools:lines="2"
tools:text="@tools:sample/lorem/random" tools:text="@tools:sample/lorem/random"
tools:visibility="visible" /> tools:visibility="visible" />
<Button
android:id="@+id/module_config"
style="@style/WidgetFoundation.Button.Text"
goneUnless="@{item.showAction}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:enabled="@{item.enabled}"
android:focusable="true"
android:onClick="@{() -> viewModel.runAction(item.item.id, item.item.name)}"
android:text="@string/module_action"
android:textAllCaps="false"
android:visibility="gone"
app:icon="@drawable/ic_action_md2"
app:iconGravity="textStart"
app:layout_constraintBottom_toBottomOf="@+id/module_remove"
app:layout_constraintTop_toTopOf="@+id/module_remove"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/ic_download_md2" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>

View File

@@ -53,6 +53,21 @@
</fragment> </fragment>
<fragment
android:id="@+id/actionFragment"
android:name="com.topjohnwu.magisk.ui.module.ActionFragment"
android:label="ActionFragment"
tools:layout="@layout/fragment_action_md2" >
<argument
android:name="id"
app:argType="string" />
<argument
android:name="name"
app:argType="string" />
</fragment>
<fragment <fragment
android:id="@+id/installFragment" android:id="@+id/installFragment"
android:name="com.topjohnwu.magisk.ui.install.InstallFragment" android:name="com.topjohnwu.magisk.ui.install.InstallFragment"
@@ -152,4 +167,12 @@
app:popEnterAnim="@anim/fragment_enter_pop" app:popEnterAnim="@anim/fragment_enter_pop"
app:popExitAnim="@anim/fragment_exit_pop" /> app:popExitAnim="@anim/fragment_exit_pop" />
<action
android:id="@+id/action_actionFragment"
app:destination="@id/actionFragment"
app:enterAnim="@anim/fragment_enter"
app:exitAnim="@anim/fragment_exit"
app:popEnterAnim="@anim/fragment_enter_pop"
app:popExitAnim="@anim/fragment_exit_pop" />
</navigation> </navigation>

5
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,5 @@
tasks.register("clean") {
subprojects.forEach {
dependsOn(":app:${it.name}:clean")
}
}

View File

@@ -19,6 +19,7 @@ android {
buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}") buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}")
buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"") buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"")
buildConfigField("int", "STUB_VERSION", Config.stubVersion) buildConfigField("int", "STUB_VERSION", Config.stubVersion)
consumerProguardFile("proguard-rules.pro")
} }
buildFeatures { buildFeatures {
@@ -30,39 +31,34 @@ android {
dependencies { dependencies {
api(project(":app:shared")) api(project(":app:shared"))
api("com.jakewharton.timber:timber:5.0.1") api(libs.timber)
api("io.noties.markwon:core:4.6.2") api(libs.markwon.core)
implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1") implementation(libs.bcpkix)
implementation("org.apache.commons:commons-compress:1.26.2") implementation(libs.commons.compress)
val vLibsu = "6.0.0" api(libs.libsu.core)
api("com.github.topjohnwu.libsu:core:${vLibsu}") api(libs.libsu.service)
api("com.github.topjohnwu.libsu:service:${vLibsu}") api(libs.libsu.nio)
api("com.github.topjohnwu.libsu:nio:${vLibsu}")
val vRetrofit = "2.11.0" implementation(libs.retrofit)
implementation("com.squareup.retrofit2:retrofit:${vRetrofit}") implementation(libs.retrofit.moshi)
implementation("com.squareup.retrofit2:converter-moshi:${vRetrofit}") implementation(libs.retrofit.scalars)
implementation("com.squareup.retrofit2:converter-scalars:${vRetrofit}")
val vOkHttp = "4.12.0" implementation(libs.okhttp)
implementation("com.squareup.okhttp3:okhttp:${vOkHttp}") implementation(libs.okhttp.logging)
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}") implementation(libs.okhttp.dnsoverhttps)
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
val vMoshi = "1.15.1" implementation(libs.moshi)
implementation("com.squareup.moshi:moshi:${vMoshi}") ksp(libs.moshi.codegen)
ksp("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
val vRoom = "2.6.1" implementation(libs.room.runtime)
implementation("androidx.room:room-runtime:${vRoom}") implementation(libs.room.ktx)
implementation("androidx.room:room-ktx:${vRoom}") ksp(libs.room.compiler)
ksp("androidx.room:room-compiler:${vRoom}")
implementation("androidx.core:core-splashscreen:1.0.1") implementation(libs.core.splashscreen)
implementation("androidx.core:core-ktx:1.13.1") implementation(libs.core.ktx)
implementation("androidx.activity:activity:1.9.0") implementation(libs.activity)
implementation("androidx.collection:collection-ktx:1.4.1") implementation(libs.collection.ktx)
implementation("androidx.profileinstaller:profileinstaller:1.3.1") implementation(libs.profileinstaller)
implementation("androidx.lifecycle:lifecycle-process:2.8.3") implementation(libs.lifecycle.process)
} }

View File

@@ -22,36 +22,21 @@
int mActivityHandlesConfigFlags; int mActivityHandlesConfigFlags;
} }
# main
-keep,allowoptimization public class com.topjohnwu.magisk.signing.SignBoot {
public static void main(java.lang.String[]);
}
# Strip Timber verbose and debug logging # Strip Timber verbose and debug logging
-assumenosideeffects class timber.log.Timber$Tree { -assumenosideeffects class timber.log.Timber$Tree {
public void v(**); public void v(**);
public void d(**); public void d(**);
} }
# https://github.com/square/retrofit/issues/3751#issuecomment-1192043644
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
# With R8 full mode generic signatures are stripped for classes that are not # With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument # kept. Suspend functions are wrapped in continuations where the type argument
# is used. # is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# Excessive obfuscation # Excessive obfuscation
-repackageclasses 'a' -flattenpackagehierarchy
-allowaccessmodification -allowaccessmodification
-obfuscationdictionary ../dict.txt
-classobfuscationdictionary ../dict.txt
-packageobfuscationdictionary ../dict.txt
-dontwarn org.bouncycastle.jsse.BCSSLParameters -dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.BCSSLSocket -dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider -dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider

View File

@@ -17,7 +17,7 @@ import kotlinx.parcelize.Parcelize
import java.io.File import java.io.File
import java.util.UUID import java.util.UUID
sealed class Subject : Parcelable { abstract class Subject : Parcelable {
abstract val url: String abstract val url: String
abstract val file: Uri abstract val file: Uri
@@ -27,24 +27,13 @@ sealed class Subject : Parcelable {
open fun pendingIntent(context: Context): PendingIntent? = null open fun pendingIntent(context: Context): PendingIntent? = null
@Parcelize abstract class Module : Subject() {
class Module( abstract val module: OnlineModule
private val module: OnlineModule, final override val url: String get() = module.zipUrl
override val autoLaunch: Boolean, final override val title: String get() = module.downloadFilename
override val notifyId: Int = Notifications.nextId() final override val file by lazy {
) : Subject() {
override val url: String get() = module.zipUrl
override val title: String get() = module.downloadFilename
@IgnoredOnParcel
override val file by lazy {
MediaStoreUtils.getFile(title).uri MediaStoreUtils.getFile(title).uri
} }
@IgnoredOnParcel
var piCreator: ((Context, Uri) -> PendingIntent)? = null
override fun pendingIntent(context: Context) = piCreator?.invoke(context, file)
} }
@Parcelize @Parcelize

View File

@@ -37,6 +37,7 @@ data class LocalModule(
val isRiru: Boolean get() = (id == "riru-core") || riruFolder.exists() val isRiru: Boolean get() = (id == "riru-core") || riruFolder.exists()
val isZygisk: Boolean get() = zygiskFolder.exists() val isZygisk: Boolean get() = zygiskFolder.exists()
val zygiskUnloaded: Boolean get() = unloaded.exists() val zygiskUnloaded: Boolean get() = unloaded.exists()
val hasAction: Boolean;
var enable: Boolean var enable: Boolean
get() = !disableFile.exists() get() = !disableFile.exists()
@@ -100,6 +101,8 @@ data class LocalModule(
if (name.isEmpty()) { if (name.isEmpty()) {
name = id name = id
} }
hasAction = RootUtils.fs.getFile(path, "action.sh").exists()
} }
suspend fun fetch(): Boolean { suspend fun fetch(): Boolean {

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.core.model.su package com.topjohnwu.magisk.core.model.su
import android.content.pm.PackageInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@@ -24,7 +24,7 @@ class SuLog(
} }
fun PackageManager.createSuLog( fun PackageManager.createSuLog(
info: PackageInfo, info: ApplicationInfo,
toUid: Int, toUid: Int,
fromPid: Int, fromPid: Int,
command: String, command: String,
@@ -33,13 +33,12 @@ fun PackageManager.createSuLog(
context: String, context: String,
gids: String, gids: String,
): SuLog { ): SuLog {
val appInfo = info.applicationInfo
return SuLog( return SuLog(
fromUid = appInfo.uid, fromUid = info.uid,
toUid = toUid, toUid = toUid,
fromPid = fromPid, fromPid = fromPid,
packageName = getNameForUid(appInfo.uid)!!, packageName = getNameForUid(info.uid)!!,
appName = appInfo.getLabel(this), appName = info.getLabel(this),
command = command, command = command,
action = policy, action = policy,
target = target, target = target,

View File

@@ -64,7 +64,7 @@ object SuCallbackHandler {
val pm = context.packageManager val pm = context.packageManager
val log = runCatching { val log = runCatching {
pm.getPackageInfo(fromUid, pid)?.let { pm.getPackageInfo(fromUid, pid)?.applicationInfo?.let {
pm.createSuLog(it, toUid, pid, command, policy, target, seContext, gids) pm.createSuLog(it, toUid, pid, command, policy, target, seContext, gids)
} }
}.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids) }.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids)

View File

@@ -125,8 +125,9 @@ object AppMigration {
apk: File, out: OutputStream, apk: File, out: OutputStream,
pkg: String, label: CharSequence pkg: String, label: CharSequence
): Boolean { ): Boolean {
val info = context.packageManager.getPackageArchiveInfo(apk.path, 0) ?: return false val pm = context.packageManager
val origLabel = info.applicationInfo.nonLocalizedLabel.toString() val info = pm.getPackageArchiveInfo(apk.path, 0)?.applicationInfo ?: return false
val origLabel = info.nonLocalizedLabel.toString()
try { try {
JarMap.open(apk, true).use { jar -> JarMap.open(apk, true).use { jar ->
val je = jar.getJarEntry(ANDROID_MANIFEST) val je = jar.getJarEntry(ANDROID_MANIFEST)
@@ -190,11 +191,12 @@ object AppMigration {
// Install and auto launch app // Install and auto launch app
val session = APKInstall.startSession(activity, pkg, onFailure) { val session = APKInstall.startSession(activity, pkg, onFailure) {
Config.suManager = pkg
Shell.cmd("touch $AppApkPath").exec()
launchApp(activity, pkg) launchApp(activity, pkg)
} }
Config.suManager = pkg val cmd = "adb_pm_install $repack $pkg"
val cmd = "touch $AppApkPath; adb_pm_install $repack $pkg"
if (Shell.cmd(cmd).exec().isSuccess) return true if (Shell.cmd(cmd).exec().isSuccess) return true
try { try {
@@ -239,11 +241,12 @@ object AppMigration {
} }
val apk = StubApk.current(activity) val apk = StubApk.current(activity)
val session = APKInstall.startSession(activity, APP_PACKAGE_NAME, onFailure) { val session = APKInstall.startSession(activity, APP_PACKAGE_NAME, onFailure) {
Config.suManager = ""
Shell.cmd("touch $AppApkPath").exec()
launchApp(activity, APP_PACKAGE_NAME) launchApp(activity, APP_PACKAGE_NAME)
dialog.dismiss() dialog.dismiss()
} }
Config.suManager = "" val cmd = "adb_pm_install $apk $APP_PACKAGE_NAME"
val cmd = "touch $AppApkPath; adb_pm_install $apk $APP_PACKAGE_NAME"
if (Shell.cmd(cmd).await().isSuccess) return if (Shell.cmd(cmd).await().isSuccess) return
val success = withContext(Dispatchers.IO) { val success = withContext(Dispatchers.IO) {
try { try {

View File

@@ -6,7 +6,6 @@ import android.system.ErrnoException
import android.system.Os import android.system.Os
import android.system.OsConstants import android.system.OsConstants
import android.system.OsConstants.O_WRONLY import android.system.OsConstants.O_WRONLY
import android.widget.Toast
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.core.os.postDelayed import androidx.core.os.postDelayed
import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.StubApk
@@ -15,13 +14,10 @@ import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.di.ServiceLocator import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.isRunningAsStub import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.copyAll import com.topjohnwu.magisk.core.ktx.copyAll
import com.topjohnwu.magisk.core.ktx.copyAndClose import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.reboot
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.ktx.writeTo import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.utils.DummyList import com.topjohnwu.magisk.core.utils.DummyList
import com.topjohnwu.magisk.core.utils.MediaStoreUtils import com.topjohnwu.magisk.core.utils.MediaStoreUtils
@@ -134,10 +130,12 @@ abstract class MagiskInstallImpl protected constructor(
val abi32 = Const.CPU_ABI_32 val abi32 = Const.CPU_ABI_32
if (Process.is64Bit() && abi32 != null) { if (Process.is64Bit() && abi32 != null) {
val magisk32 = File(installDir, "magisk32")
val entry = zf.getEntry("lib/$abi32/libmagisk.so") val entry = zf.getEntry("lib/$abi32/libmagisk.so")
zf.getInputStream(entry).writeTo(magisk32) if (entry != null) {
magisk32.setExecutable(true) val magisk32 = File(installDir, "magisk32")
zf.getInputStream(entry).writeTo(magisk32)
magisk32.setExecutable(true)
}
} }
} }
} else { } else {
@@ -583,6 +581,8 @@ abstract class MagiskInstallImpl protected constructor(
protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
protected fun restore() = findImage() && "restore_imgs $srcBoot".sh().isSuccess
protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess
@WorkerThread @WorkerThread
@@ -606,11 +606,10 @@ abstract class MagiskInstallImpl protected constructor(
} }
} }
abstract class MagiskInstaller( abstract class ConsoleInstaller(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstallImpl(console, logs) { ) : MagiskInstallImpl(console, logs) {
override suspend fun exec(): Boolean { override suspend fun exec(): Boolean {
val success = super.exec() val success = super.exec()
if (success) { if (success) {
@@ -620,40 +619,51 @@ abstract class MagiskInstaller(
} }
return success return success
} }
}
abstract class CallBackInstaller : MagiskInstallImpl(DummyList, DummyList) {
suspend fun exec(callback: (Boolean) -> Unit): Boolean {
val success = exec()
callback(success)
return success
}
}
class MagiskInstaller {
class Patch( class Patch(
private val uri: Uri, private val uri: Uri,
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = patchFile(uri) override suspend fun operations() = patchFile(uri)
} }
class SecondSlot( class SecondSlot(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = secondSlot() override suspend fun operations() = secondSlot()
} }
class Direct( class Direct(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = direct() override suspend fun operations() = direct()
} }
class Emulator( class Emulator(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstaller(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = fixEnv() override suspend fun operations() = fixEnv()
} }
class Uninstall( class Uninstall(
console: MutableList<String>, console: MutableList<String>,
logs: MutableList<String> logs: MutableList<String>
) : MagiskInstallImpl(console, logs) { ) : ConsoleInstaller(console, logs) {
override suspend fun operations() = uninstall() override suspend fun operations() = uninstall()
override suspend fun exec(): Boolean { override suspend fun exec(): Boolean {
@@ -667,19 +677,11 @@ abstract class MagiskInstaller(
} }
} }
class FixEnv(private val callback: () -> Unit) : MagiskInstallImpl(DummyList, DummyList) { class Restore : CallBackInstaller() {
override suspend fun operations() = fixEnv() override suspend fun operations() = restore()
}
override suspend fun exec(): Boolean { class FixEnv : CallBackInstaller() {
val success = super.exec() override suspend fun operations() = fixEnv()
callback()
context.toast(
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
Toast.LENGTH_LONG
)
if (success)
UiThreadHandler.handler.postDelayed(5000) { reboot() }
return success
}
} }
} }

View File

@@ -0,0 +1,32 @@
package com.topjohnwu.magisk.core.utils;
import android.os.Build;
import java.nio.file.attribute.FileTime;
import java.util.zip.ZipEntry;
public class Desugar {
public static FileTime getLastModifiedTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getLastModifiedTime();
} else {
return FileTime.fromMillis(entry.getTime());
}
}
public static FileTime getLastAccessTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getLastAccessTime();
} else {
return null;
}
}
public static FileTime getCreationTime(ZipEntry entry) {
if (Build.VERSION.SDK_INT >= 26) {
return entry.getCreationTime();
} else {
return null;
}
}
}

View File

@@ -10,10 +10,9 @@
<string name="section_theme">עיצוב</string> <string name="section_theme">עיצוב</string>
<string name="denylist">רשימת דחייה</string> <string name="denylist">רשימת דחייה</string>
<!--Home--> <!--Home-->
<string name="no_connection">אין חיבור זמין</string> <string name="no_connection">אין חיבור זמין</string>
<string name="app_changelog">רשימת שינויים</string> <string name="app_changelog">יומן שינויים</string>
<string name="loading">טוען…</string> <string name="loading">טוען…</string>
<string name="update">עדכון</string> <string name="update">עדכון</string>
<string name="not_available">ל/ז</string> <string name="not_available">ל/ז</string>
@@ -45,16 +44,16 @@
<string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לחריץ הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string> <string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לחריץ הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string>
<string name="setup_title">התקנה נוספת</string> <string name="setup_title">התקנה נוספת</string>
<string name="select_patch_file">בחירה והתקנת קובץ</string> <string name="select_patch_file">בחירה והתקנת קובץ</string>
<string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN קובץ tar (*.tar)</string> <string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN tarfile (*.tar) או payload.bin (*.bin)</string>
<string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string> <string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string>
<string name="flash_screen_title">התקנה</string> <string name="flash_screen_title">התקנה</string>
<!--Superuser--> <!--Superuser-->
<string name="su_request_title">בקשות משתמש על</string> <string name="su_request_title">בקשות משתמש על</string>
<string name="touch_filtered_warning">מכיוון שיישום מסתיר בקשה של משתמש על, Magisk לא יכול לאמת את תגובתך</string> <string name="touch_filtered_warning">מכיוון שיישום מסתיר בקשה של משתמש על, Magisk לא יכול לאמת את תגובתך</string>
<string name="deny">דחה</string> <string name="deny">דחייה</string>
<string name="prompt">מיידי</string> <string name="prompt">מיידי</string>
<string name="grant">הענק</string> <string name="grant">הענקה</string>
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nיש לדחות באי וודאות!</string> <string name="su_warning">מעניק גישה מלאה להתקן שלך.\nיש לדחות באי וודאות!</string>
<string name="forever">לצמיתות</string> <string name="forever">לצמיתות</string>
<string name="once">פעם אחת</string> <string name="once">פעם אחת</string>
@@ -62,24 +61,24 @@
<string name="twentymin">20 דקות</string> <string name="twentymin">20 דקות</string>
<string name="thirtymin">חצי שעה</string> <string name="thirtymin">חצי שעה</string>
<string name="sixtymin">שעה</string> <string name="sixtymin">שעה</string>
<string name="su_allow_toast">%1$s הוענקו הרשאות משתמש עבור</string> <string name="su_allow_toast">%1$s קיבל הרשאות משתמש על</string>
<string name="su_deny_toast">%1$s נשללו הרשאות משתמש עבור</string> <string name="su_deny_toast">%1$s נשללו הרשאות משתמש על</string>
<string name="su_snack_grant">הרשאות משתמש על עבור %1$s הוענקו</string> <string name="su_snack_grant">הרשאות משתמש על עבור %1$s הוענקו</string>
<string name="su_snack_deny">הרשאות משתמש על עבור %1$s נשללו</string> <string name="su_snack_deny">הרשאות משתמש על עבור %1$s נשללו</string>
<string name="su_snack_notif_on">התראות עבור %1$s פועלות</string> <string name="su_snack_notif_on">התראות של %1$s מופעלות</string>
<string name="su_snack_notif_off">התראות עבור %1$s כבויות</string> <string name="su_snack_notif_off">התראות של %1$s מושבתות</string>
<string name="su_snack_log_on">יומני רישום עבור %1$s פועלות</string> <string name="su_snack_log_on">יומני רישום עבור %1$s פועלות</string>
<string name="su_snack_log_off">יומני רישום עבור %1$s כבויות</string> <string name="su_snack_log_off">יומני רישום עבור %1$s מושבתות</string>
<string name="su_revoke_title">להסיר?</string> <string name="su_revoke_title">להסיר?</string>
<string name="su_revoke_msg">נא לאשר שלילת הרשאות עבור %1$s?</string> <string name="su_revoke_msg">נא לאשר שלילת הרשאות עבור %1$s?</string>
<string name="toast">הרמת כוסית</string> <string name="toast">הרמת כוסית</string>
<string name="none">ללא</string> <string name="none">ללא</string>
<string name="superuser_toggle_notification">התראות</string> <string name="superuser_toggle_notification">התראות</string>
<string name="superuser_toggle_revoke">הסרה</string> <string name="superuser_toggle_revoke">הסרה</string>
<string name="superuser_policy_none">לא נתבקשו הרשאות משתמש על על ידי שום יישום</string> <string name="superuser_policy_none">טרם נתבקשו הרשאות משתמש על על ידי יישומים</string>
<!--Logs--> <!--Logs-->
<string name="log_data_none">הינך ללא יומן רישום, יש לנסות להשתמש ביישומים מותאמים יותר למשתמש העל שלך</string> <string name="log_data_none">הינך ללא יומן, יש לנסות להשתמש יותר ביישומי השורש שלך</string>
<string name="log_data_magisk_none">יומני רישום Magisk ריקים, זה מוזר</string> <string name="log_data_magisk_none">יומני רישום Magisk ריקים, זה מוזר</string>
<string name="menuSaveLog">שמירת יומן רישום</string> <string name="menuSaveLog">שמירת יומן רישום</string>
<string name="menuClearLog">ניקוי יומן רישום כעת</string> <string name="menuClearLog">ניקוי יומן רישום כעת</string>
@@ -92,7 +91,7 @@
<!--SafetyNet--> <!--SafetyNet-->
<!-- MagiskHide --> <!--MagiskHide-->
<string name="show_system_app">הצגת יישומי מערכת</string> <string name="show_system_app">הצגת יישומי מערכת</string>
<string name="show_os_app">הצגת יישומי מערכת הפעלה</string> <string name="show_os_app">הצגת יישומי מערכת הפעלה</string>
<string name="hide_filter_hint">סינון לפי שם</string> <string name="hide_filter_hint">סינון לפי שם</string>
@@ -100,14 +99,16 @@
<!--Module--> <!--Module-->
<string name="no_info_provided">(לא סופק מידע)</string> <string name="no_info_provided">(לא סופק מידע)</string>
<string name="reboot_userspace">אתחול מהיר</string> <string name="reboot_userspace">אתחול רך</string>
<string name="reboot_recovery">אתחול למצב שחזור</string> <string name="reboot_recovery">אתחול למצב שחזור</string>
<string name="reboot_bootloader">אתחול מצב מנהל האתחול</string> <string name="reboot_bootloader">אתחול לטוען האתחול</string>
<string name="reboot_download">אתחול מצב הורדה</string> <string name="reboot_download">אתחול למצב הורדה</string>
<string name="reboot_edl">אתחול למצב EDL</string> <string name="reboot_edl">אתחול למצב EDL</string>
<string name="reboot_safe_mode">מצב בטוח</string>
<string name="module_version_author">%1$s מאת %2$s</string> <string name="module_version_author">%1$s מאת %2$s</string>
<string name="module_state_remove">הסרה</string> <string name="module_state_remove">הסרה</string>
<string name="module_state_restore">שיחזור</string> <string name="module_action">פעולה</string>
<string name="module_state_restore">שחזור</string>
<string name="module_action_install_external">התקנה מהאחסון</string> <string name="module_action_install_external">התקנה מהאחסון</string>
<string name="update_available">עדכונים זמינים</string> <string name="update_available">עדכונים זמינים</string>
<string name="suspend_text_riru">מודול מושעה כי %1$s מופעל</string> <string name="suspend_text_riru">מודול מושעה כי %1$s מופעל</string>
@@ -117,7 +118,7 @@
<string name="confirm_install">להתקין מודול %1$s?</string> <string name="confirm_install">להתקין מודול %1$s?</string>
<string name="confirm_install_title">אישור התקנה</string> <string name="confirm_install_title">אישור התקנה</string>
<!--Settings --> <!--Settings-->
<string name="settings_dark_mode_title">מצב עיצוב</string> <string name="settings_dark_mode_title">מצב עיצוב</string>
<string name="settings_dark_mode_message">נא לבחור מצב המתאים ביותר לסגנון שלך!</string> <string name="settings_dark_mode_message">נא לבחור מצב המתאים ביותר לסגנון שלך!</string>
<string name="settings_dark_mode_light">תמיד בהיר</string> <string name="settings_dark_mode_light">תמיד בהיר</string>
@@ -128,11 +129,11 @@
<string name="settings_hide_app_title">הסתרת היישום Magisk</string> <string name="settings_hide_app_title">הסתרת היישום Magisk</string>
<string name="settings_hide_app_summary">התקנת יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string> <string name="settings_hide_app_summary">התקנת יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string>
<string name="settings_restore_app_title">שיחזור היישום Magisk</string> <string name="settings_restore_app_title">שיחזור היישום Magisk</string>
<string name="settings_restore_app_summary">יש לבטל את הסתרת היישום ולשחזור אותו ל-APK המקורי</string> <string name="settings_restore_app_summary">ביטול הסתרת היישום ושחזור אל ה-APK המקורי</string>
<string name="language">שפה</string> <string name="language">שפה</string>
<string name="system_default">(ברירת מחדל מערכת)</string> <string name="system_default">(ברירת מחדל מערכת)</string>
<string name="settings_check_update_title">בדיקת עדכונים</string> <string name="settings_check_update_title">בדיקת עדכונים</string>
<string name="settings_check_update_summary">בדוק מעת לעת ברקע אם יש עדכונים</string> <string name="settings_check_update_summary">בדיקה מעת לעת ברקע אם יש עדכונים</string>
<string name="settings_update_channel_title">ערוץ עדכון</string> <string name="settings_update_channel_title">ערוץ עדכון</string>
<string name="settings_update_stable">יציב</string> <string name="settings_update_stable">יציב</string>
<string name="settings_update_beta">בטא</string> <string name="settings_update_beta">בטא</string>
@@ -161,12 +162,12 @@
<string name="settings_su_request_60">60 שניות</string> <string name="settings_su_request_60">60 שניות</string>
<string name="superuser_access">גישת משתמש על</string> <string name="superuser_access">גישת משתמש על</string>
<string name="auto_response">תגובה אוטומטית</string> <string name="auto_response">תגובה אוטומטית</string>
<string name="request_timeout">בקש פסק זמן</string> <string name="request_timeout">בקשת פסק זמן</string>
<string name="superuser_notification">התראות משתמש על</string> <string name="superuser_notification">התראות משתמש על</string>
<string name="settings_su_reauth_title">אימות מחדש לאחר שדרוג</string> <string name="settings_su_reauth_title">אימות מחדש לאחר שדרוג</string>
<string name="settings_su_reauth_summary">אימות מחדש הרשאות של משתמש על לאחר שדרוג יישום</string> <string name="settings_su_reauth_summary">אימות מחדש הרשאות של משתמש על לאחר שדרוג יישום</string>
<string name="settings_su_tapjack_title">הפעלת הגנת Tapjacking</string> <string name="settings_su_tapjack_title">הגנת Tapjacking</string>
<string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או כיסוי אחר</string> <string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או שכבת על אחרת</string>
<string name="settings_su_auth_title">אימות משתמש</string> <string name="settings_su_auth_title">אימות משתמש</string>
<string name="settings_su_auth_summary">בקשת אימות משתמש במהלך בקשות משתמש על</string> <string name="settings_su_auth_summary">בקשת אימות משתמש במהלך בקשות משתמש על</string>
<string name="settings_su_auth_insecure">לא מוגדרת שיטת אימות בהתקן</string> <string name="settings_su_auth_insecure">לא מוגדרת שיטת אימות בהתקן</string>
@@ -174,6 +175,8 @@
<string name="setting_add_shortcut_summary">הוספת קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string> <string name="setting_add_shortcut_summary">הוספת קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string>
<string name="settings_doh_title">DNS על HTTPS</string> <string name="settings_doh_title">DNS על HTTPS</string>
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string> <string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
<string name="settings_random_name_title">שם פלט אקראי</string>
<string name="settings_random_name_description">שם אקראי לקובץ הפלט של תמונות מתוקנות וקבצי tar כדי למנוע זיהוי</string>
<string name="multiuser_mode">מצב מרובה משתמשים</string> <string name="multiuser_mode">מצב מרובה משתמשים</string>
<string name="settings_owner_only">בעל ההתקן בלבד</string> <string name="settings_owner_only">בעל ההתקן בלבד</string>
<string name="settings_owner_manage">אחראי ניהול ההתקן</string> <string name="settings_owner_manage">אחראי ניהול ההתקן</string>
@@ -205,10 +208,13 @@
<string name="repo_install_title">מתקין %1$s %2$s(%3$d)</string> <string name="repo_install_title">מתקין %1$s %2$s(%3$d)</string>
<string name="download">הורדה</string> <string name="download">הורדה</string>
<string name="reboot">הפעלה מחדש</string> <string name="reboot">הפעלה מחדש</string>
<string name="close">סגירה</string>
<string name="release_notes">הערות שחרור</string> <string name="release_notes">הערות שחרור</string>
<string name="flashing">צורב…</string> <string name="flashing">צורב…</string>
<string name="running">רץ…</string>
<string name="done">בוצע!</string> <string name="done">בוצע!</string>
<string name="failure">נכשל</string> <string name="done_action">בוצעה ריצת פעולה של %1$s</string>
<string name="failure">נכשל!</string>
<string name="hide_app_title">מסתיר את יישום Magisk…</string> <string name="hide_app_title">מסתיר את יישום Magisk…</string>
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string> <string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
<string name="complete_uninstall">הסרה מלאה</string> <string name="complete_uninstall">הסרה מלאה</string>
@@ -237,4 +243,5 @@
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string> <string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
<string name="reboot_apply_change">ייש להפעיל מחדש כדי להחיל שינויים</string> <string name="reboot_apply_change">ייש להפעיל מחדש כדי להחיל שינויים</string>
<string name="restore_app_confirmation">פעולה זו תשחזר את היישום המוסתר חזרה ליישום המקורי. האם בוודאות ברצונך לעשות את זה?</string> <string name="restore_app_confirmation">פעולה זו תשחזר את היישום המוסתר חזרה ליישום המקורי. האם בוודאות ברצונך לעשות את זה?</string>
</resources> </resources>

View File

@@ -105,6 +105,7 @@
<string name="reboot_safe_mode">Modo de segurança</string> <string name="reboot_safe_mode">Modo de segurança</string>
<string name="module_version_author">%1$s por %2$s</string> <string name="module_version_author">%1$s por %2$s</string>
<string name="module_state_remove">Remover</string> <string name="module_state_remove">Remover</string>
<string name="module_action">Ação</string>
<string name="module_state_restore">Restaurar</string> <string name="module_state_restore">Restaurar</string>
<string name="module_action_install_external">Instalar a partir do armazenamento</string> <string name="module_action_install_external">Instalar a partir do armazenamento</string>
<string name="update_available">Atualização disponível</string> <string name="update_available">Atualização disponível</string>
@@ -173,7 +174,7 @@
<string name="settings_doh_title">DNS sobre HTTPS</string> <string name="settings_doh_title">DNS sobre HTTPS</string>
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string> <string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
<string name="settings_random_name_title">Randomizar nome de saída</string> <string name="settings_random_name_title">Randomizar nome de saída</string>
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar para evitar a detecção</string> <string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar (*.tar) para evitar a detecção</string>
<string name="multiuser_mode">Modo multiusuário</string> <string name="multiuser_mode">Modo multiusuário</string>
<string name="settings_owner_only">Somente proprietário do dispositivo</string> <string name="settings_owner_only">Somente proprietário do dispositivo</string>
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string> <string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
@@ -205,9 +206,12 @@
<string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string> <string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string>
<string name="download">Baixar</string> <string name="download">Baixar</string>
<string name="reboot">Reiniciar</string> <string name="reboot">Reiniciar</string>
<string name="close">Fechar</string>
<string name="release_notes">Notas da atualização</string> <string name="release_notes">Notas da atualização</string>
<string name="flashing">Flashando…</string> <string name="flashing">Flashando…</string>
<string name="running">Executando…</string>
<string name="done">Concluído!</string> <string name="done">Concluído!</string>
<string name="done_action">Ação de execução de %1$s concluída</string>
<string name="failure">Falhou!</string> <string name="failure">Falhou!</string>
<string name="hide_app_title">Ocultando o app do Magisk…</string> <string name="hide_app_title">Ocultando o app do Magisk…</string>
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string> <string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>

View File

@@ -105,6 +105,7 @@
<string name="reboot_safe_mode">Modo de segurança</string> <string name="reboot_safe_mode">Modo de segurança</string>
<string name="module_version_author">%1$s por %2$s</string> <string name="module_version_author">%1$s por %2$s</string>
<string name="module_state_remove">Remover</string> <string name="module_state_remove">Remover</string>
<string name="module_action">Ação</string>
<string name="module_state_restore">Restaurar</string> <string name="module_state_restore">Restaurar</string>
<string name="module_action_install_external">Instalar a partir do armazenamento</string> <string name="module_action_install_external">Instalar a partir do armazenamento</string>
<string name="update_available">Atualização disponível</string> <string name="update_available">Atualização disponível</string>
@@ -173,7 +174,7 @@
<string name="settings_doh_title">DNS sobre HTTPS</string> <string name="settings_doh_title">DNS sobre HTTPS</string>
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string> <string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
<string name="settings_random_name_title">Randomizar nome de saída</string> <string name="settings_random_name_title">Randomizar nome de saída</string>
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar para evitar a detecção</string> <string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar (*.tar) para evitar a detecção</string>
<string name="multiuser_mode">Modo multiusuário</string> <string name="multiuser_mode">Modo multiusuário</string>
<string name="settings_owner_only">Somente proprietário do dispositivo</string> <string name="settings_owner_only">Somente proprietário do dispositivo</string>
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string> <string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
@@ -205,9 +206,12 @@
<string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string> <string name="repo_install_title">Instalar %1$s %2$s(%3$d)</string>
<string name="download">Baixar</string> <string name="download">Baixar</string>
<string name="reboot">Reiniciar</string> <string name="reboot">Reiniciar</string>
<string name="close">Fechar</string>
<string name="release_notes">Notas da atualização</string> <string name="release_notes">Notas da atualização</string>
<string name="flashing">Flashando…</string> <string name="flashing">Flashando…</string>
<string name="running">Executando…</string>
<string name="done">Concluído!</string> <string name="done">Concluído!</string>
<string name="done_action">Ação de execução de %1$s concluída</string>
<string name="failure">Falhou!</string> <string name="failure">Falhou!</string>
<string name="hide_app_title">Ocultando o app do Magisk…</string> <string name="hide_app_title">Ocultando o app do Magisk…</string>
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string> <string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>

View File

@@ -74,7 +74,6 @@
<string name="su_revoke_msg">Konfirmo për të hequr të drejtat e %1$s?</string> <string name="su_revoke_msg">Konfirmo për të hequr të drejtat e %1$s?</string>
<string name="toast">Dolli</string> <string name="toast">Dolli</string>
<string name="none">Asnjë</string> <string name="none">Asnjë</string>
<string name="superuser_toggle_notification">Njoftimet</string> <string name="superuser_toggle_notification">Njoftimet</string>
<string name="superuser_toggle_revoke">Të drejtat</string> <string name="superuser_toggle_revoke">Të drejtat</string>
<string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar akoma akses për super-përdoruesin.</string> <string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar akoma akses për super-përdoruesin.</string>
@@ -91,8 +90,6 @@
<string name="selinux_context">Konteksti SELinux: %s</string> <string name="selinux_context">Konteksti SELinux: %s</string>
<string name="supp_group">Grupi suplementar: %s</string> <string name="supp_group">Grupi suplementar: %s</string>
<!--SafetyNet-->
<!--MagiskHide--> <!--MagiskHide-->
<string name="show_system_app">Shfaq aplikacionet e sistemit</string> <string name="show_system_app">Shfaq aplikacionet e sistemit</string>
<string name="show_os_app">Shfaq aplikacionet e sistemit operativ</string> <string name="show_os_app">Shfaq aplikacionet e sistemit operativ</string>
@@ -109,6 +106,7 @@
<string name="reboot_safe_mode">Rinis në safe mode</string> <string name="reboot_safe_mode">Rinis në safe mode</string>
<string name="module_version_author">%1$s nga %2$s</string> <string name="module_version_author">%1$s nga %2$s</string>
<string name="module_state_remove">Hiqe</string> <string name="module_state_remove">Hiqe</string>
<string name="module_action">Veprim</string>
<string name="module_state_restore">Rikëthe</string> <string name="module_state_restore">Rikëthe</string>
<string name="module_action_install_external">Instaloni nga sdcard</string> <string name="module_action_install_external">Instaloni nga sdcard</string>
<string name="update_available">Përditësimi në dispozicion</string> <string name="update_available">Përditësimi në dispozicion</string>
@@ -207,9 +205,12 @@
<string name="repo_install_title">Instalo %1$s %2$s(%3$d)</string> <string name="repo_install_title">Instalo %1$s %2$s(%3$d)</string>
<string name="download">Shkarko</string> <string name="download">Shkarko</string>
<string name="reboot">Rinis</string> <string name="reboot">Rinis</string>
<string name="close">Mbylle</string>
<string name="release_notes">Shënimet e lëshimit</string> <string name="release_notes">Shënimet e lëshimit</string>
<string name="flashing">Duke flashuar…</string> <string name="flashing">Duke flashuar…</string>
<string name="running">Duke vepruar...</string>
<string name="done">U krye!</string> <string name="done">U krye!</string>
<string name="done_action">Veprimi i ekzekutimit të %1$s u krye</string>
<string name="failure">Dështoi!</string> <string name="failure">Dështoi!</string>
<string name="hide_app_title">Fshehja e aplikacionit Magisk…</string> <string name="hide_app_title">Fshehja e aplikacionit Magisk…</string>
<string name="open_link_failed_toast">Nuk u gjet asnjë aplikacion për të hapur lidhjen</string> <string name="open_link_failed_toast">Nuk u gjet asnjë aplikacion për të hapur lidhjen</string>

View File

@@ -12,21 +12,21 @@
<!--Home--> <!--Home-->
<string name="no_connection">Bağlantı yok</string> <string name="no_connection">Bağlantı yok</string>
<string name="app_changelog">Değişiklik günlüğü</string> <string name="app_changelog">Değişiklik Günlüğü</string>
<string name="loading">Yükleniyor…</string> <string name="loading">Yükleniyor…</string>
<string name="update">Güncelle</string> <string name="update">Güncelle</string>
<string name="not_available">Yüklü değil</string> <string name="not_available">Yok</string>
<string name="hide">Gizle</string> <string name="hide">Gizle</string>
<string name="home_package">Paket</string> <string name="home_package">Paket</string>
<string name="home_app_title">Uygulama</string> <string name="home_app_title">Uygulama</string>
<string name="home_notice_content">Magisk\'i YALNIZCA resmi GitHub sayfasından indirin. Bilinmeyen kaynaklardan gelen dosyalar kötü amaçlı olabilir!</string> <string name="home_notice_content">Magisk\'i YALNIZCA resmi GitHub sayfasından indirin. Bilinmeyen kaynaklardan gelen dosyalar zararlı olabilir!</string>
<string name="home_support_title">Bizi Destekleyin</string> <string name="home_support_title">Bizi Destekleyin</string>
<string name="home_follow_title">Bizi Takip Edin</string> <string name="home_follow_title">Bizi Takip Edin</string>
<string name="home_item_source">Kaynak</string> <string name="home_item_source">Kaynak</string>
<string name="home_support_content">Magisk ücretsiz ve açık kaynaktır ve her zaman öyle kalacaktır. Ancak bir bağış yaparak bize destek olduğunuzu gösterebilirsiniz.</string> <string name="home_support_content">Magisk her zaman ücretsiz ve açık kaynak olacaktır. Ancak, bir bağış yaparak bize destek olabilirsiniz.</string>
<string name="home_installed_version">Durum</string> <string name="home_installed_version">Yüklü Sürüm</string>
<string name="home_latest_version">En son sürüm</string> <string name="home_latest_version">En Son Sürüm</string>
<string name="invalid_update_channel">Geçersiz Güncelleme Kanalı</string> <string name="invalid_update_channel">Geçersiz Güncelleme Kanalı</string>
<string name="uninstall_magisk_title">Magisk\'i Kaldır</string> <string name="uninstall_magisk_title">Magisk\'i Kaldır</string>
<string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacak!\nKök kaldırılacak!\nMagisk kullanılarak şifrelenmemiş herhangi bir dahili depolama yeniden şifrelenecek!</string> <string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacak!\nKök kaldırılacak!\nMagisk kullanılarak şifrelenmemiş herhangi bir dahili depolama yeniden şifrelenecek!</string>
@@ -38,14 +38,14 @@
<string name="install_options_title">Seçenekler</string> <string name="install_options_title">Seçenekler</string>
<string name="install_method_title">Yöntem</string> <string name="install_method_title">Yöntem</string>
<string name="install_next">Sonraki</string> <string name="install_next">Sonraki</string>
<string name="install_start">Haydi başlayalım</string> <string name="install_start">Hadi başlayalım</string>
<string name="manager_download_install">İndirmek ve yüklemek için basın</string> <string name="manager_download_install">İndirmek ve yüklemek için basın</string>
<string name="direct_install">Doğrudan Kurulum (Önerilir)</string> <string name="direct_install">Doğrudan Yükleme (Önerilir)</string>
<string name="install_inactive_slot">Etkin Olmayan Yuvaya Yükle (OTA\'dan Sonra)</string> <string name="install_inactive_slot">Etkin Olmayan Slot\'a Yükle (OTA Sonrası)</string>
<string name="install_inactive_slot_msg">Yeniden başlatmanın ardından cihazınız mevcut etkin olmayan yuvaya önyükleme yapmaya ZORLANACAK!\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam edilsin mi?</string> <string name="install_inactive_slot_msg">Cihazınız yeniden başlatıldıktan sonra zorunlu olarak mevcut etkin olmayan slota önyükleme yapılacaktır!\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam etmek istiyor musunuz?</string>
<string name="setup_title">Ek Kurulum</string> <string name="setup_title">Ek Kurulum</string>
<string name="select_patch_file">Bir Dosya Seç ve Yama Yap</string> <string name="select_patch_file">Bir Dosya Seç ve Yama Yap</string>
<string name="patch_file_msg">Bir ham görüntü (*.img) veya bir ODIN tar dosyası (*.tar) veya bir payload.bin (*.bin) seçin</string> <string name="patch_file_msg">Ham bir görüntü (*.img) veya bir ODIN tar dosyası (*.tar) veya bir payload.bin (*.bin) seçin</string>
<string name="reboot_delay_toast">5 saniye içinde yeniden başlatılıyor…</string> <string name="reboot_delay_toast">5 saniye içinde yeniden başlatılıyor…</string>
<string name="flash_screen_title">Yükleniyor</string> <string name="flash_screen_title">Yükleniyor</string>
@@ -53,42 +53,42 @@
<string name="su_request_title">Süper Kullanıcı İsteği</string> <string name="su_request_title">Süper Kullanıcı İsteği</string>
<string name="touch_filtered_warning">Bir uygulama bir Süper Kullanıcı isteğini engellediği için Magisk yanıtınızı doğrulayamıyor</string> <string name="touch_filtered_warning">Bir uygulama bir Süper Kullanıcı isteğini engellediği için Magisk yanıtınızı doğrulayamıyor</string>
<string name="deny">Reddet</string> <string name="deny">Reddet</string>
<string name="prompt">Sor</string> <string name="prompt">İstem</string>
<string name="grant">İzin ver</string> <string name="grant">İzin Ver</string>
<string name="su_warning">Cihazınıza tam erişim sağlar.\nEğer emin değilseniz reddedin!</string> <string name="su_warning">Cihazınıza tam erişim sağlar.\nEmin değilseniz reddedin!</string>
<string name="forever">Daima</string> <string name="forever">Daima</string>
<string name="once">Bir kez</string> <string name="once">Bir kez</string>
<string name="tenmin">10 dakika</string> <string name="tenmin">10 dakika</string>
<string name="twentymin">20 dakika</string> <string name="twentymin">20 dakika</string>
<string name="thirtymin">30 dakika</string> <string name="thirtymin">30 dakika</string>
<string name="sixtymin">60 dakika</string> <string name="sixtymin">60 dakika</string>
<string name="su_allow_toast">%1$s uygulamasının Süper Kullanıcı izni verildi</string> <string name="su_allow_toast">%1$s uygulamasının süper kullanıcı hakları verildi</string>
<string name="su_deny_toast">%1$s uygulamasının Süper Kullanıcı izni reddedildi</string> <string name="su_deny_toast">%1$s uygulamasının süper kullanıcı hakları reddedildi</string>
<string name="su_snack_grant">%1$s uygulamasının Süper Kullanıcı izni verildi</string> <string name="su_snack_grant">%1$s uygulamasının süper kullanıcı hakları verildi</string>
<string name="su_snack_deny">%1$s uygulamasının Süper Kullanıcı izni reddedildi</string> <string name="su_snack_deny">%1$s uygulamasının süper kullanıcı hakları reddedildi</string>
<string name="su_snack_notif_on">%1$s uygulamasının bildirimleri etkinleştirildi</string> <string name="su_snack_notif_on">%1$s uygulamasının bildirimleri etkinleştirildi</string>
<string name="su_snack_notif_off">%1$s uygulamasının bildirimleri devre dışı bırakıldı</string> <string name="su_snack_notif_off">%1$s uygulamasının bildirimleri devre dışı bırakıldı</string>
<string name="su_snack_log_on">%1$s uygulamasının günlüğü etkinleştirildi</string> <string name="su_snack_log_on">%1$s uygulamasının günlüğü etkinleştirildi</string>
<string name="su_snack_log_off">%1$s uygulamasının günlüğü devre dışı bırakıldı</string> <string name="su_snack_log_off">%1$s uygulamasının günlüğü devre dışı bırakıldı</string>
<string name="su_revoke_title">İptal et?</string> <string name="su_revoke_title">İptal Et?</string>
<string name="su_revoke_msg">%1$s uygulamasının Süper Kullanıcı haklarını iptal etmeyi onaylayın</string> <string name="su_revoke_msg">%1$s uygulamasının süper kullanıcı haklarını iptal etmek istediğinize emin misiniz?</string>
<string name="toast">Tost</string> <string name="toast">Bildirim</string>
<string name="none">Hiçbiri</string> <string name="none">Yok</string>
<string name="superuser_toggle_notification">Bildirimler</string> <string name="superuser_toggle_notification">Bildirimler</string>
<string name="superuser_toggle_revoke">İptal et</string> <string name="superuser_toggle_revoke">İptal Et</string>
<string name="superuser_policy_none">Henüz hiçbir uygulama Süper Kullanıcı izni istemedi.</string> <string name="superuser_policy_none">Henüz hiçbir uygulama Süper Kullanıcı izni istemedi.</string>
<!--Logs--> <!--Logs-->
<string name="log_data_none">Günlük kullanmıyorsunuz, kök uygulamalarınızı daha fazla kullanmayı deneyin</string> <string name="log_data_none">Günlük kullanmıyorsunuz, root (kök) uygulamalarınızı daha çok kullanmayı deneyin</string>
<string name="log_data_magisk_none">Magisk günlükleri boş, bu garip</string> <string name="log_data_magisk_none">Magisk günlükleri boş, bu tuhaf</string>
<string name="menuSaveLog">Günlüğü kaydet</string> <string name="menuSaveLog">Günlüğü kaydet</string>
<string name="menuClearLog">Günlüğü şimdi temizle</string> <string name="menuClearLog">Günlüğü şimdi temizle</string>
<string name="logs_cleared">Günlük kaydı başarıyla temizlendi</string> <string name="logs_cleared">Günlük kaydı başarıyla temizlendi</string>
<string name="pid">PID: %1$d</string> <string name="pid">PID: %1$d</string>
<string name="target_uid">Hedef UID: %1$d</string> <string name="target_uid">Hedef UID: %1$d</string>
<string name="target_pid">Ns hedef PID\'sini bağla: %s</string> <string name="target_pid">Mount ns hedef PID: %s</string>
<string name="selinux_context">SELinux içeriği: %s</string> <string name="selinux_context">SELinux bağlamı: %s</string>
<string name="supp_group">Ek grup: %s</string> <string name="supp_group">Ek grup: %s</string>
<!--SafetyNet--> <!--SafetyNet-->
@@ -96,7 +96,7 @@
<!--MagiskHide--> <!--MagiskHide-->
<string name="show_system_app">Sistem uygulamalarını göster</string> <string name="show_system_app">Sistem uygulamalarını göster</string>
<string name="show_os_app">İşletim sistemi uygulamalarını göster</string> <string name="show_os_app">İşletim sistemi uygulamalarını göster</string>
<string name="hide_filter_hint">Ada göre filtrele</string> <string name="hide_filter_hint">İsme göre filtrele</string>
<string name="hide_search">Ara</string> <string name="hide_search">Ara</string>
<!--Module--> <!--Module-->
@@ -106,13 +106,14 @@
<string name="reboot_bootloader">Önyükleyici modunda yeniden başlat</string> <string name="reboot_bootloader">Önyükleyici modunda yeniden başlat</string>
<string name="reboot_download">İndirme modunda yeniden başlat</string> <string name="reboot_download">İndirme modunda yeniden başlat</string>
<string name="reboot_edl">EDL modunda yeniden başlat</string> <string name="reboot_edl">EDL modunda yeniden başlat</string>
<string name="reboot_safe_mode">Güvenli mod</string>
<string name="module_version_author">%1$s / %2$s</string> <string name="module_version_author">%1$s / %2$s</string>
<string name="module_state_remove">Kaldır</string> <string name="module_state_remove">Kaldır</string>
<string name="module_state_restore">Geri yükle</string> <string name="module_state_restore">Geri Yükle</string>
<string name="module_action_install_external">Depolamadan yükle</string> <string name="module_action_install_external">Depolamadan yükle</string>
<string name="update_available">Güncelleme Mevcut</string> <string name="update_available">Güncelleme Mevcut</string>
<string name="suspend_text_riru">%1$s etkinleştirildiği için modül askıya alındı</string> <string name="suspend_text_riru">Modül, %1$s etkin olduğu için askıya alındı</string>
<string name="suspend_text_zygisk">%1$s etkinleştirilmediği için modül askıya alındı</string> <string name="suspend_text_zygisk">Modül, %1$s etkin olmadığı için askıya alındı</string>
<string name="zygisk_module_unloaded">Uyumsuzluk nedeniyle Zygisk modülü yüklenmedi</string> <string name="zygisk_module_unloaded">Uyumsuzluk nedeniyle Zygisk modülü yüklenmedi</string>
<string name="module_empty">Yüklü modül yok</string> <string name="module_empty">Yüklü modül yok</string>
<string name="confirm_install">%1$s modülü yüklensin mi?</string> <string name="confirm_install">%1$s modülü yüklensin mi?</string>
@@ -121,39 +122,39 @@
<!--Settings--> <!--Settings-->
<string name="settings_dark_mode_title">Tema Modu</string> <string name="settings_dark_mode_title">Tema Modu</string>
<string name="settings_dark_mode_message">Tarzınıza en uygun modu seçin!</string> <string name="settings_dark_mode_message">Tarzınıza en uygun modu seçin!</string>
<string name="settings_dark_mode_light">Daima Açık</string> <string name="settings_dark_mode_light">Her Zaman Aydınlık</string>
<string name="settings_dark_mode_system">Sistemi Takip Et</string> <string name="settings_dark_mode_system">Sistemi Takip Et</string>
<string name="settings_dark_mode_dark">Daima Koyu</string> <string name="settings_dark_mode_dark">Her Zaman Karanlık</string>
<string name="settings_download_path_title">İndirme yolu</string> <string name="settings_download_path_title">İndirme Yolu</string>
<string name="settings_download_path_message">Dosyalar %1$s konumuna kaydedilecek</string> <string name="settings_download_path_message">Dosyalar %1$s konumuna kaydedilecek</string>
<string name="settings_hide_app_title">Magisk uygulamasını gizle</string> <string name="settings_hide_app_title">Magisk uygulamasını gizle</string>
<string name="settings_hide_app_summary">Rastgele bir paket kimliği ve özel uygulama etiketi olan bir proxy uygulaması yükleyin</string> <string name="settings_hide_app_summary">Rastgele bir paket kimliği ve özel uygulama etiketi olan bir vekil (proxy) uygulaması yükleyin</string>
<string name="settings_restore_app_title">Magisk uygulamasını geri yükle</string> <string name="settings_restore_app_title">Magisk uygulamasını geri yükle</string>
<string name="settings_restore_app_summary">Uygulamayı göster ve orijinal APK\'yı geri yükle</string> <string name="settings_restore_app_summary">Uygulamayı göster ve orijinal APK\'yı geri yükle</string>
<string name="language">Dil</string> <string name="language">Dil</string>
<string name="system_default">(Sistem Varsayılanı)</string> <string name="system_default">(Sistem Varsayılanı)</string>
<string name="settings_check_update_title">Güncellemeleri Kontrol Et</string> <string name="settings_check_update_title">Güncellemeleri Kontrol Et</string>
<string name="settings_check_update_summary">Arka plandaki güncellemeleri düzenli olarak kontrol et</string> <string name="settings_check_update_summary">Arka planda düzenli olarak güncellemeleri kontrol et</string>
<string name="settings_update_channel_title">Güncelleme Kanalı</string> <string name="settings_update_channel_title">Güncelleme Kanalı</string>
<string name="settings_update_stable">Stabil</string> <string name="settings_update_stable">Kararlı</string>
<string name="settings_update_beta">Beta</string> <string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Özel</string> <string name="settings_update_custom">Özel</string>
<string name="settings_update_custom_msg">Özel bir kanal bağlantısı ekle</string> <string name="settings_update_custom_msg">Özel kanal URL\'si girin</string>
<string name="settings_zygisk_summary">Zygisk arka plan programında Magisk\'in bazı bölümlerini çalıştır</string> <string name="settings_zygisk_summary">Magisk\'in bazı bölümlerini zygote daemon\'unda çalıştır</string>
<string name="settings_denylist_title">Reddetme Listesini Zorla</string> <string name="settings_denylist_title">Reddetme Listesini Zorla</string>
<string name="settings_denylist_summary">Reddetme listesindeki işlemlerde tüm Magisk değişiklikleri geri alınır</string> <string name="settings_denylist_summary">Reddetme Listesindeki işlemler tüm Magisk değişikliklerini geri alacak</string>
<string name="settings_denylist_config_title">Reddetme Listesini Yapılandır</string> <string name="settings_denylist_config_title">Reddetme Listesini Yapılandır</string>
<string name="settings_denylist_config_summary">Reddetme listesine dahil edilecek işlemleri seç</string> <string name="settings_denylist_config_summary">Reddetme Listesine dahil edilecek işlemleri seçin</string>
<string name="settings_hosts_title">Sistemsiz ana makineler (systemless hosts)</string> <string name="settings_hosts_title">Sistemsiz ana makineler (systemless hosts)</string>
<string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz ana makineler (systemless hosts) desteği</string> <string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz ana makineler (systemless hosts) desteği</string>
<string name="settings_hosts_toast">Sistemsiz ana makineler (systemless hosts) modülü eklendi</string> <string name="settings_hosts_toast">Sistemsiz ana makineler (systemless hosts) modülü eklendi</string>
<string name="settings_app_name_hint">Yeni ad</string> <string name="settings_app_name_hint">Yeni ad</string>
<string name="settings_app_name_helper">Uygulama bu adla yeniden paketlenecek</string> <string name="settings_app_name_helper">Uygulama bu isimle yeniden paketlenecek</string>
<string name="settings_app_name_error">Geçersiz format</string> <string name="settings_app_name_error">Geçersiz format</string>
<string name="settings_su_app_adb">Uygulamalar ve ADB</string> <string name="settings_su_app_adb">Uygulamalar ve ADB</string>
<string name="settings_su_app">Yalnızca uygulamalar</string> <string name="settings_su_app">Sadece Uygulamalar</string>
<string name="settings_su_adb">Yalnızca ADB</string> <string name="settings_su_adb">Sadece ADB</string>
<string name="settings_su_disable">Devre dışı</string> <string name="settings_su_disable">Devre Dışı</string>
<string name="settings_su_request_10">10 saniye</string> <string name="settings_su_request_10">10 saniye</string>
<string name="settings_su_request_15">15 saniye</string> <string name="settings_su_request_15">15 saniye</string>
<string name="settings_su_request_20">20 saniye</string> <string name="settings_su_request_20">20 saniye</string>
@@ -164,39 +165,41 @@
<string name="auto_response">Otomatik Yanıt</string> <string name="auto_response">Otomatik Yanıt</string>
<string name="request_timeout">İstek Zaman Aşımı</string> <string name="request_timeout">İstek Zaman Aşımı</string>
<string name="superuser_notification">Süper Kullanıcı Bildirimi</string> <string name="superuser_notification">Süper Kullanıcı Bildirimi</string>
<string name="settings_su_reauth_title">Yükseltmeden sonra yeniden kimlik doğrulaması yap</string> <string name="settings_su_reauth_title">Yükseltme sonrası yeniden doğrulama yap</string>
<string name="settings_su_reauth_summary">Uygulamaları yükselttikten sonra Süper Kullanıcı izinlerini tekrar iste</string> <string name="settings_su_reauth_summary">Uygulama güncellemelerinden sonra Süper Kullanıcı izinlerini tekrar iste</string>
<string name="settings_su_tapjack_title">Sahte Ekran (Tapjacking) Koruması</string> <string name="settings_su_tapjack_title">Tapjacking Koruması</string>
<string name="settings_su_tapjack_summary">Süper Kullanıcı bilgi istemi iletişim kutusu, herhangi bir başka pencere veya yer paylaşımı tarafından engellendiğinde gire yanıt vermeyecektir.</string> <string name="settings_su_tapjack_summary">Süper Kullanıcı istemi diyalogu, başka bir pencere veya katman tarafından gizlendiğinde girdilere yanıt vermeyecektir</string>
<string name="settings_su_auth_title">Kullanıcı Kimlik Doğrulaması</string> <string name="settings_su_auth_title">Kullanıcı Kimlik Doğrulama</string>
<string name="settings_su_auth_summary">Süper Kullanıcı istekleri sırasında kullanıcı kimlik doğrulaması iste</string> <string name="settings_su_auth_summary">Süper Kullanıcı isteklerinde kullanıcı kimlik doğrulaması iste</string>
<string name="settings_su_auth_insecure">Cihazda hiçbir kimlik doğrulama yöntemi yapılandırılmamış</string> <string name="settings_su_auth_insecure">Cihazda yapılandırılmış bir kimlik doğrulama yöntemi yok</string>
<string name="settings_customization">Özelleştir</string> <string name="settings_customization">Özelleştir</string>
<string name="setting_add_shortcut_summary">Uygulamayı gizledikten sonra adın ve simgenin tanınmasının zor olması durumunda ana ekrana güzel bir kısayol ekle</string> <string name="setting_add_shortcut_summary">Uygulamayı gizledikten sonra adı ve simgeyi tanımakta zorlanıyorsanız ana ekrana güzel bir kısayol ekle</string>
<string name="settings_doh_title">HTTPS üzerinden DNS</string> <string name="settings_doh_title">DNS üzerinden HTTPS</string>
<string name="settings_doh_description">Bazı ülkelerde DNS zehirlenmesine geçici çözüm</string> <string name="settings_doh_description">Bazı ülkelerde DNS zehirlemesine karşı geçici çözüm</string>
<string name="settings_random_name_title">Çıkış adını rastgele seç</string>
<string name="settings_random_name_description">Algılamayı önlemek için yamalı resimlerin ve tar dosyalarının çıkış dosya adını rastgele seç</string>
<string name="multiuser_mode">Çok Kullanıcılı Mod</string> <string name="multiuser_mode">Çok Kullanıcılı Mod</string>
<string name="settings_owner_only">Yalnızca Cihaz Sahibi</string> <string name="settings_owner_only">Yalnızca Cihaz Sahibi</string>
<string name="settings_owner_manage">Cihaz Sahibi Tarafından Yönetildi</string> <string name="settings_owner_manage">Cihaz Sahibi Yönetiminde</string>
<string name="settings_user_independent">Kullanıcıdan Bağımsız</string> <string name="settings_user_independent">Kullanıcıdan Bağımsız</string>
<string name="owner_only_summary">Kök erişimi yalnızca sahibine aittir</string> <string name="owner_only_summary">Yalnızca sahip kök (root) erişimine sahiptir</string>
<string name="owner_manage_summary">Kök erişimini yalnızca sahip yönetebilir ve istek istemlerini alabilir</string> <string name="owner_manage_summary">Yalnızca sahip kök (root) erişimini yönetebilir ve istek uyarılarını alabilir</string>
<string name="user_independent_summary">Her kullanıcının kendi ayrı kök kuralları vardır</string> <string name="user_independent_summary">Her kullanıcının kendi ayrı kök (root) kuralları vardır</string>
<string name="mount_namespace_mode">Bağlama Ad Alanı Modu</string> <string name="mount_namespace_mode">Bağlama Ad Alanı Modu</string>
<string name="settings_ns_global">Küresel Ad Alanı</string> <string name="settings_ns_global">Küresel Ad Alanı</string>
<string name="settings_ns_requester">Ad Alanını Devral</string> <string name="settings_ns_requester">Ad Alanını Devral</string>
<string name="settings_ns_isolate">İzole Edilmiş Ad Alanı</string> <string name="settings_ns_isolate">İzolasyon Ad Alanı</string>
<string name="global_summary">Tüm kök oturumları, global bağlama ad alanını kullanır</string> <string name="global_summary">Tüm kök (root) oturumları küresel bağlama ad alanını kullanır</string>
<string name="requester_summary">Kök oturumları, istek sahibinin ad alanını devralır</string> <string name="requester_summary">Kök (root) oturumları isteyicisinin ad alanını devralacak</string>
<string name="isolate_summary">Her kök oturumun kendi izole edilmiş ad alanı olacaktır</string> <string name="isolate_summary">Her kök (root) oturumu kendi izole ad alanına sahip olacak</string>
<!--Notifications--> <!--Notifications-->
<string name="update_channel">Magisk Güncellemeleri</string> <string name="update_channel">Magisk Güncellemeleri</string>
<string name="progress_channel">İlerleme Bildirimleri</string> <string name="progress_channel">İlerleme Bildirimleri</string>
<string name="updated_channel">Güncelleme Tamamlandı</string> <string name="updated_channel">Güncelleme Tamamlandı</string>
<string name="download_complete">İndirme Tamamlandı</string> <string name="download_complete">İndirme tamamlandı</string>
<string name="download_file_error">Dosya indirilirken hata oluştu</string> <string name="download_file_error">Dosya indirilirken hata oluştu</string>
<string name="magisk_update_title">Magisk Güncellemesi Mevcut!</string> <string name="magisk_update_title">Magisk Güncellemesi Mevcut!</string>
<string name="updated_title">Magisk Güncellendi</string> <string name="updated_title">Magisk Güncellendi</string>
@@ -204,41 +207,41 @@
<!--Toasts, Dialogs--> <!--Toasts, Dialogs-->
<string name="yes">Mevcut</string> <string name="yes">Mevcut</string>
<string name="no">Mevcut değil</string> <string name="no">Mevcut Değil</string>
<string name="repo_install_title">%1$s %2$s(%3$d) yükle</string> <string name="repo_install_title">%1$s %2$s(%3$d) Kur</string>
<string name="download">İndir</string> <string name="download">İndir</string>
<string name="reboot">Yeniden başlat</string> <string name="reboot">Yeniden Başlat</string>
<string name="release_notes">Sürüm notları</string> <string name="release_notes">Sürüm Notları</string>
<string name="flashing">Flaşlanıyor…</string> <string name="flashing">Yükleniyor...</string>
<string name="done">Tamamlandı!</string> <string name="done">Tamamlandı!</string>
<string name="failure">Başarısız!</string> <string name="failure">Başarısız!</string>
<string name="hide_app_title">Magisk uygulaması gizleniyor…</string> <string name="hide_app_title">Magisk uygulaması gizleniyor…</string>
<string name="open_link_failed_toast">Bağlantıyıacak uygulama bulunamadı</string> <string name="open_link_failed_toast">Bağlantıyımak için uygulama bulunamadı</string>
<string name="complete_uninstall">Kaldırmayı Tamamla</string> <string name="complete_uninstall">Tamamen Kaldır</string>
<string name="restore_img">Görüntüleri Geri Yükle</string> <string name="restore_img">Görüntüleri Geri Yükle</string>
<string name="restore_img_msg">Geri yükleniyor</string> <string name="restore_img_msg">Geri Yükleniyor...</string>
<string name="restore_done">Geri yükleme tamamlandı!</string> <string name="restore_done">Geri yükleme tamamlandı!</string>
<string name="restore_fail">Stok yedeği mevcut değil!</string> <string name="restore_fail">Stok yedeği mevcut değil!</string>
<string name="setup_fail">Kurulum başarısız oldu</string> <string name="setup_fail">Kurulum başarısız oldu</string>
<string name="env_fix_title">Ek Kurulum Gerekiyor</string> <string name="env_fix_title">Ek Ayar Gerekiyor</string>
<string name="env_fix_msg">Magisk\'in düzgün çalışması için cihazınızın ek kuruluma ihtiyacı var. Devam etmek ve yeniden başlatmak istiyor musunuz?</string> <string name="env_fix_msg">Magisk\'in düzgün çalışabilmesi için cihazınızın ek ayarlar yapması gerekiyor. Devam etmek ve yeniden başlatmak istiyor musunuz?</string>
<string name="env_full_fix_msg">Cihazınızın düzgün çalışması için Magisk\'in yeniden başlatılması gerekiyor. Lütfen Magisk\'i uygulama içinden yeniden yükleyin, kurtarma modu doğru cihaz bilgilerini alamıyor.</string> <string name="env_full_fix_msg">Cihazınızın düzgün çalışabilmesi için Magisk\'in yeniden yüklenmesi gerekiyor. Lütfen Magisk\'i uygulama içinde yeniden yükleyin, kurtarma modu doğru cihaz bilgilerini alamaz.</string>
<string name="setup_msg">Ortam kurulumu çalıştırılıyor</string> <string name="setup_msg">Ortam kurulumu yapılıyor...</string>
<string name="unsupport_magisk_title">Desteklenmeyen Magisk Sürümü</string> <string name="unsupport_magisk_title">Desteklenmeyen Magisk Sürümü</string>
<string name="unsupport_magisk_msg">Uygulamanın bu sürümü %1$s altındaki Magisk sürümlerini desteklemiyor.\n\nUygulama Magisk yüklenmemiş gibi davranacak, lütfen en kısa sürede Magisk\'i yükseltin.</string> <string name="unsupport_magisk_msg">Bu uygulama sürümü, %1$s altındaki Magisk sürümlerini desteklemiyor.\n\nUygulama, Magisk yüklü değilmiş gibi davranacaktır, lütfen en kısa sürede Magisk\'i güncelleyin.</string>
<string name="unsupport_general_title">Anormal Durum</string> <string name="unsupport_general_title">Anormal Durum</string>
<string name="unsupport_system_app_msg">Bu uygulamanın sistem uygulaması olarak çalıştırılması desteklenmiyor. Lütfen uygulamayı bir kullanıcı uygulamasına geri yükleyin.</string> <string name="unsupport_system_app_msg">Bu uygulamanın sistem uygulaması olarak çalıştırılması desteklenmiyor. Lütfen uygulamayı kullanıcı uygulamasına geri döndürün.</string>
<string name="unsupport_other_su_msg">Magisk\'ten olmayan bir \"su\" ikilisi algılandı. Lütfen rakip kök çözümlerini kaldırın ve/veya Magisk\'i yeniden yükleyin.</string> <string name="unsupport_other_su_msg">Magisk\'ten gelmeyen bir "su" ikili dosyası tespit edildi. Lütfen herhangi bir rakip kök (root) çözümünü kaldırın ve/veya Magisk\'i yeniden yükleyin.</string>
<string name="unsupport_external_storage_msg">Magisk harici depolamaya yüklenmiş. Lütfen uygulamayı dahili depolamaya taşıyın.</string> <string name="unsupport_external_storage_msg">Magisk harici depolamaya yüklendi. Lütfen uygulamayı dahili depolamaya taşıyın.</string>
<string name="unsupport_nonroot_stub_msg">Kök (root) kaybolduğu için gizli Magisk uygulaması çalışmaya devam edemiyor. Lütfen orijinal APK\'yı geri yükleyin.</string> <string name="unsupport_nonroot_stub_msg">Gizli Magisk uygulaması kök (root) erişimi kaybolduğu için çalışmaya devam edemez. Lütfen orijinal APK\'yı geri yükleyin.</string>
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string> <string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
<string name="external_rw_permission_denied">Bu işlevi etkinleştirmek için depolama izni veriniz.</string> <string name="external_rw_permission_denied">Bu işlevselliği etkinleştirmek için depolama izni verin</string>
<string name="post_notifications_denied">Bu işlevi etkinleştirmek için bildirim izni veriniz.</string> <string name="post_notifications_denied">Bu işlevselliği etkinleştirmek için bildirim izni verin</string>
<string name="install_unknown_denied">Bu işlevi etkinleştirmek için "Bilinmeyen uygulamaları yükle" ayarına izin veriniz.</string> <string name="install_unknown_denied">Bu işlevselliği etkinleştirmek için "bilinmeyen uygulamaları yükle" iznini verin</string>
<string name="add_shortcut_title">Ana ekrana kısayol ekle</string> <string name="add_shortcut_title">Ana ekrana kısayol ekle</string>
<string name="add_shortcut_msg">Bu uygulamayı gizledikten sonra adını ve simgesini tanımak zorlaşabilir. Ana ekrana güzel bir kısayol eklemek ister misiniz?</string> <string name="add_shortcut_msg">Bu uygulamayı gizledikten sonra adı ve simgesi tanınmayabilir. Ana ekrana güzel bir kısayol eklemek ister misiniz?</string>
<string name="app_not_found">Bu eylemi gerçekleştirecek uygulama bulunamadı</string> <string name="app_not_found">Bu lemi gerçekleştirecek uygulama bulunamadı</string>
<string name="reboot_apply_change">Değişiklikleri uygulamak için yeniden başlatın</string> <string name="reboot_apply_change">Değişiklikleri uygulamak için yeniden başlatın</string>
<string name="restore_app_confirmation">Bu işlem, gizli uygulamayı orijinal uygulama ile değiştirecektir. Bu işlemi yapmak istediğinizden emin misiniz?</string> <string name="restore_app_confirmation">Bu, gizli uygulamayı orijinal uygulamaya geri yükleyecektir. Gerçekten bunu yapmak istiyor musunuz?</string>
</resources> </resources>

View File

@@ -109,6 +109,7 @@
<string name="reboot_safe_mode">安全模式</string> <string name="reboot_safe_mode">安全模式</string>
<string name="module_version_author">%1$s作者 %2$s</string> <string name="module_version_author">%1$s作者 %2$s</string>
<string name="module_state_remove">移除</string> <string name="module_state_remove">移除</string>
<string name="module_action">操作</string>
<string name="module_state_restore">还原</string> <string name="module_state_restore">还原</string>
<string name="module_action_install_external">从本地安装</string> <string name="module_action_install_external">从本地安装</string>
<string name="update_available">可更新</string> <string name="update_available">可更新</string>
@@ -176,6 +177,8 @@
<string name="setting_add_shortcut_summary">在隐藏后难以识别名称和图标的情况下,添加快捷方式到桌面</string> <string name="setting_add_shortcut_summary">在隐藏后难以识别名称和图标的情况下,添加快捷方式到桌面</string>
<string name="settings_doh_title">安全 DNSDoH</string> <string name="settings_doh_title">安全 DNSDoH</string>
<string name="settings_doh_description">解决某些地区的 DNS 污染问题</string> <string name="settings_doh_description">解决某些地区的 DNS 污染问题</string>
<string name="settings_random_name_title">随机文件名</string>
<string name="settings_random_name_description">随机修补镜像和 tar 文件的文件名以防止检测</string>
<string name="multiuser_mode">多用户模式</string> <string name="multiuser_mode">多用户模式</string>
<string name="settings_owner_only">仅设备所有者</string> <string name="settings_owner_only">仅设备所有者</string>
@@ -209,9 +212,12 @@
<string name="repo_install_title">安装 %1$s %2$s(%3$d)</string> <string name="repo_install_title">安装 %1$s %2$s(%3$d)</string>
<string name="download">下载</string> <string name="download">下载</string>
<string name="reboot">重启</string> <string name="reboot">重启</string>
<string name="close">关闭</string>
<string name="release_notes">发布说明</string> <string name="release_notes">发布说明</string>
<string name="flashing">正在刷入</string> <string name="flashing">正在刷入</string>
<string name="running">运行中……</string>
<string name="done">完成!</string> <string name="done">完成!</string>
<string name="done_action">%1$s 操作运行完成</string>
<string name="failure">失败</string> <string name="failure">失败</string>
<string name="hide_app_title">正在隐藏 Magisk 应用</string> <string name="hide_app_title">正在隐藏 Magisk 应用</string>
<string name="open_link_failed_toast">找不到能打开此链接的应用</string> <string name="open_link_failed_toast">找不到能打开此链接的应用</string>

View File

@@ -109,6 +109,7 @@
<string name="reboot_safe_mode">Safe mode</string> <string name="reboot_safe_mode">Safe mode</string>
<string name="module_version_author">%1$s by %2$s</string> <string name="module_version_author">%1$s by %2$s</string>
<string name="module_state_remove">Remove</string> <string name="module_state_remove">Remove</string>
<string name="module_action">Action</string>
<string name="module_state_restore">Restore</string> <string name="module_state_restore">Restore</string>
<string name="module_action_install_external">Install from storage</string> <string name="module_action_install_external">Install from storage</string>
<string name="update_available">Update Available</string> <string name="update_available">Update Available</string>
@@ -211,9 +212,12 @@
<string name="repo_install_title">Install %1$s %2$s(%3$d)</string> <string name="repo_install_title">Install %1$s %2$s(%3$d)</string>
<string name="download">Download</string> <string name="download">Download</string>
<string name="reboot">Reboot</string> <string name="reboot">Reboot</string>
<string name="close">Close</string>
<string name="release_notes">Release notes</string> <string name="release_notes">Release notes</string>
<string name="flashing">Flashing…</string> <string name="flashing">Flashing…</string>
<string name="running">Running…</string>
<string name="done">Done!</string> <string name="done">Done!</string>
<string name="done_action">Done running action of %1$s</string>
<string name="failure">Failed!</string> <string name="failure">Failed!</string>
<string name="hide_app_title">Hiding the Magisk app…</string> <string name="hide_app_title">Hiding the Magisk app…</string>
<string name="open_link_failed_toast">No app found to open the link</string> <string name="open_link_failed_toast">No app found to open the link</string>

View File

@@ -1,13 +1,22 @@
package com.topjohnwu.magisk; package com.topjohnwu.magisk;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo;
public class ProviderInstaller { public class ProviderInstaller {
private static final String GMS_PACKAGE_NAME = "com.google.android.gms";
public static boolean install(Context context) { public static boolean install(Context context) {
try { try {
// Check if gms is a system app
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(GMS_PACKAGE_NAME, 0);
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
return false;
}
// Try installing new SSL provider from Google Play Service // Try installing new SSL provider from Google Play Service
Context gms = context.createPackageContext("com.google.android.gms", Context gms = context.createPackageContext(GMS_PACKAGE_NAME,
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
gms.getClassLoader() gms.getClassLoader()
.loadClass("com.google.android.gms.common.security.ProviderInstallerImpl") .loadClass("com.google.android.gms.common.security.ProviderInstallerImpl")

View File

@@ -6,7 +6,7 @@ plugins {
lsparanoid { lsparanoid {
seed = if (RAND_SEED != 0) RAND_SEED else null seed = if (RAND_SEED != 0) RAND_SEED else null
includeDependencies = true includeDependencies = true
global = true classFilter = { true }
} }
android { android {
@@ -15,7 +15,7 @@ android {
val canary = !Config.version.contains(".") val canary = !Config.version.contains(".")
val url = if (canary) null val url = if (canary) null
else "https://cdn.jsdelivr.net/gh/topjohnwu/magisk-files@${Config.version}/app-release.apk" else "https://github.com/topjohnwu/Magisk/releases/download/v${Config.version}/Magisk-v${Config.version}.apk"
defaultConfig { defaultConfig {
applicationId = "com.topjohnwu.magisk" applicationId = "com.topjohnwu.magisk"
@@ -27,9 +27,9 @@ android {
buildTypes { buildTypes {
release { release {
proguardFiles("proguard-rules.pro")
isMinifyEnabled = true isMinifyEnabled = true
isShrinkResources = false isShrinkResources = false
proguardFiles("proguard-rules.pro")
} }
} }
@@ -38,7 +38,7 @@ android {
} }
} }
setupStub() setupStubApk()
dependencies { dependencies {
implementation(project(":app:shared")) implementation(project(":app:shared"))

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="upgrade_msg">عليك الترقية ماجـيسك Manager لإكمال تهيئة التطبيق.هل اكمل؟</string> <string name="upgrade_msg">عليك الترقية Magisk لإكمال تهيئة التطبيق. هل تريد التنزيل والتثبيت؟</string>
<string name="no_internet_msg">يرجى الاتصال بالانترنيت! ترقية ماجـيسك مطلوب...</string> <string name="no_internet_msg">يرجى اللإتصال بالإنترنت! ترقية Magisk مطلوبة.</string>
<string name="dling">جارٍ التنزيل</string> <string name="dling">جارٍ التنزيل</string>
<string name="relaunch_app">يرجى إعادة تشغيل التطبيق يدوياً</string>
</resources> </resources>

661
build.py
View File

@@ -5,6 +5,7 @@ import lzma
import multiprocessing import multiprocessing
import os import os
import platform import platform
import re
import shutil import shutil
import stat import stat
import subprocess import subprocess
@@ -38,6 +39,7 @@ def vprint(str):
print(str) print(str)
# Environment checks and detection
is_windows = os.name == "nt" is_windows = os.name == "nt"
EXE_EXT = ".exe" if is_windows else "" EXE_EXT = ".exe" if is_windows else ""
@@ -51,7 +53,6 @@ if is_windows:
# We can't do ANSI color codes in terminal on Windows without colorama # We can't do ANSI color codes in terminal on Windows without colorama
no_color = True no_color = True
# Environment checks
if not sys.version_info >= (3, 8): if not sys.version_info >= (3, 8):
error("Requires Python 3.8+") error("Requires Python 3.8+")
@@ -63,42 +64,40 @@ except KeyError:
except KeyError: except KeyError:
error("Please set Android SDK path to environment variable ANDROID_HOME") error("Please set Android SDK path to environment variable ANDROID_HOME")
if shutil.which("sccache") is not None:
os.environ["RUSTC_WRAPPER"] = "sccache"
os.environ["NDK_CCACHE"] = "sccache"
os.environ["CARGO_INCREMENTAL"] = "0"
if shutil.which("ccache") is not None:
os.environ["NDK_CCACHE"] = "ccache"
cpu_count = multiprocessing.cpu_count() cpu_count = multiprocessing.cpu_count()
os_name = platform.system().lower() os_name = platform.system().lower()
archs = ["armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64"] # Common constants
triples = [ support_abis = {
"armv7a-linux-androideabi", "armeabi-v7a": "thumbv7neon-linux-androideabi",
"i686-linux-android", "x86": "i686-linux-android",
"aarch64-linux-android", "arm64-v8a": "aarch64-linux-android",
"x86_64-linux-android", "x86_64": "x86_64-linux-android",
"riscv64-linux-android", "riscv64": "riscv64-linux-android",
] }
default_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"] default_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
support_targets = default_targets + ["resetprop"] support_targets = default_targets | {"resetprop"}
rust_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"] rust_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
# Common paths
ndk_root = sdk_path / "ndk" ndk_root = sdk_path / "ndk"
ndk_path = ndk_root / "magisk" ndk_path = ndk_root / "magisk"
ndk_build = ndk_path / "ndk-build" ndk_build = ndk_path / "ndk-build"
rust_bin = ndk_path / "toolchains" / "rust" / "bin" rust_bin = ndk_path / "toolchains" / "rust" / "bin"
llvm_bin = ndk_path / "toolchains" / "llvm" / "prebuilt" / f"{os_name}-x86_64" / "bin" llvm_bin = ndk_path / "toolchains" / "llvm" / "prebuilt" / f"{os_name}-x86_64" / "bin"
cargo = rust_bin / f"cargo{EXE_EXT}" cargo = rust_bin / "cargo"
gradlew = Path("gradlew" + (".bat" if is_windows else "")).resolve() gradlew = Path.cwd() / "gradlew"
adb_path = sdk_path / "platform-tools" / f"adb{EXE_EXT}" adb_path = sdk_path / "platform-tools" / "adb"
native_gen_path = Path("native", "out", "generated").resolve() native_gen_path = Path("native", "out", "generated").resolve()
# Global vars # Global vars
config = {} config = {}
STDOUT = None args = {}
build_tools = None build_abis = {}
###################
# Helper functions
###################
def mv(source: Path, target: Path): def mv(source: Path, target: Path):
@@ -137,20 +136,26 @@ def rm_on_error(func, path, _):
def rm_rf(path: Path): def rm_rf(path: Path):
vprint(f"rm -rf {path}") vprint(f"rm -rf {path}")
shutil.rmtree(path, ignore_errors=False, onerror=rm_on_error) if sys.version_info >= (3, 12):
shutil.rmtree(path, ignore_errors=False, onexc=rm_on_error)
else:
shutil.rmtree(path, ignore_errors=False, onerror=rm_on_error)
def execv(cmd, env=None): def execv(cmds: list, env=None):
return subprocess.run(cmd, stdout=STDOUT, env=env) out = None if args.force_out or args.verbose > 0 else subprocess.DEVNULL
# Use shell on Windows to support PATHEXT
return subprocess.run(cmds, stdout=out, env=env, shell=is_windows)
def system(cmd): def cmd_out(cmds: list):
return subprocess.run(cmd, shell=True, stdout=STDOUT)
def cmd_out(cmd, env=None):
return ( return (
subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, env=env) subprocess.run(
cmds,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
shell=is_windows,
)
.stdout.strip() .stdout.strip()
.decode("utf-8") .decode("utf-8")
) )
@@ -160,51 +165,9 @@ def xz(data):
return lzma.compress(data, preset=9, check=lzma.CHECK_NONE) return lzma.compress(data, preset=9, check=lzma.CHECK_NONE)
def parse_props(file): ###############
props = {} # Build Native
with open(file, "r") as f: ###############
for line in [l.strip(" \t\r\n") for l in f]:
if line.startswith("#") or len(line) == 0:
continue
prop = line.split("=")
if len(prop) != 2:
continue
value = prop[1].strip(" \t\r\n")
if len(value) == 0:
continue
props[prop[0].strip(" \t\r\n")] = value
return props
def load_config(args):
commit_hash = cmd_out(["git", "rev-parse", "--short=8", "HEAD"])
# Default values
config["version"] = commit_hash
config["versionCode"] = 1000000
config["outdir"] = "out"
args.config = Path(args.config)
# Load prop files
if args.config.exists():
config.update(parse_props(args.config))
if Path("gradle.properties").exists():
for key, value in parse_props("gradle.properties").items():
if key.startswith("magisk."):
config[key[7:]] = value
try:
config["versionCode"] = int(config["versionCode"])
except ValueError:
error('Config error: "versionCode" is required to be an integer')
config["outdir"] = Path(config["outdir"])
config["outdir"].mkdir(mode=0o755, parents=True, exist_ok=True)
global STDOUT
STDOUT = None if args.verbose > 0 else subprocess.DEVNULL
def clean_elf(): def clean_elf():
@@ -225,94 +188,127 @@ def clean_elf():
elf_cleaner, elf_cleaner,
] ]
) )
args = [elf_cleaner, "--api-level", "23"] cmds = [elf_cleaner, "--api-level", "23"]
args.extend( cmds.extend(glob.glob("native/out/*/magisk"))
Path("native", "out", arch, bin) cmds.extend(glob.glob("native/out/*/magiskpolicy"))
for arch in archs execv(cmds)
for bin in ["magisk", "magiskpolicy"]
)
execv(args)
def run_ndk_build(args, flags): def run_ndk_build(cmds: list):
os.chdir("native") os.chdir("native")
flags = "NDK_PROJECT_PATH=. NDK_APPLICATION_MK=src/Application.mk " + flags cmds.append("NDK_PROJECT_PATH=.")
cmds.append("NDK_APPLICATION_MK=src/Application.mk")
cmds.append(f"APP_ABI={' '.join(build_abis.keys())}")
cmds.append(f"-j{cpu_count}")
if args.verbose > 1: if args.verbose > 1:
flags = "V=1 " + flags cmds.append("V=1")
proc = system(f"{ndk_build} {flags} -j{cpu_count}") if not args.release:
cmds.append("MAGISK_DEBUG=1")
proc = execv([ndk_build, *cmds])
if proc.returncode != 0: if proc.returncode != 0:
error("Build binary failed!") error("Build binary failed!")
os.chdir("..") os.chdir("..")
for arch in archs:
for tgt in support_targets + ["libinit-ld.so"]: for arch in build_abis.keys():
source = Path("native", "libs", arch, tgt) arch_dir = Path("native", "libs", arch)
target = Path("native", "out", arch, tgt) out_dir = Path("native", "out", arch)
for source in arch_dir.iterdir():
target = out_dir / source.name
mv(source, target) mv(source, target)
def build_cpp_src(targets: set):
dump_flag_header()
cmds = []
clean = False
if "magisk" in targets:
cmds.append("B_MAGISK=1")
clean = True
if "magiskpolicy" in targets:
cmds.append("B_POLICY=1")
clean = True
if "magiskinit" in targets:
cmds.append("B_PRELOAD=1")
if "resetprop" in targets:
cmds.append("B_PROP=1")
if cmds:
run_ndk_build(cmds)
cmds.clear()
if "magiskinit" in targets:
cmds.append("B_INIT=1")
if "magiskboot" in targets:
cmds.append("B_BOOT=1")
if cmds:
cmds.append("B_CRT0=1")
run_ndk_build(cmds)
if clean:
clean_elf()
def run_cargo(cmds): def run_cargo(cmds):
env = os.environ.copy() env = os.environ.copy()
env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}' env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}'
env["CARGO_BUILD_RUSTC"] = str(rust_bin / f"rustc{EXE_EXT}") env["CARGO_BUILD_RUSTC"] = str(rust_bin / f"rustc{EXE_EXT}")
env["RUSTFLAGS"] = f"-Clinker-plugin-lto -Zthreads={min(8, cpu_count)}" env["CARGO_BUILD_RUSTFLAGS"] = f"-Z threads={min(8, cpu_count)}"
return execv([cargo, *cmds], env) return execv([cargo, *cmds], env)
def run_cargo_build(args): def build_rust_src(targets: set):
native_out = Path("..", "out") targets = targets.copy()
native_out.mkdir(mode=0o755, exist_ok=True) if "resetprop" in targets:
targets = set(args.target) & set(rust_targets)
if "resetprop" in args.target:
targets.add("magisk") targets.add("magisk")
targets = targets & rust_targets
if len(targets) == 0: if not targets:
return return
# Start building the actual build commands os.chdir(Path("native", "src"))
# Start building the build commands
cmds = ["build", "-p", ""] cmds = ["build", "-p", ""]
rust_out = "debug"
if args.release: if args.release:
cmds.append("-r") cmds.append("-r")
rust_out = "release" profile = "release"
else:
profile = "debug"
if args.verbose == 0: if args.verbose == 0:
cmds.append("-q") cmds.append("-q")
elif args.verbose > 1: elif args.verbose > 1:
cmds.append("--verbose") cmds.append("--verbose")
cmds.append("--target") for triple in build_abis.values():
cmds.append("") cmds.append("--target")
cmds.append(triple)
for arch, triple in zip(archs, triples): for tgt in targets:
rust_triple = ( cmds[2] = tgt
"thumbv7neon-linux-androideabi" if triple.startswith("armv7") else triple proc = run_cargo(cmds)
) if proc.returncode != 0:
cmds[-1] = rust_triple error("Build binary failed!")
for target in targets: os.chdir(Path("..", ".."))
cmds[2] = target
proc = run_cargo(cmds)
if proc.returncode != 0:
error("Build binary failed!")
native_out = Path("native", "out")
rust_out = native_out / "rust"
for arch, triple in build_abis.items():
arch_out = native_out / arch arch_out = native_out / arch
arch_out.mkdir(mode=0o755, exist_ok=True) arch_out.mkdir(mode=0o755, exist_ok=True)
for tgt in targets: for tgt in targets:
source = Path("target", rust_triple, rust_out, f"lib{tgt}.a") source = rust_out / triple / profile / f"lib{tgt}.a"
target = arch_out / f"lib{tgt}-rs.a" target = arch_out / f"lib{tgt}-rs.a"
mv(source, target) mv(source, target)
def run_cargo_cmd(args):
global STDOUT
STDOUT = None
if len(args.commands) >= 1 and args.commands[0] == "--":
args.commands = args.commands[1:]
os.chdir(Path("native", "src"))
run_cargo(args.commands)
os.chdir(Path("..", ".."))
def write_if_diff(file_name: Path, text: str): def write_if_diff(file_name: Path, text: str):
do_write = True do_write = True
if file_name.exists(): if file_name.exists():
@@ -324,25 +320,6 @@ def write_if_diff(file_name: Path, text: str):
f.write(text) f.write(text)
def binary_dump(src, var_name, compressor=xz):
out_str = f"constexpr unsigned char {var_name}[] = {{"
for i, c in enumerate(compressor(src.read())):
if i % 16 == 0:
out_str += "\n"
out_str += f"0x{c:02X},"
out_str += "\n};\n"
return out_str
def dump_bin_header(args):
native_gen_path.mkdir(mode=0o755, parents=True, exist_ok=True)
for arch in archs:
preload = Path("native", "out", arch, "libinit-ld.so")
with open(preload, "rb") as src:
text = binary_dump(src, "init_ld_xz")
write_if_diff(Path(native_gen_path, f"{arch}_binaries.h"), text)
def dump_flag_header(): def dump_flag_header():
flag_txt = textwrap.dedent( flag_txt = textwrap.dedent(
"""\ """\
@@ -361,7 +338,7 @@ def dump_flag_header():
write_if_diff(Path(native_gen_path, "flags.h"), flag_txt) write_if_diff(Path(native_gen_path, "flags.h"), flag_txt)
def build_binary(args): def build_native():
# Verify NDK install # Verify NDK install
try: try:
with open(Path(ndk_path, "ONDK_VERSION"), "r") as ondk_ver: with open(Path(ndk_path, "ONDK_VERSION"), "r") as ondk_ver:
@@ -369,65 +346,29 @@ def build_binary(args):
except: except:
error('Unmatched NDK. Please install/upgrade NDK with "build.py ndk"') error('Unmatched NDK. Please install/upgrade NDK with "build.py ndk"')
if "target" not in vars(args): if "targets" not in vars(args) or not args.targets:
vars(args)["target"] = [] targets = default_targets
if args.target:
args.target = set(args.target) & set(support_targets)
if not args.target:
return
else: else:
args.target = default_targets targets = set(args.targets) & support_targets
if not targets:
return
header("* Building binaries: " + " ".join(args.target)) header("* Building: " + " ".join(targets))
os.chdir(Path("native", "src")) if sccache := shutil.which("sccache"):
run_cargo_build(args) os.environ["RUSTC_WRAPPER"] = sccache
os.chdir(Path("..", "..")) os.environ["NDK_CCACHE"] = sccache
os.environ["CARGO_INCREMENTAL"] = "0"
if ccache := shutil.which("ccache"):
os.environ["NDK_CCACHE"] = ccache
dump_flag_header() build_rust_src(targets)
build_cpp_src(targets)
flag = ""
clean = False
if "magisk" in args.target: ############
flag += " B_MAGISK=1" # Build App
clean = True ############
if "magiskpolicy" in args.target:
flag += " B_POLICY=1"
clean = True
if "magiskinit" in args.target:
flag += " B_PRELOAD=1"
if "resetprop" in args.target:
flag += " B_PROP=1"
if flag:
run_ndk_build(args, flag)
flag = ""
if "magiskinit" in args.target:
# magiskinit embeds preload.so
dump_bin_header(args)
flag += " B_INIT=1"
if "magiskboot" in args.target:
flag += " B_BOOT=1"
if flag:
flag += " B_CRT0=1"
run_ndk_build(args, flag)
if clean:
clean_elf()
# BusyBox is built with different API level
if "busybox" in args.target:
run_ndk_build(args, "B_BB=1")
def find_jdk(): def find_jdk():
@@ -462,7 +403,7 @@ def find_jdk():
return env return env
def build_apk(args, module): def build_apk(module: str):
env = find_jdk() env = find_jdk()
build_type = "Release" if args.release else "Debug" build_type = "Release" if args.release else "Debug"
@@ -488,9 +429,9 @@ def build_apk(args, module):
header(f"Output: {target}") header(f"Output: {target}")
def build_app(args): def build_app():
header("* Building the Magisk app") header("* Building the Magisk app")
build_apk(args, ":app:apk") build_apk(":app:apk")
build_type = "release" if args.release else "debug" build_type = "release" if args.release else "debug"
@@ -506,28 +447,32 @@ def build_app(args):
cp(source, target) cp(source, target)
def build_stub(args): def build_stub():
header("* Building the stub app") header("* Building the stub app")
build_apk(args, ":app:stub") build_apk(":app:stub")
def cleanup(args): ################
support_targets = {"native", "cpp", "rust", "java"} # Build General
if args.target: ################
args.target = set(args.target) & support_targets
if "native" in args.target:
args.target.add("cpp") def cleanup():
args.target.add("rust") support_targets = {"native", "cpp", "rust", "app"}
if args.targets:
targets = set(args.targets) & support_targets
if "native" in targets:
targets.add("cpp")
targets.add("rust")
else: else:
args.target = support_targets targets = support_targets
if "cpp" in args.target: if "cpp" in targets:
header("* Cleaning C++") header("* Cleaning C++")
rm_rf(Path("native", "libs")) rm_rf(Path("native", "libs"))
rm_rf(Path("native", "obj")) rm_rf(Path("native", "obj"))
rm_rf(Path("native", "out"))
if "rust" in args.target: if "rust" in targets:
header("* Cleaning Rust") header("* Cleaning Rust")
rm_rf(Path("native", "src", "target")) rm_rf(Path("native", "src", "target"))
rm(Path("native", "src", "boot", "proto", "mod.rs")) rm(Path("native", "src", "boot", "proto", "mod.rs"))
@@ -535,21 +480,34 @@ def cleanup(args):
for rs_gen in glob.glob("native/**/*-rs.*pp", recursive=True): for rs_gen in glob.glob("native/**/*-rs.*pp", recursive=True):
rm(rs_gen) rm(rs_gen)
if "java" in args.target: if "native" in targets:
header("* Cleaning java") rm_rf(Path("native", "out"))
execv(
[ if "app" in targets:
gradlew, header("* Cleaning app")
":app:apk:clean", execv([gradlew, ":app:clean"], env=find_jdk())
":app:core:clean",
":app:shared:clean",
":app:stub:clean",
],
env=find_jdk(),
)
def setup_ndk(args): def build_all():
build_native()
build_app()
############
# Utilities
############
def cargo_cli():
args.force_out = True
if len(args.commands) >= 1 and args.commands[0] == "--":
args.commands = args.commands[1:]
os.chdir(Path("native", "src"))
run_cargo(args.commands)
os.chdir(Path("..", ".."))
def setup_ndk():
ndk_ver = config["ondkVersion"] ndk_ver = config["ondkVersion"]
url = f"https://github.com/topjohnwu/ondk/releases/download/{ndk_ver}/ondk-{ndk_ver}-{os_name}.tar.xz" url = f"https://github.com/topjohnwu/ondk/releases/download/{ndk_ver}/ondk-{ndk_ver}-{os_name}.tar.xz"
ndk_archive = url.split("/")[-1] ndk_archive = url.split("/")[-1]
@@ -568,7 +526,7 @@ def setup_ndk(args):
mv(ondk_path, ndk_path) mv(ondk_path, ndk_path)
def push_files(args, script): def push_files(script):
abi = cmd_out([adb_path, "shell", "getprop", "ro.product.cpu.abi"]) abi = cmd_out([adb_path, "shell", "getprop", "ro.product.cpu.abi"])
if not abi: if not abi:
error("Cannot detect emulator ABI") error("Cannot detect emulator ABI")
@@ -596,37 +554,37 @@ def push_files(args, script):
error("adb push failed!") error("adb push failed!")
def setup_avd(args): def setup_avd():
if not args.skip: if not args.skip:
build_all(args) build_all()
header("* Setting up emulator") header("* Setting up emulator")
push_files(args, Path("scripts", "avd_magisk.sh")) push_files(Path("scripts", "avd_magisk.sh"))
proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_magisk.sh"]) proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_magisk.sh"])
if proc.returncode != 0: if proc.returncode != 0:
error("avd_magisk.sh failed!") error("avd_magisk.sh failed!")
def patch_avd_file(args): def patch_avd_file():
if not args.skip: if not args.skip:
args.release = False build_all()
build_all(args)
args.target = Path(args.target) input = Path(args.image)
src_file = f"/data/local/tmp/{args.target.name}"
out_file = f"{src_file}.magisk"
if args.output: if args.output:
args.output = Path(args.output) output = Path(args.output)
else: else:
args.output = args.target.parent / f"{args.target.name}.magisk" output = input.parent / f"{input.name}.magisk"
header(f"* Patching {args.target.name}") src_file = f"/data/local/tmp/{input.name}"
out_file = f"{src_file}.magisk"
push_files(args, Path("scripts", "avd_patch.sh")) header(f"* Patching {input.name}")
proc = execv([adb_path, "push", args.target, "/data/local/tmp"]) push_files(Path("scripts", "avd_patch.sh"))
proc = execv([adb_path, "push", input, "/data/local/tmp"])
if proc.returncode != 0: if proc.returncode != 0:
error("adb push failed!") error("adb push failed!")
@@ -634,19 +592,14 @@ def patch_avd_file(args):
if proc.returncode != 0: if proc.returncode != 0:
error("avd_patch.sh failed!") error("avd_patch.sh failed!")
proc = execv([adb_path, "pull", out_file, args.output]) proc = execv([adb_path, "pull", out_file, output])
if proc.returncode != 0: if proc.returncode != 0:
error("adb pull failed!") error("adb pull failed!")
header(f"Output: {args.output}") header(f"Output: {output}")
def build_all(args): def setup_rustup():
build_binary(args)
build_app(args)
def setup_rustup(args):
wrapper_dir = Path(args.wrapper_dir) wrapper_dir = Path(args.wrapper_dir)
rm_rf(wrapper_dir) rm_rf(wrapper_dir)
wrapper_dir.mkdir(mode=0o755, parents=True, exist_ok=True) wrapper_dir.mkdir(mode=0o755, parents=True, exist_ok=True)
@@ -662,10 +615,10 @@ def setup_rustup(args):
# Build rustup_wrapper # Build rustup_wrapper
wrapper_src = Path("tools", "rustup_wrapper") wrapper_src = Path("tools", "rustup_wrapper")
cargo_toml = wrapper_src / "Cargo.toml" cargo_toml = wrapper_src / "Cargo.toml"
execv( cmds = ["build", "--release", f"--manifest-path={cargo_toml}"]
[cargo, "build", "--release", f"--manifest-path={cargo_toml}"] if args.verbose > 1:
+ (["--verbose"] if args.verbose > 1 else []) cmds.append("--verbose")
) run_cargo(cmds)
# Replace rustup with wrapper # Replace rustup with wrapper
wrapper = wrapper_dir / (f"rustup{EXE_EXT}") wrapper = wrapper_dir / (f"rustup{EXE_EXT}")
@@ -674,77 +627,149 @@ def setup_rustup(args):
wrapper.chmod(0o755) wrapper.chmod(0o755)
parser = argparse.ArgumentParser(description="Magisk build script") ##################
parser.set_defaults(func=lambda x: None) # Config and args
parser.add_argument( ##################
"-r", "--release", action="store_true", help="compile in release mode"
)
parser.add_argument("-v", "--verbose", action="count", default=0, help="verbose output")
parser.add_argument(
"-c",
"--config",
default="config.prop",
help="custom config file (default: config.prop)",
)
subparsers = parser.add_subparsers(title="actions")
all_parser = subparsers.add_parser("all", help="build everything")
all_parser.set_defaults(func=build_all)
binary_parser = subparsers.add_parser("binary", help="build binaries") def parse_props(file):
binary_parser.add_argument( props = {}
"target", with open(file, "r") as f:
nargs="*", for line in [l.strip(" \t\r\n") for l in f]:
help=f"{', '.join(support_targets)}, \ if line.startswith("#") or len(line) == 0:
or empty for defaults ({', '.join(default_targets)})", continue
) prop = line.split("=")
binary_parser.set_defaults(func=build_binary) if len(prop) != 2:
continue
key = prop[0].strip(" \t\r\n")
value = prop[1].strip(" \t\r\n")
if not key or not value:
continue
props[key] = value
return props
cargo_parser = subparsers.add_parser("cargo", help="run cargo with proper environment")
cargo_parser.add_argument("commands", nargs=argparse.REMAINDER)
cargo_parser.set_defaults(func=run_cargo_cmd)
rustup_parser = subparsers.add_parser("rustup", help="setup rustup wrapper") def load_config():
rustup_parser.add_argument("wrapper_dir", help="path to setup rustup wrapper binaries") commit_hash = cmd_out(["git", "rev-parse", "--short=8", "HEAD"])
rustup_parser.set_defaults(func=setup_rustup)
app_parser = subparsers.add_parser("app", help="build the Magisk app") # Default values
app_parser.set_defaults(func=build_app) config["version"] = commit_hash
config["versionCode"] = 1000000
config["outdir"] = "out"
stub_parser = subparsers.add_parser("stub", help="build the stub app") args.config = Path(args.config)
stub_parser.set_defaults(func=build_stub)
avd_parser = subparsers.add_parser("emulator", help="setup AVD for development") # Load prop files
avd_parser.add_argument( if args.config.exists():
"-s", "--skip", action="store_true", help="skip building binaries and the app" config.update(parse_props(args.config))
)
avd_parser.set_defaults(func=setup_avd)
avd_patch_parser = subparsers.add_parser( if Path("gradle.properties").exists():
"avd_patch", help="patch AVD ramdisk.img or init_boot.img" for key, value in parse_props("gradle.properties").items():
) if key.startswith("magisk."):
avd_patch_parser.add_argument("target", help="path to ramdisk.img or init_boot.img") config[key[7:]] = value
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
avd_patch_parser.add_argument(
"-s", "--skip", action="store_true", help="skip building binaries and the app"
)
avd_patch_parser.set_defaults(func=patch_avd_file)
clean_parser = subparsers.add_parser("clean", help="cleanup") try:
clean_parser.add_argument( config["versionCode"] = int(config["versionCode"])
"target", nargs="*", help="native, cpp, rust, java, or empty to clean all" except ValueError:
) error('Config error: "versionCode" is required to be an integer')
clean_parser.set_defaults(func=cleanup)
ndk_parser = subparsers.add_parser("ndk", help="setup Magisk NDK") config["outdir"] = Path(config["outdir"])
ndk_parser.set_defaults(func=setup_ndk) config["outdir"].mkdir(mode=0o755, parents=True, exist_ok=True)
if len(sys.argv) == 1: if "abiList" in config:
parser.print_help() abiList = re.split("\\s*,\\s*", config["abiList"])
sys.exit(1) archs = set(abiList) & support_abis.keys()
else:
archs = {"armeabi-v7a", "x86", "arm64-v8a", "x86_64"}
args = parser.parse_args() triples = map(support_abis.get, archs)
load_config(args)
# Call corresponding functions global build_abis
args.func(args) build_abis = dict(zip(archs, triples))
def parse_args():
parser = argparse.ArgumentParser(description="Magisk build script")
parser.set_defaults(func=lambda x: None)
parser.add_argument(
"-r", "--release", action="store_true", help="compile in release mode"
)
parser.add_argument(
"-v", "--verbose", action="count", default=0, help="verbose output"
)
parser.add_argument(
"-c",
"--config",
default="config.prop",
help="custom config file (default: config.prop)",
)
subparsers = parser.add_subparsers(title="actions")
all_parser = subparsers.add_parser("all", help="build everything")
native_parser = subparsers.add_parser("native", help="build native binaries")
native_parser.add_argument(
"targets",
nargs="*",
help=f"{', '.join(support_targets)}, \
or empty for defaults ({', '.join(default_targets)})",
)
app_parser = subparsers.add_parser("app", help="build the Magisk app")
stub_parser = subparsers.add_parser("stub", help="build the stub app")
clean_parser = subparsers.add_parser("clean", help="cleanup")
clean_parser.add_argument(
"targets", nargs="*", help="native, cpp, rust, java, or empty to clean all"
)
ndk_parser = subparsers.add_parser("ndk", help="setup Magisk NDK")
emu_parser = subparsers.add_parser("emulator", help="setup AVD for development")
emu_parser.add_argument(
"-s", "--skip", action="store_true", help="skip building binaries and the app"
)
avd_patch_parser = subparsers.add_parser(
"avd_patch", help="patch AVD ramdisk.img or init_boot.img"
)
avd_patch_parser.add_argument("image", help="path to ramdisk.img or init_boot.img")
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
avd_patch_parser.add_argument(
"-s", "--skip", action="store_true", help="skip building binaries and the app"
)
cargo_parser = subparsers.add_parser(
"cargo", help="call 'cargo' commands against the project"
)
cargo_parser.add_argument("commands", nargs=argparse.REMAINDER)
rustup_parser = subparsers.add_parser("rustup", help="setup rustup wrapper")
rustup_parser.add_argument(
"wrapper_dir", help="path to setup rustup wrapper binaries"
)
# Set callbacks
all_parser.set_defaults(func=build_all)
native_parser.set_defaults(func=build_native)
cargo_parser.set_defaults(func=cargo_cli)
rustup_parser.set_defaults(func=setup_rustup)
app_parser.set_defaults(func=build_app)
stub_parser.set_defaults(func=build_stub)
emu_parser.set_defaults(func=setup_avd)
avd_patch_parser.set_defaults(func=patch_avd_file)
clean_parser.set_defaults(func=cleanup)
ndk_parser.set_defaults(func=setup_ndk)
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
return parser.parse_args()
args = parse_args()
load_config()
vars(args)["force_out"] = False
args.func()

View File

@@ -1,4 +1,4 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
plugins { plugins {
`kotlin-dsl` `kotlin-dsl`
@@ -18,17 +18,17 @@ gradlePlugin {
} }
} }
tasks.withType<KotlinCompile>().configureEach { kotlin {
kotlinOptions { compilerOptions {
languageVersion = "2.0" languageVersion = KotlinVersion.KOTLIN_2_0
} }
} }
dependencies { dependencies {
implementation(kotlin("gradle-plugin", "2.0.0")) implementation(kotlin("gradle-plugin", libs.versions.kotlin.get()))
implementation("com.android.tools.build:gradle:8.5.1") implementation(libs.android.gradle.plugin)
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.23") implementation(libs.ksp.plugin)
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7") implementation(libs.navigation.safe.args.plugin)
implementation("org.lsposed.lsparanoid:gradle-plugin:0.5.2") implementation(libs.lsparanoid.plugin)
implementation("org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r") implementation(libs.jgit)
} }

View File

@@ -0,0 +1,7 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}

View File

@@ -0,0 +1,67 @@
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Opcodes.ASM9
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
private const val DESUGAR_GET_TIME_DESC = "(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor
): ClassVisitor {
return DesugarClassVisitor(nextClassVisitor)
}
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
class DesugarClassVisitor(cv: ClassVisitor) : ClassVisitor(ASM9, cv) {
override fun visitMethod(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
return DesugarMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions))
}
}
class DesugarMethodVisitor(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
override fun visitMethodInsn(
opcode: Int,
owner: String,
name: String,
descriptor: String,
isInterface: Boolean
) {
if (!process(name, descriptor)) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
}
}
private fun process(name: String, descriptor: String): Boolean {
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
return false
when (name) {
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
DESUGAR_CLASS_NAME.replace('.', '/'),
name,
DESUGAR_GET_TIME_DESC,
false
)
}
else -> return false
}
return true
}
}
}

View File

@@ -8,6 +8,8 @@ import java.util.Properties
private val props = Properties() private val props = Properties()
private var commitHash = "" private var commitHash = ""
private val supportAbis = setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64")
private val defaultAbis = setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64")
object Config { object Config {
operator fun get(key: String): String? { operator fun get(key: String): String? {
@@ -20,6 +22,10 @@ object Config {
val version: String get() = get("version") ?: commitHash val version: String get() = get("version") ?: commitHash
val versionCode: Int get() = get("magisk.versionCode")!!.toInt() val versionCode: Int get() = get("magisk.versionCode")!!.toInt()
val stubVersion: String get() = get("magisk.stubVersion")!! val stubVersion: String get() = get("magisk.stubVersion")!!
val abiList: Set<String> get() {
val abiList = get("abiList") ?: return defaultAbis
return abiList.split(Regex("\\s*,\\s*")).toSet() intersect supportAbis
}
} }
class MagiskPlugin : Plugin<Project> { class MagiskPlugin : Plugin<Project> {

View File

@@ -1,6 +1,8 @@
import com.android.build.api.artifact.ArtifactTransformationRequest import com.android.build.api.artifact.ArtifactTransformationRequest
import com.android.build.api.artifact.SingleArtifact import com.android.build.api.artifact.SingleArtifact
import com.android.build.api.dsl.ApkSigningConfig import com.android.build.api.dsl.ApkSigningConfig
import com.android.build.api.instrumentation.FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
import com.android.build.api.instrumentation.InstrumentationScope
import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.gradle.BaseExtension import com.android.build.gradle.BaseExtension
import com.android.build.gradle.LibraryExtension import com.android.build.gradle.LibraryExtension
@@ -15,6 +17,7 @@ import org.gradle.api.Action
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.JavaVersion import org.gradle.api.JavaVersion
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Copy
@@ -69,18 +72,18 @@ private val Project.androidComponents
fun Project.setupCommon() { fun Project.setupCommon() {
androidBase { androidBase {
compileSdkVersion(34) compileSdkVersion(35)
buildToolsVersion = "34.0.0" buildToolsVersion = "34.0.0"
ndkPath = "$sdkDirectory/ndk/magisk" ndkPath = "$sdkDirectory/ndk/magisk"
ndkVersion = "27.0.11902837" ndkVersion = "27.0.12077973"
defaultConfig { defaultConfig {
minSdk = 23 minSdk = 23
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_21
} }
packagingOptions { packagingOptions {
@@ -108,31 +111,33 @@ fun Project.setupCommon() {
tasks.withType<KotlinCompile> { tasks.withType<KotlinCompile> {
compilerOptions { compilerOptions {
jvmTarget = JvmTarget.JVM_17 jvmTarget = JvmTarget.JVM_21
} }
} }
} }
const val BUSYBOX_DOWNLOAD_URL = const val BUSYBOX_DOWNLOAD_URL =
"https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.0.zip" "https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.1.zip"
const val BUSYBOX_ZIP_CHECKSUM = const val BUSYBOX_ZIP_CHECKSUM =
"ea4f3019b0087dcb68130b32ab59dc2db0ee0af11d8396124a94c4231c5ea441" "b4d0551feabaf314e53c79316c980e8f66432e9fb91a69dbbf10a93564b40951"
fun Project.setupCoreLib() { fun Project.setupCoreLib() {
setupCommon() setupCommon()
val abiList = Config.abiList
val syncLibs by tasks.registering(Sync::class) { val syncLibs by tasks.registering(Sync::class) {
into("src/main/jniLibs") into("src/main/jniLibs")
for (abi in arrayOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64")) { for (abi in abiList) {
into(abi) { into(abi) {
from(rootProject.file("native/out/$abi")) { from(rootProject.file("native/out/$abi")) {
include("magiskboot", "magiskinit", "magiskpolicy", "magisk") include("magiskboot", "magiskinit", "magiskpolicy", "magisk", "libinit-ld.so")
rename { "lib$it.so" } rename { if (it.endsWith(".so")) it else "lib$it.so" }
} }
} }
} }
onlyIf { onlyIf {
if (inputs.sourceFiles.files.size != 20) if (inputs.sourceFiles.files.size != abiList.size * 5)
throw StopExecutionException("Please build binaries first! (./build.py binary)") throw StopExecutionException("Please build binaries first! (./build.py binary)")
true true
} }
@@ -158,6 +163,7 @@ fun Project.setupCoreLib() {
} }
} }
from(zipTree(bb)) from(zipTree(bb))
include(abiList.map { "$it/libbusybox.so" })
into("src/main/jniLibs") into("src/main/jniLibs")
} }
@@ -293,7 +299,7 @@ fun Project.setupAppCommon() {
} }
defaultConfig { defaultConfig {
targetSdk = 34 targetSdk = 35
} }
buildTypes { buildTypes {
@@ -345,7 +351,34 @@ fun Project.setupAppCommon() {
} }
} }
fun Project.setupStub() { fun Project.setupMainApk() {
setupAppCommon()
android {
namespace = "com.topjohnwu.magisk"
defaultConfig {
applicationId = "com.topjohnwu.magisk"
vectorDrawables.useSupportLibrary = true
versionName = Config.version
versionCode = Config.versionCode
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
debugSymbolLevel = "FULL"
}
}
androidComponents.onVariants { variant ->
variant.instrumentation.apply {
setAsmFramesComputationMode(COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS)
transformClassesWith(
DesugarClassVisitorFactory::class.java, InstrumentationScope.ALL) {}
}
}
}
}
fun Project.setupStubApk() {
setupAppCommon() setupAppCommon()
androidComponents.onVariants { variant -> androidComponents.onVariants { variant ->
@@ -372,8 +405,8 @@ fun Project.setupStub() {
val outAppClassDir = layout.buildDirectory.file("generated/source/app/${variantLowered}").get().asFile val outAppClassDir = layout.buildDirectory.file("generated/source/app/${variantLowered}").get().asFile
val outResDir = layout.buildDirectory.dir("generated/source/res/${variantLowered}").get().asFile val outResDir = layout.buildDirectory.dir("generated/source/res/${variantLowered}").get().asFile
val aapt = File(androidApp.sdkDirectory, "build-tools/${androidApp.buildToolsVersion}/aapt2") val aapt = File(androidApp.sdkDirectory, "build-tools/${androidApp.buildToolsVersion}/aapt2")
val apk = layout.buildDirectory.file("intermediates/processed_res/" + val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
"${variantLowered}/process${variantCapped}Resources/out/resources-${variantLowered}.ap_").get().asFile "${variantLowered}/process${variantCapped}Resources/linked-resources-binary-format-${variantLowered}.ap_").get().asFile
val genManifestTask = tasks.register("generate${variantCapped}ObfuscatedClass") { val genManifestTask = tasks.register("generate${variantCapped}ObfuscatedClass") {
inputs.property("seed", RAND_SEED) inputs.property("seed", RAND_SEED)
@@ -414,8 +447,8 @@ fun Project.setupStub() {
registerJavaGeneratingTask(processResourcesTask, outResDir) registerJavaGeneratingTask(processResourcesTask, outResDir)
} }
// Override optimizeReleaseResources task // Override optimizeReleaseResources task
val apk = layout.buildDirectory.file("intermediates/processed_res/" + val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
"release/processReleaseResources/out/resources-release.ap_").get().asFile "release/processReleaseResources/linked-resources-binary-format-release.ap_").get().asFile
val optRes = layout.buildDirectory.file("intermediates/optimized_processed_res/" + val optRes = layout.buildDirectory.file("intermediates/optimized_processed_res/" +
"release/optimizeReleaseResources/resources-release-optimize.ap_").get().asFile "release/optimizeReleaseResources/resources-release-optimize.ap_").get().asFile
afterEvaluate { afterEvaluate {

View File

@@ -9,6 +9,10 @@ version=string
# Output path. Default: out # Output path. Default: out
outdir=string outdir=string
# List of ABIs to build, separated with ','
# Default: armeabi-v7a,x86,arm64-v8a,x86_64
abiList=[string]
##################################################### #####################################################
# Signing configs for signing zips and APKs # Signing configs for signing zips and APKs
# These 4 variables has to be either all set or not # These 4 variables has to be either all set or not

View File

@@ -1,5 +1,29 @@
# Magisk Changelog # Magisk Changelog
### v28.0
- [General] Support 16k page size
- [General] Add basic support for RISC-V (not built in releases)
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
- [Core] Remove unnecessary mirror for magic mount
- [Core] Update boot image detection logic to support more devices
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
- [MagiskInit] Update preinit partition detection
- [Zygisk] Update internal JNI hooking implementation
- [MagiskPolicy] Preserve sepolicy config flag after patching
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
- [DenyList] Support enforcing denylist when Zygisk is disabled
- [Resetprop] Improve implementation to workaround several property modification detections
- [Resetprop] Update to properly work with property overlays
- [App] Major internal code refactoring
- [App] Support patching Samsung firmware with images larger than 8GiB
- [App] Use user-initiated job instead of foreground services on Android 14
- [App] Support Android 13+ built-in per-app language preferences
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
- [MagiskBoot] Support spliting kernel images without decompression
- [MagiskBoot] Properly support vendor boot images
- [MagiskBoot] Disable Samsung PROCA from kernel image
### v27.0 ### v27.0
- [Zygisk] Introduce new code injection mechanism - [Zygisk] Introduce new code injection mechanism

View File

@@ -54,6 +54,7 @@ A Magisk module is a folder placed in `/data/adb/modules` with the structure bel
│ ├── post-fs-data.sh <--- This script will be executed in post-fs-data │ ├── post-fs-data.sh <--- This script will be executed in post-fs-data
│ ├── service.sh <--- This script will be executed in late_start service │ ├── service.sh <--- This script will be executed in late_start service
| ├── uninstall.sh <--- This script will be executed when Magisk removes your module | ├── uninstall.sh <--- This script will be executed when Magisk removes your module
| ├── action.sh <--- This script will be executed when user click the action button in Magisk app
│ ├── system.prop <--- Properties in this file will be loaded as system properties by resetprop │ ├── system.prop <--- Properties in this file will be loaded as system properties by resetprop
│ ├── sepolicy.rule <--- Additional custom sepolicy rules │ ├── sepolicy.rule <--- Additional custom sepolicy rules
│ │ │ │
@@ -231,7 +232,7 @@ The list above will result in the following files being created: `$MODPATH/syste
In Magisk, you can run boot scripts in 2 different modes: **post-fs-data** and **late_start service** mode. In Magisk, you can run boot scripts in 2 different modes: **post-fs-data** and **late_start service** mode.
- post-fs-data mode - post-fs-data mode
- This stage is BLOCKING. The boot process is paused before execution is done, or 10 seconds have passed. - This stage is BLOCKING. The boot process is paused before execution is done, or 40 seconds have passed.
- Scripts run before any modules are mounted. This allows a module developer to dynamically adjust their modules before it gets mounted. - Scripts run before any modules are mounted. This allows a module developer to dynamically adjust their modules before it gets mounted.
- This stage happens before Zygote is started, which pretty much means everything in Android - This stage happens before Zygote is started, which pretty much means everything in Android
- **WARNING:** using `setprop` will deadlock the boot process! Please use `resetprop -n <prop_name> <prop_value>` instead. - **WARNING:** using `setprop` will deadlock the boot process! Please use `resetprop -n <prop_name> <prop_value>` instead.

25
docs/releases/28000.md Normal file
View File

@@ -0,0 +1,25 @@
## 2024.10.10 Magisk v28.0
- [General] Support 16k page size
- [General] Add basic support for RISC-V (not built in releases)
- [General] Use a minimal libc to build static executables (`magiskinit` and `magiskboot`) for smaller sizes
- [Core] Remove unnecessary mirror for magic mount
- [Core] Update boot image detection logic to support more devices
- [MagiskInit] Rewrite 2SI logic for injecting `magiskinit` as `init`
- [MagiskInit] Update preinit partition detection
- [Zygisk] Update internal JNI hooking implementation
- [MagiskPolicy] Preserve sepolicy config flag after patching
- [MagiskPolicy] Optimize patching rules to reduce the amount of new rules being injected
- [DenyList] Support enforcing denylist when Zygisk is disabled
- [Resetprop] Improve implementation to workaround several property modification detections
- [Resetprop] Update to properly work with property overlays
- [App] Major internal code refactoring
- [App] Support patching Samsung firmware with images larger than 8GiB
- [App] Use user-initiated job instead of foreground services on Android 14
- [App] Support Android 13+ built-in per-app language preferences
- [App] Add `action.sh` support to allow modules to define an action triggered from UI
- [MagiskBoot] Support spliting kernel images without decompression
- [MagiskBoot] Properly support vendor boot images
- [MagiskBoot] Disable Samsung PROCA from kernel image
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)

View File

@@ -1,5 +1,6 @@
# Release Notes # Release Notes
- [v28.0](28000.md)
- [v27.0](27000.md) - [v27.0](27000.md)
- [v26.4](26400.md) - [v26.4](26400.md)
- [v26.3](26300.md) - [v26.3](26300.md)

View File

@@ -41,7 +41,9 @@ Supported actions:
repack [-n] <origbootimg> [outbootimg] repack [-n] <origbootimg> [outbootimg]
Repack boot image components using files from the current directory Repack boot image components using files from the current directory
to [outbootimg], or 'new-boot.img' if not specified. to [outbootimg], or 'new-boot.img' if not specified. Current directory
should only contain required files for [outbootimg], or incorrect
[outbootimg] may be produced.
<origbootimg> is the original boot image used to unpack the components. <origbootimg> is the original boot image used to unpack the components.
By default, each component will be automatically compressed using its By default, each component will be automatically compressed using its
corresponding format detected in <origbootimg>. If a component file corresponding format detected in <origbootimg>. If a component file

View File

@@ -20,6 +20,9 @@ org.gradle.parallel=true
# Enable build cache # Enable build cache
org.gradle.caching=true org.gradle.caching=true
# Use K2 in kapt
kapt.use.k2=true
# Android # Android
android.useAndroidX=true android.useAndroidX=true
android.injected.testOnly=false android.injected.testOnly=false
@@ -27,5 +30,5 @@ android.nonFinalResIds=false
# Magisk # Magisk
magisk.stubVersion=40 magisk.stubVersion=40
magisk.versionCode=27005 magisk.versionCode=28002
magisk.ondkVersion=r27.2 magisk.ondkVersion=r27.4

66
gradle/libs.versions.toml Normal file
View File

@@ -0,0 +1,66 @@
[versions]
kotlin = "2.0.21"
android = "8.7.2"
ksp = "2.0.21-1.0.28"
rikka = "1.3.0"
navigation = "2.8.4"
libsu = "6.0.0"
moshi = "1.15.1"
okhttp = "4.12.0"
retrofit = "2.11.0"
room = "2.6.1"
[libraries]
bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version = "1.79" }
commons-compress = { module = "org.apache.commons:commons-compress", version = "1.27.1" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
retrofit-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" }
markwon-core = { module = "io.noties.markwon:core", version = "4.6.2" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
timber = { module = "com.jakewharton.timber:timber", version = "5.0.1" }
jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version = "6.10.0.202406032230-r" }
# AndroidX
activity = { module = "androidx.activity:activity", version = "1.9.3" }
appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.0" }
core-ktx = { module = "androidx.core:core-ktx", version = "1.15.0" }
core-splashscreen = { module = "androidx.core:core-splashscreen", version = "1.0.1" }
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.2.0" }
fragment-ktx = { module = "androidx.fragment:fragment-ktx", version = "1.8.5" }
navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" }
navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version = "1.4.1" }
recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.3.2" }
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" }
transition = { module = "androidx.transition:transition", version = "1.5.1" }
collection-ktx = { module = "androidx.collection:collection-ktx", version = "1.4.5" }
lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version = "2.8.7" }
material = { module = "com.google.android.material:material", version = "1.12.0" }
jdk-libs = { module = "com.android.tools:desugar_jdk_libs_nio", version = "2.1.3" }
# topjohnwu
indeterminate-checkbox = { module = "com.github.topjohnwu:indeterminate-checkbox", version = "1.0.7" }
libsu-core = { module = "com.github.topjohnwu.libsu:core", version.ref = "libsu" }
libsu-service = { module = "com.github.topjohnwu.libsu:service", version.ref = "libsu" }
libsu-nio = { module = "com.github.topjohnwu.libsu:nio", version.ref = "libsu" }
# Rikka
rikka-recyclerview = { module = "dev.rikka.rikkax.recyclerview:recyclerview-ktx", version = "1.3.2" }
rikka-layoutinflater = { module = "dev.rikka.rikkax.layoutinflater:layoutinflater", version.ref = "rikka" }
rikka-insets = { module = "dev.rikka.rikkax.insets:insets", version.ref = "rikka" }
# Build plugins
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "android" }
ksp-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
navigation-safe-args-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "navigation" }
lsparanoid-plugin = { module = "org.lsposed.lsparanoid:gradle-plugin", version = "0.6.0" }
[plugins]

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,7 +1,10 @@
[build] [build]
# Choose arm64 as the default target to make the IDE happy. # Set arm64 as the default target
# The actual compilation will have the target overriden by command-line. # The actual compilation will have the target overriden by command-line.
target = "aarch64-linux-android" target = "aarch64-linux-android"
# Enable cross language LTO, and explicitly set dwarf-version for ThinLTO
rustflags = ["-Z", "dwarf-version=4", "-C", "linker-plugin-lto"]
target-dir = "../out/rust"
[unstable] [unstable]
build-std = ["std", "panic_abort"] build-std = ["std", "panic_abort"]

View File

@@ -1,2 +0,0 @@
test.cpp
target/

View File

@@ -1,7 +1,5 @@
APP_BUILD_SCRIPT := src/Android.mk APP_BUILD_SCRIPT := src/Android.mk
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 riscv64 APP_CFLAGS := -Wall -Oz -fomit-frame-pointer
APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto
APP_LDFLAGS := -flto -Wl,--icf=all
APP_CPPFLAGS := -std=c++23 APP_CPPFLAGS := -std=c++23
APP_STL := none APP_STL := none
APP_PLATFORM := android-23 APP_PLATFORM := android-23
@@ -9,11 +7,25 @@ APP_THIN_ARCHIVE := true
APP_STRIP_MODE := none APP_STRIP_MODE := none
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
ifdef MAGISK_DEBUG
NDK_APP_OUT := ./obj/debug
APP_CFLAGS += -flto=thin -gdwarf-4
APP_LDFLAGS += -flto=thin
else
NDK_APP_OUT := ./obj/release
APP_CFLAGS += -flto
APP_LDFLAGS += -flto -Wl,--icf=all
endif
ifdef B_CRT0 ifdef B_CRT0
# Disable all security and debugging features # Disable all security and debugging features
APP_CFLAGS += -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector -U_FORTIFY_SOURCE APP_CFLAGS += -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector -fno-threadsafe-statics -U_FORTIFY_SOURCE
# Override output folder to make sure all dependencies are rebuilt with new CFLAGS # Override output folder to make sure all dependencies are rebuilt with new CFLAGS
NDK_APP_OUT := ./obj/nolibc NDK_APP_OUT := $(NDK_APP_OUT)-nolibc
endif endif

340
native/src/Cargo.lock generated
View File

@@ -32,9 +32,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "base" name = "base"
@@ -66,27 +66,27 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.11.0-pre.5" version = "0.11.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ded684142010808eb980d9974ef794da2bcf97d13396143b1515e9f0fb4a10e" checksum = "17092d478f4fadfb35a7e082f62e49f0907fdf048801d9d706277e34f9df8a78"
dependencies = [ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.15.0" version = "1.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83"
dependencies = [ dependencies = [
"bytemuck_derive", "bytemuck_derive",
] ]
[[package]] [[package]]
name = "bytemuck_derive" name = "bytemuck_derive"
version = "1.6.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -101,9 +101,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.90" version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@@ -123,9 +123,9 @@ dependencies = [
[[package]] [[package]]
name = "const-oid" name = "const-oid"
version = "0.10.0-pre.2" version = "0.10.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e3352a27098ba6b09546e5f13b15165e6a88b5c2723afecb3ea9576b27e3ea" checksum = "9adcf94f05e094fca3005698822ec791cb4433ced416afda1c5ca3b8dfc05a2f"
[[package]] [[package]]
name = "const_format" name = "const_format"
@@ -158,9 +158,9 @@ dependencies = [
[[package]] [[package]]
name = "crypto-bigint" name = "crypto-bigint"
version = "0.6.0-pre.12" version = "0.6.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1943d7beadd9ce2b25f3bae73b9e9336fccc1edf38bdec1ed58d3aa183989e11" checksum = "e43027691f1c055da3da4f7d96af09fcec420d435d5616e51f29afd0811c56a7"
dependencies = [ dependencies = [
"hybrid-array", "hybrid-array",
"num-traits", "num-traits",
@@ -171,9 +171,9 @@ dependencies = [
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.2.0-pre.5" version = "0.2.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7aa2ec04f5120b830272a481e8d9d8ba4dda140d2cda59b0f1110d5eb93c38e" checksum = "8c070b79a496dccd931229780ad5bbedd535ceff6c3565605a8e440e18e1aa2b"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"hybrid-array", "hybrid-array",
@@ -182,7 +182,7 @@ dependencies = [
[[package]] [[package]]
name = "cxx" name = "cxx"
version = "1.0.115" version = "1.0.124"
dependencies = [ dependencies = [
"cc", "cc",
"cxxbridge-flags", "cxxbridge-flags",
@@ -191,7 +191,7 @@ dependencies = [
[[package]] [[package]]
name = "cxx-gen" name = "cxx-gen"
version = "0.7.115" version = "0.7.124"
dependencies = [ dependencies = [
"codespan-reporting", "codespan-reporting",
"proc-macro2", "proc-macro2",
@@ -201,11 +201,11 @@ dependencies = [
[[package]] [[package]]
name = "cxxbridge-flags" name = "cxxbridge-flags"
version = "1.0.115" version = "1.0.124"
[[package]] [[package]]
name = "cxxbridge-macro" name = "cxxbridge-macro"
version = "1.0.115" version = "1.0.124"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -214,9 +214,9 @@ dependencies = [
[[package]] [[package]]
name = "der" name = "der"
version = "0.8.0-pre.0" version = "0.8.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b489fd2221710c1dd46637d66b984161fb66134f81437a8489800306bcc2ecea" checksum = "05d9c07d3bd80cf0935ce478d07edf7e7a5b158446757f988f3e62082227b700"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"der_derive", "der_derive",
@@ -227,9 +227,9 @@ dependencies = [
[[package]] [[package]]
name = "der_derive" name = "der_derive"
version = "0.8.0-pre.0" version = "0.8.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd1ee9778ac378876dc78f546d2821fae40a1b69ec8d82f3745392d69ff89ce6" checksum = "2c46c0d3c8dba679a95cc7caf42fe6220338e28c9d7c09e0a458e6f6156c06e7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -238,9 +238,9 @@ dependencies = [
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.11.0-pre.8" version = "0.11.0-pre.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065d93ead7c220b85d5b4be4795d8398eac4ff68b5ee63895de0a3c1fb6edf25" checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"const-oid", "const-oid",
@@ -250,9 +250,9 @@ dependencies = [
[[package]] [[package]]
name = "ecdsa" name = "ecdsa"
version = "0.17.0-pre.5" version = "0.17.0-pre.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7e045ee5c360512162782f3d4cb07d2f4ce8c4ef9bf7c77ec16d1cf60b3d5ca" checksum = "fad051af2b2d2f356d716138c76775929be913deb5b4ea217cd2613535936bef"
dependencies = [ dependencies = [
"der", "der",
"digest", "digest",
@@ -264,9 +264,9 @@ dependencies = [
[[package]] [[package]]
name = "elliptic-curve" name = "elliptic-curve"
version = "0.14.0-pre.5" version = "0.14.0-pre.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a1775af172997a40c14854c3a9fde9e03e5772084b334b6a0bb18bf7f93ac16" checksum = "4ed8e96bb573517f42470775f8ef1b9cd7595de52ba7a8e19c48325a92c8fe4f"
dependencies = [ dependencies = [
"base16ct", "base16ct",
"crypto-bigint", "crypto-bigint",
@@ -301,15 +301,15 @@ dependencies = [
[[package]] [[package]]
name = "flagset" name = "flagset"
version = "0.4.5" version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1" checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@@ -329,27 +329,27 @@ dependencies = [
[[package]] [[package]]
name = "hkdf" name = "hkdf"
version = "0.13.0-pre.3" version = "0.13.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd5d615ab5c462f96c309b3a00b19f373025a4981312f717f9df5bbd0201530c" checksum = "00176ff81091018d42ff82e8324f8e5adb0b7e0468d1358f653972562dbff031"
dependencies = [ dependencies = [
"hmac", "hmac",
] ]
[[package]] [[package]]
name = "hmac" name = "hmac"
version = "0.13.0-pre.3" version = "0.13.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffd790a0795ee332ed3e8959e5b177beb70d7112eb7d345428ec17427897d5ce" checksum = "e4b1fb14e4df79f9406b434b60acef9f45c26c50062cccf1346c6103b8c47d58"
dependencies = [ dependencies = [
"digest", "digest",
] ]
[[package]] [[package]]
name = "hybrid-array" name = "hybrid-array"
version = "0.2.0-rc.8" version = "0.2.0-rc.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53668f5da5a41d9eaf4bf7064be46d1ebe6a4e1ceed817f387587b18f2b51047" checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400"
dependencies = [ dependencies = [
"typenum", "typenum",
"zeroize", "zeroize",
@@ -357,18 +357,18 @@ dependencies = [
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [ dependencies = [
"spin", "spin",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]] [[package]]
name = "libm" name = "libm"
@@ -378,9 +378,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "magisk" name = "magisk"
@@ -443,9 +443,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.2" version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
@@ -502,9 +502,9 @@ dependencies = [
[[package]] [[package]]
name = "num-iter" name = "num-iter"
version = "0.1.44" version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@@ -513,9 +513,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm", "libm",
@@ -523,8 +523,9 @@ dependencies = [
[[package]] [[package]]
name = "p256" name = "p256"
version = "0.14.0-pre.0" version = "0.14.0-pre.1"
source = "git+https://github.com/RustCrypto/elliptic-curves.git?rev=5d1c252c2defb5808f55329f3e2955ca72d7f8b5#5d1c252c2defb5808f55329f3e2955ca72d7f8b5" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c32c18a74d9dda1314d2f945fb3e274848822f63f264a9e4d3f783e29b3bc1f"
dependencies = [ dependencies = [
"ecdsa", "ecdsa",
"elliptic-curve", "elliptic-curve",
@@ -534,8 +535,9 @@ dependencies = [
[[package]] [[package]]
name = "p384" name = "p384"
version = "0.14.0-pre" version = "0.14.0-pre.1"
source = "git+https://github.com/RustCrypto/elliptic-curves.git?rev=5d1c252c2defb5808f55329f3e2955ca72d7f8b5#5d1c252c2defb5808f55329f3e2955ca72d7f8b5" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99acc40dbfad9cc3dc102828f5678c8ca14f0cbf3a1f56f74c2875b5a84427af"
dependencies = [ dependencies = [
"ecdsa", "ecdsa",
"elliptic-curve", "elliptic-curve",
@@ -545,8 +547,9 @@ dependencies = [
[[package]] [[package]]
name = "p521" name = "p521"
version = "0.14.0-pre" version = "0.14.0-pre.1"
source = "git+https://github.com/RustCrypto/elliptic-curves.git?rev=5d1c252c2defb5808f55329f3e2955ca72d7f8b5#5d1c252c2defb5808f55329f3e2955ca72d7f8b5" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec5d919bea930a34a522bb1c95a89f559925deab255db2c2ffa174fc48df664"
dependencies = [ dependencies = [
"base16ct", "base16ct",
"ecdsa", "ecdsa",
@@ -568,18 +571,18 @@ dependencies = [
[[package]] [[package]]
name = "pem-rfc7468" name = "pem-rfc7468"
version = "1.0.0-pre.0" version = "1.0.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a65e1c27d1680f8805b3f8c9949f08d6aa5d6cbd088c9896e64a53821dc27d" checksum = "b6c1cde4770761bf6bd336f947b9ac1fe700b0a4ec5867cf66cf08597fe89e8c"
dependencies = [ dependencies = [
"base64ct", "base64ct",
] ]
[[package]] [[package]]
name = "pkcs1" name = "pkcs1"
version = "0.8.0-pre.0" version = "0.8.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f6af6e88ac39402f67488e22faa9eb15cf065f520cf4a09419393691a6d0133" checksum = "0d2f4c73d459a85331915baebd5082dce5ee8ef16fd9a1ca75559ac91e66a9ee"
dependencies = [ dependencies = [
"der", "der",
"pkcs8", "pkcs8",
@@ -588,9 +591,9 @@ dependencies = [
[[package]] [[package]]
name = "pkcs8" name = "pkcs8"
version = "0.11.0-pre.0" version = "0.11.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "935c09e0aecb0cb8f8907b57438b19a068cb74a25189b06724f061170b2465ff" checksum = "66180445f1dce533620a7743467ef85fe1c5e80cdaf7c7053609d7a2fbcdae20"
dependencies = [ dependencies = [
"der", "der",
"spki", "spki",
@@ -598,28 +601,33 @@ dependencies = [
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]] [[package]]
name = "primefield" name = "primefield"
version = "0.14.0-pre" version = "0.14.0-pre.0"
source = "git+https://github.com/RustCrypto/elliptic-curves.git?rev=5d1c252c2defb5808f55329f3e2955ca72d7f8b5#5d1c252c2defb5808f55329f3e2955ca72d7f8b5" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3f2ce0fa9cccdaf216230d151ce51a15298aef50ad76081a830128ecbc6428a"
[[package]] [[package]]
name = "primeorder" name = "primeorder"
version = "0.14.0-pre.0" version = "0.14.0-pre.1"
source = "git+https://github.com/RustCrypto/elliptic-curves.git?rev=5d1c252c2defb5808f55329f3e2955ca72d7f8b5#5d1c252c2defb5808f55329f3e2955ca72d7f8b5" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bed0c431186675ad845922b903d28c7faa2b634a6d130fb7b50bb289f5a4d52"
dependencies = [ dependencies = [
"elliptic-curve", "elliptic-curve",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.79" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -634,9 +642,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -672,9 +680,9 @@ dependencies = [
[[package]] [[package]]
name = "rfc6979" name = "rfc6979"
version = "0.5.0-pre.3" version = "0.5.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "045972f2f66b9467a2f6834b7fd0f9b23ca214b4a8700b880c36edb726e96da6" checksum = "871ee76a3eee98b0f805e5d1caf26929f4565073c580c053a55f886fc15dea49"
dependencies = [ dependencies = [
"hmac", "hmac",
"subtle", "subtle",
@@ -682,9 +690,9 @@ dependencies = [
[[package]] [[package]]
name = "rsa" name = "rsa"
version = "0.10.0-pre.1" version = "0.10.0-pre.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43e0089f12e510517c97e1adc17d0f8374efbabdd021dfb7645d6619f85633e9" checksum = "57e864e43f5d003321ab452feea6450f9611d7be6726489b4ec051da34774c62"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"digest", "digest",
@@ -703,9 +711,9 @@ dependencies = [
[[package]] [[package]]
name = "sec1" name = "sec1"
version = "0.8.0-pre.1" version = "0.8.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02dc081ed777a3bab68583b52ffb8221677b6e90d483b320963a247e2c07f328" checksum = "32c98827dc6ed0ea1707286a3d14b4ad4e25e2643169cbf111568a46ff5b09f5"
dependencies = [ dependencies = [
"base16ct", "base16ct",
"der", "der",
@@ -717,18 +725,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -737,9 +745,9 @@ dependencies = [
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.11.0-pre.3" version = "0.11.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3885de8cb916f223718c1ccd47a840b91f806333e76002dc5cb3862154b4fed3" checksum = "9540978cef7a8498211c1b1c14e5ce920fe5bd524ea84f4a3d72d4602515ae93"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures", "cpufeatures",
@@ -748,9 +756,9 @@ dependencies = [
[[package]] [[package]]
name = "sha2" name = "sha2"
version = "0.11.0-pre.3" version = "0.11.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f33549bf3064b62478926aa89cbfc7c109aab66ae8f0d5d2ef839e482cc30d6" checksum = "540c0893cce56cdbcfebcec191ec8e0f470dd1889b6e7a0b503e310a94a168f5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures", "cpufeatures",
@@ -759,9 +767,9 @@ dependencies = [
[[package]] [[package]]
name = "signature" name = "signature"
version = "2.3.0-pre.3" version = "2.3.0-pre.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1700c22ba9ce32c7b0a1495068a906c3552e7db386af7cf865162e0dea498523" checksum = "054d71959c7051b9042c26af337f05cc930575ed2604d7d3ced3158383e59734"
dependencies = [ dependencies = [
"digest", "digest",
"rand_core", "rand_core",
@@ -781,15 +789,15 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.5.2" version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]] [[package]]
name = "spki" name = "spki"
version = "0.8.0-pre.0" version = "0.8.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb2b56670f5ef52934c97efad30bf42585de0c33ec3e2a886e38b80d2db67243" checksum = "ee3fb1c675852398475928637b3ebbdd7e1d0cc24d27b3bbc81788b4eb51e310"
dependencies = [ dependencies = [
"base64ct", "base64ct",
"der", "der",
@@ -797,15 +805,15 @@ dependencies = [
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.5.0" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.58" version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -823,18 +831,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.58" version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.58" version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -876,9 +884,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.11" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@@ -892,41 +900,92 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.6" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"winapi", "windows-sys",
] ]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "windows-sys"
version = "0.4.0" version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "x509-cert" name = "x509-cert"
version = "0.3.0-pre" version = "0.3.0-pre"
source = "git+https://github.com/RustCrypto/formats.git?rev=809df65b20d61e88afb7f514b5cfdd3d1958a40f#809df65b20d61e88afb7f514b5cfdd3d1958a40f" source = "git+https://github.com/RustCrypto/formats.git?rev=9c0e851c6db9c2c8a2601840d46375afde2663fb#9c0e851c6db9c2c8a2601840d46375afde2663fb"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"der", "der",
@@ -935,10 +994,31 @@ dependencies = [
] ]
[[package]] [[package]]
name = "zeroize" name = "zerocopy"
version = "1.7.0" version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
dependencies = [ dependencies = [
"zeroize_derive", "zeroize_derive",
] ]

View File

@@ -13,16 +13,16 @@ num-derive = "0.4"
thiserror = "1.0" thiserror = "1.0"
byteorder = "1" byteorder = "1"
size = "0.4" size = "0.4"
sha1 = "0.11.0-pre.3" sha1 = "0.11.0-pre.4"
sha2 = "=0.11.0-pre.3" sha2 = "=0.11.0-pre.4"
digest = "0.11.0-pre.8" digest = "0.11.0-pre.9"
#p256 = "0.14" p256 = "0.14.0-pre.1"
#p384 = "0.14" p384 = "0.14.0-pre.1"
#p521 = "0.14" p521 = "0.14.0-pre.1"
rsa = "0.10.0-pre.1" rsa = "0.10.0-pre.2"
#x509-cert = "0.3" #x509-cert = "0.3"
der = "0.8.0-pre.0" der = "0.8.0-rc.0"
bytemuck = "1.14" bytemuck = "1.16"
fdt = "0.1" fdt = "0.1"
const_format = "0.2" const_format = "0.2"
@@ -40,29 +40,17 @@ default-features = false
git = "https://github.com/tafia/quick-protobuf.git" git = "https://github.com/tafia/quick-protobuf.git"
rev = "2f37d5a65504de7d716b5b28fd82219501a901a9" rev = "2f37d5a65504de7d716b5b28fd82219501a901a9"
[workspace.dependencies.p256]
git = "https://github.com/RustCrypto/elliptic-curves.git"
rev = "5d1c252c2defb5808f55329f3e2955ca72d7f8b5"
[workspace.dependencies.p384]
git = "https://github.com/RustCrypto/elliptic-curves.git"
rev = "5d1c252c2defb5808f55329f3e2955ca72d7f8b5"
[workspace.dependencies.p521]
git = "https://github.com/RustCrypto/elliptic-curves.git"
rev = "5d1c252c2defb5808f55329f3e2955ca72d7f8b5"
[workspace.dependencies.x509-cert] [workspace.dependencies.x509-cert]
git = "https://github.com/RustCrypto/formats.git" git = "https://github.com/RustCrypto/formats.git"
rev = "809df65b20d61e88afb7f514b5cfdd3d1958a40f" rev = "9c0e851c6db9c2c8a2601840d46375afde2663fb"
[profile.dev] [profile.dev]
opt-level = "z" opt-level = "z"
lto = true lto = "thin"
panic = "abort" panic = "abort"
[profile.release] [profile.release]
opt-level = "z" opt-level = "z"
lto = true lto = "fat"
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"

View File

@@ -7,7 +7,7 @@ LOCAL_MODULE := libbase
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
src/include \ src/include \
$(LOCAL_PATH)/include \ $(LOCAL_PATH)/include \
$(LOCAL_PATH)/../external/cxx-rs/include \ src/external/cxx-rs/include \
out/generated out/generated
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_EXPORT_STATIC_LIBRARIES := libcxx LOCAL_EXPORT_STATIC_LIBRARIES := libcxx

View File

@@ -108,7 +108,7 @@ impl StringExt for String {
fn nul_terminate(&mut self) -> &mut [u8] { fn nul_terminate(&mut self) -> &mut [u8] {
self.reserve(1); self.reserve(1);
// SAFETY: the string is reserved to have enough capacity to fit in the null byte // SAFETY: the string is reserved to have enough capacity to fit in the null byte
// SAFETY: the null byte is explicitly added outside of the string's length // SAFETY: the null byte is explicitly added outside the string's length
unsafe { unsafe {
let buf = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len() + 1); let buf = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len() + 1);
*buf.get_unchecked_mut(self.len()) = b'\0'; *buf.get_unchecked_mut(self.len()) = b'\0';
@@ -122,7 +122,7 @@ impl StringExt for PathBuf {
fn nul_terminate(&mut self) -> &mut [u8] { fn nul_terminate(&mut self) -> &mut [u8] {
self.reserve(1); self.reserve(1);
// SAFETY: the PathBuf is reserved to have enough capacity to fit in the null byte // SAFETY: the PathBuf is reserved to have enough capacity to fit in the null byte
// SAFETY: the null byte is explicitly added outside of the PathBuf's length // SAFETY: the null byte is explicitly added outside the PathBuf's length
unsafe { unsafe {
let bytes: &mut [u8] = mem::transmute(self.as_mut_os_str().as_bytes()); let bytes: &mut [u8] = mem::transmute(self.as_mut_os_str().as_bytes());
let buf = slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len() + 1); let buf = slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len() + 1);
@@ -314,7 +314,7 @@ impl Utf8CStr {
CStr::from_bytes_with_nul(buf)?; CStr::from_bytes_with_nul(buf)?;
str::from_utf8(buf)?; str::from_utf8(buf)?;
// Both condition checked // Both condition checked
unsafe { Ok(mem::transmute(buf)) } unsafe { Ok(mem::transmute::<&mut [u8], &mut Utf8CStr>(buf)) }
} }
pub fn from_string(s: &mut String) -> &mut Utf8CStr { pub fn from_string(s: &mut String) -> &mut Utf8CStr {

View File

@@ -4,9 +4,9 @@ use std::io;
use std::os::fd::{BorrowedFd, OwnedFd, RawFd}; use std::os::fd::{BorrowedFd, OwnedFd, RawFd};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use cxx::private::c_char; use libc::{c_char, mode_t};
use libc::mode_t;
use crate::files::map_file_at;
pub(crate) use crate::xwrap::*; pub(crate) use crate::xwrap::*;
use crate::{ use crate::{
clone_attr, cstr, fclone_attr, fd_path, map_fd, map_file, slice_from_ptr, CxxResultExt, clone_attr, cstr, fclone_attr, fd_path, map_fd, map_file, slice_from_ptr, CxxResultExt,
@@ -61,6 +61,14 @@ pub(crate) fn map_file_for_cxx(path: &Utf8CStr, rw: bool) -> &'static mut [u8] {
map_file(path, rw).log_cxx().unwrap_or(&mut []) map_file(path, rw).log_cxx().unwrap_or(&mut [])
} }
pub(crate) fn map_file_at_for_cxx(fd: RawFd, path: &Utf8CStr, rw: bool) -> &'static mut [u8] {
unsafe {
map_file_at(BorrowedFd::borrow_raw(fd), path, rw)
.log_cxx()
.unwrap_or(&mut [])
}
}
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] { pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
unsafe { unsafe {
map_fd(BorrowedFd::borrow_raw(fd), sz, rw) map_fd(BorrowedFd::borrow_raw(fd), sz, rw)

View File

@@ -117,6 +117,14 @@ mmap_data::mmap_data(const char *name, bool rw) {
} }
} }
mmap_data::mmap_data(int dirfd, const char *name, bool rw) {
auto slice = rust::map_file_at(dirfd, name, rw);
if (!slice.empty()) {
_buf = slice.data();
_sz = slice.size();
}
}
mmap_data::mmap_data(int fd, size_t sz, bool rw) { mmap_data::mmap_data(int fd, size_t sz, bool rw) {
auto slice = rust::map_fd(fd, sz, rw); auto slice = rust::map_fd(fd, sz, rw);
if (!slice.empty()) { if (!slice.empty()) {

View File

@@ -26,6 +26,7 @@ struct mmap_data : public byte_data {
ALLOW_MOVE_ONLY(mmap_data) ALLOW_MOVE_ONLY(mmap_data)
explicit mmap_data(const char *name, bool rw = false); explicit mmap_data(const char *name, bool rw = false);
mmap_data(int dirfd, const char *name, bool rw = false);
mmap_data(int fd, size_t sz, bool rw = false); mmap_data(int fd, size_t sz, bool rw = false);
~mmap_data(); ~mmap_data();
}; };
@@ -36,11 +37,11 @@ int mkdirs(const char *path, mode_t mode);
ssize_t canonical_path(const char * __restrict__ path, char * __restrict__ buf, size_t bufsiz); ssize_t canonical_path(const char * __restrict__ path, char * __restrict__ buf, size_t bufsiz);
bool rm_rf(const char *path); bool rm_rf(const char *path);
bool frm_rf(int dirfd); bool frm_rf(int dirfd);
void cp_afc(const char *src, const char *dest); bool cp_afc(const char *src, const char *dest);
void mv_path(const char *src, const char *dest); bool mv_path(const char *src, const char *dest);
void link_path(const char *src, const char *dest); bool link_path(const char *src, const char *dest);
void clone_attr(const char *src, const char *dest); bool clone_attr(const char *src, const char *dest);
void fclone_attr(int src, int dest); bool fclone_attr(int src, int dest);
} // extern "C" } // extern "C"

View File

@@ -856,6 +856,14 @@ impl MappedFile {
Ok(MappedFile(map_file(path, true)?)) Ok(MappedFile(map_file(path, true)?))
} }
pub fn openat<T: AsFd>(dir: &T, path: &Utf8CStr) -> io::Result<MappedFile> {
Ok(MappedFile(map_file_at(dir.as_fd(), path, false)?))
}
pub fn openat_rw<T: AsFd>(dir: &T, path: &Utf8CStr) -> io::Result<MappedFile> {
Ok(MappedFile(map_file_at(dir.as_fd(), path, true)?))
}
pub fn create(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<MappedFile> { pub fn create(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<MappedFile> {
Ok(MappedFile(map_fd(fd, sz, rw)?)) Ok(MappedFile(map_fd(fd, sz, rw)?))
} }
@@ -888,6 +896,14 @@ extern "C" {
// We mark the returned slice static because it is valid until explicitly unmapped // We mark the returned slice static because it is valid until explicitly unmapped
pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8]> { pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8]> {
unsafe { map_file_at(BorrowedFd::borrow_raw(libc::AT_FDCWD), path, rw) }
}
pub(crate) fn map_file_at(
dirfd: BorrowedFd,
path: &Utf8CStr,
rw: bool,
) -> io::Result<&'static mut [u8]> {
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
const BLKGETSIZE64: u32 = 0x80081272; const BLKGETSIZE64: u32 = 0x80081272;
@@ -895,18 +911,22 @@ pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8
const BLKGETSIZE64: u32 = 0x80041272; const BLKGETSIZE64: u32 = 0x80041272;
let flag = if rw { O_RDWR } else { O_RDONLY }; let flag = if rw { O_RDWR } else { O_RDONLY };
let file = FsPath::from(path).open(flag | O_CLOEXEC)?; let fd = unsafe {
OwnedFd::from_raw_fd(
libc::openat(dirfd.as_raw_fd(), path.as_ptr(), flag | O_CLOEXEC).check_os_err()?,
)
};
let attr = fd_get_attr(file.as_raw_fd())?; let attr = fd_get_attr(fd.as_raw_fd())?;
let sz = if attr.is_block_device() { let sz = if attr.is_block_device() {
let mut sz = 0_u64; let mut sz = 0_u64;
unsafe { ioctl(file.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?; unsafe { ioctl(fd.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?;
sz sz
} else { } else {
attr.st.st_size as u64 attr.st.st_size as u64
}; };
map_fd(file.as_fd(), sz as usize, rw) map_fd(fd.as_fd(), sz as usize, rw)
} }
pub(crate) fn map_fd(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<&'static mut [u8]> { pub(crate) fn map_fd(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<&'static mut [u8]> {

View File

@@ -1,13 +0,0 @@
#if defined(__arm__)
#include <armeabi-v7a_binaries.h>
#elif defined(__aarch64__)
#include <arm64-v8a_binaries.h>
#elif defined(__i386__)
#include <x86_binaries.h>
#elif defined(__x86_64__)
#include <x86_64_binaries.h>
#elif defined(__riscv)
#include <riscv64_binaries.h>
#else
#error Unsupported ABI
#endif

View File

@@ -61,6 +61,8 @@ pub mod ffi {
fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize; fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize;
#[cxx_name = "map_file"] #[cxx_name = "map_file"]
fn map_file_for_cxx(path: Utf8CStrRef, rw: bool) -> &'static mut [u8]; fn map_file_for_cxx(path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
#[cxx_name = "map_file_at"]
fn map_file_at_for_cxx(fd: i32, path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
#[cxx_name = "map_fd"] #[cxx_name = "map_fd"]
fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8]; fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8];
} }

View File

@@ -1,6 +1,7 @@
#include <bit> #include <bit>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <span>
#include <base.hpp> #include <base.hpp>
@@ -61,6 +62,8 @@ void dyn_img_hdr::print() const {
fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size()); fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size());
if (ver == 2 || is_vendor()) if (ver == 2 || is_vendor())
fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size()); fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size());
if (ver == 4 && is_vendor())
fprintf(stderr, "%-*s [%u]\n", PADDING, "BOOTCONFIG_SZ", bootconfig_size());
if (uint32_t os_ver = os_version()) { if (uint32_t os_ver = os_version()) {
int a,b,c,y,m = 0; int a,b,c,y,m = 0;
@@ -273,8 +276,7 @@ static format_t check_fmt_lg(const uint8_t *buf, unsigned sz) {
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s) #define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
const pair<const uint8_t *, dyn_img_hdr *> pair<const uint8_t *, dyn_img_hdr *> boot_img::create_hdr(const uint8_t *addr, format_t type) {
boot_img::create_hdr(const uint8_t *addr, format_t type) {
if (type == AOSP_VENDOR) { if (type == AOSP_VENDOR) {
fprintf(stderr, "VENDOR_BOOT_HDR\n"); fprintf(stderr, "VENDOR_BOOT_HDR\n");
auto h = reinterpret_cast<const boot_img_hdr_vnd_v3*>(addr); auto h = reinterpret_cast<const boot_img_hdr_vnd_v3*>(addr);
@@ -346,12 +348,25 @@ const pair<const uint8_t *, dyn_img_hdr *>
addr += ACCLAIM_PRE_HEADER_SZ; addr += ACCLAIM_PRE_HEADER_SZ;
} }
// addr could be adjusted
return make_pair(addr, make_hdr(addr)); return make_pair(addr, make_hdr(addr));
} }
static const char *vendor_ramdisk_type(int type) {
switch (type) {
case VENDOR_RAMDISK_TYPE_PLATFORM:
return "platform";
case VENDOR_RAMDISK_TYPE_RECOVERY:
return "recovery";
case VENDOR_RAMDISK_TYPE_DLKM:
return "dlkm";
case VENDOR_RAMDISK_TYPE_NONE:
default:
return "none";
}
}
#define assert_off() \ #define assert_off() \
if ((base_addr + off) > (map.buf() + map.sz())) { \ if ((base_addr + off) > (map.buf() + map_end)) { \
fprintf(stderr, "Corrupted boot image!\n"); \ fprintf(stderr, "Corrupted boot image!\n"); \
return false; \ return false; \
} }
@@ -362,14 +377,6 @@ off += hdr->name##_size(); \
off = align_to(off, hdr->page_size()); \ off = align_to(off, hdr->page_size()); \
assert_off(); assert_off();
#define get_ignore(name) \
if (hdr->name##_size()) { \
auto blk_sz = align_to(hdr->name##_size(), hdr->page_size()); \
off += blk_sz; \
} \
assert_off();
bool boot_img::parse_image(const uint8_t *p, format_t type) { bool boot_img::parse_image(const uint8_t *p, format_t type) {
auto [base_addr, hdr] = create_hdr(p, type); auto [base_addr, hdr] = create_hdr(p, type);
if (hdr == nullptr) { if (hdr == nullptr) {
@@ -388,6 +395,7 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
hdr->print(); hdr->print();
size_t map_end = align_to(map.sz(), getpagesize());
size_t off = hdr->hdr_space(); size_t off = hdr->hdr_space();
get_block(kernel); get_block(kernel);
get_block(ramdisk); get_block(ramdisk);
@@ -395,16 +403,13 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
get_block(extra); get_block(extra);
get_block(recovery_dtbo); get_block(recovery_dtbo);
get_block(dtb); get_block(dtb);
get_block(signature);
auto ignore_addr = base_addr + off; get_block(vendor_ramdisk_table);
get_ignore(signature) get_block(bootconfig);
get_ignore(vendor_ramdisk_table)
get_ignore(bootconfig)
payload = byte_view(base_addr, off); payload = byte_view(base_addr, off);
auto tail_addr = base_addr + off; auto tail_addr = base_addr + off;
ignore = byte_view(ignore_addr, tail_addr - ignore_addr); tail = byte_view(tail_addr, map.buf() + map_end - tail_addr);
tail = byte_view(tail_addr, map.buf() + map.sz() - tail_addr);
if (auto size = hdr->kernel_size()) { if (auto size = hdr->kernel_size()) {
if (int dtb_off = find_dtb_offset(kernel, size); dtb_off > 0) { if (int dtb_off = find_dtb_offset(kernel, size); dtb_off > 0) {
@@ -458,24 +463,40 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]); fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]);
} }
if (auto size = hdr->ramdisk_size()) { if (auto size = hdr->ramdisk_size()) {
if (hdr->is_vendor() && hdr->header_version() >= 4) { if (hdr->vendor_ramdisk_table_size()) {
// v4 vendor boot contains multiple ramdisks // v4 vendor boot contains multiple ramdisks
// Do not try to mess with it for now using table_entry = const vendor_ramdisk_table_entry_v4;
r_fmt = UNKNOWN; if (hdr->vendor_ramdisk_table_entry_size() != sizeof(table_entry)) {
fprintf(stderr,
"! Invalid vendor image: vendor_ramdisk_table_entry_size != %zu\n",
sizeof(table_entry));
exit(1);
}
span<table_entry> table(
reinterpret_cast<table_entry *>(vendor_ramdisk_table),
hdr->vendor_ramdisk_table_entry_num());
for (auto &it : table) {
format_t fmt = check_fmt_lg(ramdisk + it.ramdisk_offset, it.ramdisk_size);
fprintf(stderr,
"%-*s name=[%s] type=[%s] size=[%u] fmt=[%s]\n", PADDING, "VND_RAMDISK",
it.ramdisk_name, vendor_ramdisk_type(it.ramdisk_type),
it.ramdisk_size, fmt2name[fmt]);
}
} else { } else {
r_fmt = check_fmt_lg(ramdisk, size); r_fmt = check_fmt_lg(ramdisk, size);
if (r_fmt == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR\n");
flags[MTK_RAMDISK] = true;
r_hdr = reinterpret_cast<const mtk_hdr *>(ramdisk);
fprintf(stderr, "%-*s [%u]\n", PADDING, "SIZE", r_hdr->size);
fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", r_hdr->name);
ramdisk += sizeof(mtk_hdr);
hdr->ramdisk_size() -= sizeof(mtk_hdr);
r_fmt = check_fmt_lg(ramdisk, hdr->ramdisk_size());
}
fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]);
} }
if (r_fmt == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR\n");
flags[MTK_RAMDISK] = true;
r_hdr = reinterpret_cast<const mtk_hdr *>(ramdisk);
fprintf(stderr, "%-*s [%u]\n", PADDING, "SIZE", r_hdr->size);
fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", r_hdr->name);
ramdisk += sizeof(mtk_hdr);
hdr->ramdisk_size() -= sizeof(mtk_hdr);
r_fmt = check_fmt_lg(ramdisk, hdr->ramdisk_size());
}
fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]);
} }
if (auto size = hdr->extra_size()) { if (auto size = hdr->extra_size()) {
e_fmt = check_fmt_lg(extra, size); e_fmt = check_fmt_lg(extra, size);
@@ -561,7 +582,30 @@ int unpack(const char *image, bool skip_decomp, bool hdr) {
dump(boot.kernel_dtb.buf(), boot.kernel_dtb.sz(), KER_DTB_FILE); dump(boot.kernel_dtb.buf(), boot.kernel_dtb.sz(), KER_DTB_FILE);
// Dump ramdisk // Dump ramdisk
if (!skip_decomp && COMPRESSED(boot.r_fmt)) { if (boot.hdr->vendor_ramdisk_table_size()) {
using table_entry = const vendor_ramdisk_table_entry_v4;
span<table_entry> table(
reinterpret_cast<table_entry *>(boot.vendor_ramdisk_table),
boot.hdr->vendor_ramdisk_table_entry_num());
xmkdir(VND_RAMDISK_DIR, 0755);
owned_fd dirfd = xopen(VND_RAMDISK_DIR, O_RDONLY | O_CLOEXEC);
for (auto &it : table) {
char file_name[40];
if (it.ramdisk_name[0] == '\0') {
strscpy(file_name, RAMDISK_FILE, sizeof(file_name));
} else {
ssprintf(file_name, sizeof(file_name), "%s.cpio", it.ramdisk_name);
}
owned_fd fd = xopenat(dirfd, file_name, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
format_t fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
if (!skip_decomp && COMPRESSED(fmt)) {
decompress(fmt, fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
} else {
xwrite(fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
}
}
} else if (!skip_decomp && COMPRESSED(boot.r_fmt)) {
if (boot.hdr->ramdisk_size() != 0) { if (boot.hdr->ramdisk_size() != 0) {
int fd = creat(RAMDISK_FILE, 0644); int fd = creat(RAMDISK_FILE, 0644);
decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size()); decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size());
@@ -591,6 +635,9 @@ int unpack(const char *image, bool skip_decomp, bool hdr) {
// Dump dtb // Dump dtb
dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE); dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE);
// Dump bootconfig
dump(boot.bootconfig, boot.hdr->bootconfig_size(), BOOTCONFIG_FILE);
return boot.flags[CHROMEOS_FLAG] ? 2 : 0; return boot.flags[CHROMEOS_FLAG] ? 2 : 0;
} }
@@ -620,6 +667,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
hdr->ramdisk_size() = 0; hdr->ramdisk_size() = 0;
hdr->second_size() = 0; hdr->second_size() = 0;
hdr->dtb_size() = 0; hdr->dtb_size() = 0;
hdr->bootconfig_size() = 0;
if (access(HEADER_FILE, R_OK) == 0) if (access(HEADER_FILE, R_OK) == 0)
hdr->load_hdr_file(); hdr->load_hdr_file();
@@ -703,7 +751,40 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
// Copy MTK headers // Copy MTK headers
xwrite(fd, boot.r_hdr, sizeof(mtk_hdr)); xwrite(fd, boot.r_hdr, sizeof(mtk_hdr));
} }
if (access(RAMDISK_FILE, R_OK) == 0) {
using table_entry = vendor_ramdisk_table_entry_v4;
vector<table_entry> ramdisk_table;
if (boot.hdr->vendor_ramdisk_table_size()) {
// Create a copy so we can modify it
auto entry_start = reinterpret_cast<const table_entry *>(boot.vendor_ramdisk_table);
ramdisk_table.insert(
ramdisk_table.begin(),
entry_start, entry_start + boot.hdr->vendor_ramdisk_table_entry_num());
owned_fd dirfd = xopen(VND_RAMDISK_DIR, O_RDONLY | O_CLOEXEC);
uint32_t ramdisk_offset = 0;
for (auto &it : ramdisk_table) {
char file_name[64];
if (it.ramdisk_name[0] == '\0') {
strscpy(file_name, RAMDISK_FILE, sizeof(file_name));
} else {
ssprintf(file_name, sizeof(file_name), "%s.cpio", it.ramdisk_name);
}
mmap_data m(dirfd, file_name);
format_t fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
it.ramdisk_offset = ramdisk_offset;
if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(fmt)) {
it.ramdisk_size = compress(fmt, fd, m.buf(), m.sz());
} else {
it.ramdisk_size = xwrite(fd, m.buf(), m.sz());
}
ramdisk_offset += it.ramdisk_size;
}
hdr->ramdisk_size() = ramdisk_offset;
file_align();
} else if (access(RAMDISK_FILE, R_OK) == 0) {
mmap_data m(RAMDISK_FILE); mmap_data m(RAMDISK_FILE);
auto r_fmt = boot.r_fmt; auto r_fmt = boot.r_fmt;
if (!skip_comp && !hdr->is_vendor() && hdr->header_version() == 4 && r_fmt != LZ4_LEGACY) { if (!skip_comp && !hdr->is_vendor() && hdr->header_version() == 4 && r_fmt != LZ4_LEGACY) {
@@ -754,10 +835,22 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
file_align(); file_align();
} }
// Directly copy ignored blobs // Copy boot signature
if (boot.ignore.sz()) { if (boot.hdr->signature_size()) {
// ignore.sz() should already be aligned xwrite(fd, boot.signature, boot.hdr->signature_size());
xwrite(fd, boot.ignore.buf(), boot.ignore.sz()); file_align();
}
// vendor ramdisk table
if (!ramdisk_table.empty()) {
xwrite(fd, ramdisk_table.data(), sizeof(table_entry) * ramdisk_table.size());
file_align();
}
// bootconfig
if (access(BOOTCONFIG_FILE, R_OK) == 0) {
hdr->bootconfig_size() = restore(fd, BOOTCONFIG_FILE);
file_align();
} }
// Proprietary stuffs // Proprietary stuffs

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <stdint.h> #include <cstdint>
#include <utility> #include <utility>
#include <bitset> #include <bitset>
#include <cxx.h> #include <cxx.h>
@@ -111,15 +111,21 @@ struct AvbVBMetaImageHeader {
#define VENDOR_RAMDISK_NAME_SIZE 32 #define VENDOR_RAMDISK_NAME_SIZE 32
#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16 #define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
/* When the boot image header has a version of 0 - 2, the structure of the boot #define VENDOR_RAMDISK_TYPE_NONE 0
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
#define VENDOR_RAMDISK_TYPE_DLKM 3
/*
* When the boot image header has a version of 0 - 2, the structure of the boot
* image is as follows: * image is as follows:
* *
* +-----------------+ * +-----------------+
* | boot header | 1 page * | boot header | 1 page
* +-----------------+ * +-----------------+
* | kernel | n pages * | kernel | m pages
* +-----------------+ * +-----------------+
* | ramdisk | m pages * | ramdisk | n pages
* +-----------------+ * +-----------------+
* | second stage | o pages * | second stage | o pages
* +-----------------+ * +-----------------+
@@ -130,8 +136,8 @@ struct AvbVBMetaImageHeader {
* | dtb | q pages * | dtb | q pages
* +-----------------+ * +-----------------+
* *
* n = (kernel_size + page_size - 1) / page_size * m = (kernel_size + page_size - 1) / page_size
* m = (ramdisk_size + page_size - 1) / page_size * n = (ramdisk_size + page_size - 1) / page_size
* o = (second_size + page_size - 1) / page_size * o = (second_size + page_size - 1) / page_size
* p = (recovery_dtbo_size + page_size - 1) / page_size * p = (recovery_dtbo_size + page_size - 1) / page_size
* q = (dtb_size + page_size - 1) / page_size * q = (dtb_size + page_size - 1) / page_size
@@ -211,7 +217,8 @@ struct boot_img_hdr_pxa : public boot_img_hdr_v0_common {
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed)); } __attribute__((packed));
/* When the boot image header has a version of 3 - 4, the structure of the boot /*
* When the boot image header has a version of 3 - 4, the structure of the boot
* image is as follows: * image is as follows:
* *
* +---------------------+ * +---------------------+
@@ -329,7 +336,7 @@ struct vendor_ramdisk_table_entry_v4 {
uint32_t ramdisk_size; /* size in bytes for the ramdisk image */ uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */ uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
uint32_t ramdisk_type; /* type of the ramdisk */ uint32_t ramdisk_type; /* type of the ramdisk */
uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */ char ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */
// Hardware identifiers describing the board, soc or platform which this // Hardware identifiers describing the board, soc or platform which this
// ramdisk is intended to be loaded on. // ramdisk is intended to be loaded on.
@@ -376,8 +383,12 @@ struct dyn_img_hdr {
// v4 specific // v4 specific
decl_val(signature_size, 32) decl_val(signature_size, 32)
// v4 vendor specific
decl_val(vendor_ramdisk_table_size, 32) decl_val(vendor_ramdisk_table_size, 32)
decl_val(bootconfig_size, 32) decl_val(vendor_ramdisk_table_entry_num, 32)
decl_val(vendor_ramdisk_table_entry_size, 32)
decl_var(bootconfig_size, 32)
virtual ~dyn_img_hdr() { virtual ~dyn_img_hdr() {
free(raw); free(raw);
@@ -554,7 +565,9 @@ struct dyn_img_vnd_v4 : public dyn_img_vnd_v3 {
impl_cls(vnd_v4) impl_cls(vnd_v4)
impl_val(vendor_ramdisk_table_size) impl_val(vendor_ramdisk_table_size)
impl_val(bootconfig_size) impl_val(vendor_ramdisk_table_entry_num)
impl_val(vendor_ramdisk_table_entry_size)
impl_var(bootconfig_size)
}; };
#undef __impl_cls #undef __impl_cls
@@ -591,7 +604,7 @@ struct boot_img {
const mmap_data map; const mmap_data map;
// Android image header // Android image header
const dyn_img_hdr *hdr; const dyn_img_hdr *hdr = nullptr;
// Flags to indicate the state of current boot image // Flags to indicate the state of current boot image
std::bitset<BOOT_FLAGS_MAX> flags; std::bitset<BOOT_FLAGS_MAX> flags;
@@ -607,9 +620,9 @@ struct boot_img {
// Layout of the memory mapped region // Layout of the memory mapped region
// +---------+ // +---------+
// | head | Vendor specific. Should be empty for standard AOSP boot images. // | head | Vendor specific. Should not exist for standard AOSP boot images.
// +---------+ // +---------+
// | payload | The actual boot image, including the AOSP boot image header. // | payload | The actual entire AOSP boot image, including the boot image header.
// +---------+ // +---------+
// | tail | Data after payload. Usually contains signature/AVB information. // | tail | Data after payload. Usually contains signature/AVB information.
// +---------+ // +---------+
@@ -618,8 +631,8 @@ struct boot_img {
byte_view tail; byte_view tail;
// MTK headers // MTK headers
const mtk_hdr *k_hdr; const mtk_hdr *k_hdr = nullptr;
const mtk_hdr *r_hdr; const mtk_hdr *r_hdr = nullptr;
// The pointers/values after parse_image // The pointers/values after parse_image
// +---------------+ // +---------------+
@@ -629,23 +642,26 @@ struct boot_img {
// +---------------+ // +---------------+
// | z_info.tail | z_info.tail.sz() // | z_info.tail | z_info.tail.sz()
// +---------------+ // +---------------+
const zimage_hdr *z_hdr; const zimage_hdr *z_hdr = nullptr;
struct { struct {
uint32_t hdr_sz; uint32_t hdr_sz;
byte_view tail; byte_view tail;
} z_info; } z_info;
// AVB structs // AVB structs
const AvbFooter *avb_footer; const AvbFooter *avb_footer = nullptr;
const AvbVBMetaImageHeader *vbmeta; const AvbVBMetaImageHeader *vbmeta = nullptr;
// Pointers to blocks defined in header // Pointers to blocks defined in header
const uint8_t *kernel; const uint8_t *kernel = nullptr;
const uint8_t *ramdisk; const uint8_t *ramdisk = nullptr;
const uint8_t *second; const uint8_t *second = nullptr;
const uint8_t *extra; const uint8_t *extra = nullptr;
const uint8_t *recovery_dtbo; const uint8_t *recovery_dtbo = nullptr;
const uint8_t *dtb; const uint8_t *dtb = nullptr;
const uint8_t *signature = nullptr;
const uint8_t *vendor_ramdisk_table = nullptr;
const uint8_t *bootconfig = nullptr;
// dtb embedded in kernel // dtb embedded in kernel
byte_view kernel_dtb; byte_view kernel_dtb;
@@ -657,7 +673,7 @@ struct boot_img {
~boot_img(); ~boot_img();
bool parse_image(const uint8_t *addr, format_t type); bool parse_image(const uint8_t *addr, format_t type);
const std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type); std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type);
// Rust FFI // Rust FFI
rust::Slice<const uint8_t> get_payload() const { return payload; } rust::Slice<const uint8_t> get_payload() const { return payload; }

View File

@@ -175,9 +175,8 @@ Supported commands:
extract [ENTRY OUT] extract [ENTRY OUT]
Extract ENTRY to OUT, or extract all entries to current directory Extract ENTRY to OUT, or extract all entries to current directory
test test
Test the cpio's status Test the cpio's status. Return values:
Return value is 0 or bitwise or-ed of following values: 0:stock 1:Magisk 2:unsupported
0x1:Magisk 0x2:unsupported
patch patch
Apply ramdisk patches Apply ramdisk patches
Configure with env variables: KEEPVERITY KEEPFORCEENCRYPT Configure with env variables: KEEPVERITY KEEPFORCEENCRYPT
@@ -544,7 +543,6 @@ impl Cpio {
} }
fn test(&self) -> i32 { fn test(&self) -> i32 {
let mut ret = 0;
for file in [ for file in [
"sbin/launch_daemonsu.sh", "sbin/launch_daemonsu.sh",
"sbin/su", "sbin/su",
@@ -561,11 +559,10 @@ impl Cpio {
"overlay/init.magisk.rc", "overlay/init.magisk.rc",
] { ] {
if self.exists(file) { if self.exists(file) {
ret |= MAGISK_PATCHED; return MAGISK_PATCHED;
break;
} }
} }
ret 0
} }
fn restore(&mut self) -> LoggedResult<()> { fn restore(&mut self) -> LoggedResult<()> {

View File

@@ -7,11 +7,13 @@
#define HEADER_FILE "header" #define HEADER_FILE "header"
#define KERNEL_FILE "kernel" #define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio" #define RAMDISK_FILE "ramdisk.cpio"
#define VND_RAMDISK_DIR "vendor_ramdisk"
#define SECOND_FILE "second" #define SECOND_FILE "second"
#define EXTRA_FILE "extra" #define EXTRA_FILE "extra"
#define KER_DTB_FILE "kernel_dtb" #define KER_DTB_FILE "kernel_dtb"
#define RECV_DTBO_FILE "recovery_dtbo" #define RECV_DTBO_FILE "recovery_dtbo"
#define DTB_FILE "dtb" #define DTB_FILE "dtb"
#define BOOTCONFIG_FILE "bootconfig"
#define NEW_BOOT "new-boot.img" #define NEW_BOOT "new-boot.img"
int unpack(const char *image, bool skip_decomp = false, bool hdr = false); int unpack(const char *image, bool skip_decomp = false, bool hdr = false);

View File

@@ -7,8 +7,12 @@
using namespace std; using namespace std;
#ifdef USE_CRT0 #ifdef USE_CRT0
__asm__(".global vfprintf \n vfprintf = musl_vfprintf"); __BEGIN_DECLS
__asm__(".global vsscanf \n vsscanf = tfp_vsscanf"); int musl_vfprintf(FILE *stream, const char *format, va_list arg);
int vfprintf(FILE *stream, const char *format, va_list arg) {
return musl_vfprintf(stream, format, arg);
}
__END_DECLS
#endif #endif
static void print_formats() { static void print_formats() {
@@ -40,7 +44,9 @@ Supported actions:
repack [-n] <origbootimg> [outbootimg] repack [-n] <origbootimg> [outbootimg]
Repack boot image components using files from the current directory Repack boot image components using files from the current directory
to [outbootimg], or 'new-boot.img' if not specified. to [outbootimg], or 'new-boot.img' if not specified. Current directory
should only contain required files for [outbootimg], or incorrect
[outbootimg] may be produced.
<origbootimg> is the original boot image used to unpack the components. <origbootimg> is the original boot image used to unpack the components.
By default, each component will be automatically compressed using its By default, each component will be automatically compressed using its
corresponding format detected in <origbootimg>. If a component file corresponding format detected in <origbootimg>. If a component file
@@ -142,6 +148,8 @@ int main(int argc, char *argv[]) {
unlink(EXTRA_FILE); unlink(EXTRA_FILE);
unlink(RECV_DTBO_FILE); unlink(RECV_DTBO_FILE);
unlink(DTB_FILE); unlink(DTB_FILE);
unlink(BOOTCONFIG_FILE);
rm_rf(VND_RAMDISK_DIR);
} else if (argc > 2 && action == "sha1") { } else if (argc > 2 && action == "sha1") {
uint8_t sha1[20]; uint8_t sha1[20];
{ {

View File

@@ -25,6 +25,18 @@ static bool magisk_env() {
LOGI("* Initializing Magisk environment\n"); LOGI("* Initializing Magisk environment\n");
ssprintf(buf, sizeof(buf), "%s/0/%s/install", APP_DATA_DIR, JAVA_PACKAGE_NAME);
// Alternative binaries paths
const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf };
for (auto alt : alt_bin) {
if (access(alt, F_OK) == 0) {
rm_rf(DATABIN);
cp_afc(alt, DATABIN);
rm_rf(alt);
}
}
rm_rf("/cache/data_adb");
// Directories in /data/adb // Directories in /data/adb
chmod(SECURE_DIR, 0700); chmod(SECURE_DIR, 0700);
xmkdir(DATABIN, 0755); xmkdir(DATABIN, 0755);

View File

@@ -372,6 +372,11 @@ static void daemon_entry() {
} }
} }
LOGI("* Device API level: %d\n", SDK_INT); LOGI("* Device API level: %d\n", SDK_INT);
// Samsung workaround #7887
if (access("/system_ext/app/mediatek-res/mediatek-res.apk", F_OK) == 0) {
set_prop("ro.vendor.mtk_model", "0");
}
restore_tmpcon(); restore_tmpcon();
@@ -392,21 +397,6 @@ static void daemon_entry() {
ssprintf(path, sizeof(path), "%s/" ROOTOVL, tmp); ssprintf(path, sizeof(path), "%s/" ROOTOVL, tmp);
rm_rf(path); rm_rf(path);
// Use isolated devpts if kernel support
if (access("/dev/pts/ptmx", F_OK) == 0) {
ssprintf(path, sizeof(path), "%s/" SHELLPTS, tmp);
if (access(path, F_OK)) {
xmkdirs(path, 0755);
xmount("devpts", path, "devpts", MS_NOSUID | MS_NOEXEC, "newinstance");
char ptmx[64];
ssprintf(ptmx, sizeof(ptmx), "%s/ptmx", path);
if (access(ptmx, F_OK)) {
xumount(path);
rmdir(path);
}
}
}
fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
sockaddr_un addr = {.sun_family = AF_LOCAL}; sockaddr_un addr = {.sun_family = AF_LOCAL};
ssprintf(addr.sun_path, sizeof(addr.sun_path), "%s/" MAIN_SOCKET, tmp); ssprintf(addr.sun_path, sizeof(addr.sun_path), "%s/" MAIN_SOCKET, tmp);

View File

@@ -24,20 +24,12 @@ static sqlite3 *mDB = nullptr;
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
static int (*sqlite3_open_v2)( using sqlite3_callback = int (*)(void*, int, char**, char**);
const char *filename, static int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
sqlite3 **ppDb,
int flags,
const char *zVfs);
static const char *(*sqlite3_errmsg)(sqlite3 *db); static const char *(*sqlite3_errmsg)(sqlite3 *db);
static int (*sqlite3_close)(sqlite3 *db); static int (*sqlite3_close)(sqlite3 *db);
static void (*sqlite3_free)(void *v); static void (*sqlite3_free)(void *v);
static int (*sqlite3_exec)( static int (*sqlite3_exec)(sqlite3 *db, const char *sql, sqlite3_callback fn, void *v, char **errmsg);
sqlite3 *db,
const char *sql,
int (*callback)(void*, int, char**, char**),
void *v,
char **errmsg);
// Internal Android linker APIs // Internal Android linker APIs
@@ -135,51 +127,69 @@ static int ver_cb(void *ver, int, char **data, char **) {
return 0; return 0;
} }
#define err_ret(e) if (e) return e; bool db_result::check_err() {
if (!err.empty()) {
LOGE("sqlite3_exec: %s\n", err.data());
return true;
}
return false;
}
static char *open_and_init_db(sqlite3 *&db) { static db_result sql_exec(sqlite3 *db, const char *sql, sqlite3_callback fn, void *v) {
char *err = nullptr;
sqlite3_exec(db, sql, fn, v, &err);
if (err) {
db_result r = err;
sqlite3_free(err);
return r;
}
return {};
}
#define sql_exe_ret(...) if (auto r = sql_exec(__VA_ARGS__); !r) return r
#define fn_run_ret(fn) if (auto r = fn(); !r) return r
static db_result open_and_init_db(sqlite3 *&db) {
if (!dload_sqlite()) if (!dload_sqlite())
return strdup("Cannot load libsqlite.so"); return "Cannot load libsqlite.so";
int ret = sqlite3_open_v2(MAGISKDB, &db, int ret = sqlite3_open_v2(MAGISKDB, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr); SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr);
if (ret) if (ret)
return strdup(sqlite3_errmsg(db)); return sqlite3_errmsg(db);
int ver = 0; int ver = 0;
bool upgrade = false; bool upgrade = false;
char *err = nullptr; sql_exe_ret(db, "PRAGMA user_version", ver_cb, &ver);
sqlite3_exec(db, "PRAGMA user_version", ver_cb, &ver, &err);
err_ret(err);
if (ver > DB_VERSION) { if (ver > DB_VERSION) {
// Don't support downgrading database // Don't support downgrading database
sqlite3_close(db); sqlite3_close(db);
return strdup("Downgrading database is not supported"); return "Downgrading database is not supported";
} }
auto create_policy = [&] { auto create_policy = [&] {
sqlite3_exec(db, return sql_exec(db,
"CREATE TABLE IF NOT EXISTS policies " "CREATE TABLE IF NOT EXISTS policies "
"(uid INT, policy INT, until INT, logging INT, " "(uid INT, policy INT, until INT, logging INT, "
"notification INT, PRIMARY KEY(uid))", "notification INT, PRIMARY KEY(uid))",
nullptr, nullptr, &err); nullptr, nullptr);
}; };
auto create_settings = [&] { auto create_settings = [&] {
sqlite3_exec(db, return sql_exec(db,
"CREATE TABLE IF NOT EXISTS settings " "CREATE TABLE IF NOT EXISTS settings "
"(key TEXT, value INT, PRIMARY KEY(key))", "(key TEXT, value INT, PRIMARY KEY(key))",
nullptr, nullptr, &err); nullptr, nullptr);
}; };
auto create_strings = [&] { auto create_strings = [&] {
sqlite3_exec(db, return sql_exec(db,
"CREATE TABLE IF NOT EXISTS strings " "CREATE TABLE IF NOT EXISTS strings "
"(key TEXT, value TEXT, PRIMARY KEY(key))", "(key TEXT, value TEXT, PRIMARY KEY(key))",
nullptr, nullptr, &err); nullptr, nullptr);
}; };
auto create_denylist = [&] { auto create_denylist = [&] {
sqlite3_exec(db, return sql_exec(db,
"CREATE TABLE IF NOT EXISTS denylist " "CREATE TABLE IF NOT EXISTS denylist "
"(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process))", "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process))",
nullptr, nullptr, &err); nullptr, nullptr);
}; };
// Database changelog: // Database changelog:
@@ -194,21 +204,17 @@ static char *open_and_init_db(sqlite3 *&db) {
// 12: rebuild table `policies` to drop column `package_name` // 12: rebuild table `policies` to drop column `package_name`
if (/* 0, 1, 2, 3, 4, 5, 6 */ ver <= 6) { if (/* 0, 1, 2, 3, 4, 5, 6 */ ver <= 6) {
create_policy(); fn_run_ret(create_policy);
err_ret(err); fn_run_ret(create_settings);
create_settings(); fn_run_ret(create_strings);
err_ret(err); fn_run_ret(create_denylist);
create_strings();
err_ret(err);
create_denylist();
err_ret(err);
// Directly jump to latest // Directly jump to latest
ver = DB_VERSION; ver = DB_VERSION;
upgrade = true; upgrade = true;
} }
if (ver == 7) { if (ver == 7) {
sqlite3_exec(db, sql_exe_ret(db,
"BEGIN TRANSACTION;" "BEGIN TRANSACTION;"
"ALTER TABLE hidelist RENAME TO hidelist_tmp;" "ALTER TABLE hidelist RENAME TO hidelist_tmp;"
"CREATE TABLE IF NOT EXISTS hidelist " "CREATE TABLE IF NOT EXISTS hidelist "
@@ -216,14 +222,13 @@ static char *open_and_init_db(sqlite3 *&db) {
"INSERT INTO hidelist SELECT process as package_name, process FROM hidelist_tmp;" "INSERT INTO hidelist SELECT process as package_name, process FROM hidelist_tmp;"
"DROP TABLE hidelist_tmp;" "DROP TABLE hidelist_tmp;"
"COMMIT;", "COMMIT;",
nullptr, nullptr, &err); nullptr, nullptr);
err_ret(err);
// Directly jump to version 9 // Directly jump to version 9
ver = 9; ver = 9;
upgrade = true; upgrade = true;
} }
if (ver == 8) { if (ver == 8) {
sqlite3_exec(db, sql_exe_ret(db,
"BEGIN TRANSACTION;" "BEGIN TRANSACTION;"
"ALTER TABLE hidelist RENAME TO hidelist_tmp;" "ALTER TABLE hidelist RENAME TO hidelist_tmp;"
"CREATE TABLE IF NOT EXISTS hidelist " "CREATE TABLE IF NOT EXISTS hidelist "
@@ -231,30 +236,26 @@ static char *open_and_init_db(sqlite3 *&db) {
"INSERT INTO hidelist SELECT * FROM hidelist_tmp;" "INSERT INTO hidelist SELECT * FROM hidelist_tmp;"
"DROP TABLE hidelist_tmp;" "DROP TABLE hidelist_tmp;"
"COMMIT;", "COMMIT;",
nullptr, nullptr, &err); nullptr, nullptr);
err_ret(err);
ver = 9; ver = 9;
upgrade = true; upgrade = true;
} }
if (ver == 9) { if (ver == 9) {
sqlite3_exec(db, "DROP TABLE IF EXISTS logs", nullptr, nullptr, &err); sql_exe_ret(db, "DROP TABLE IF EXISTS logs", nullptr, nullptr);
err_ret(err);
ver = 10; ver = 10;
upgrade = true; upgrade = true;
} }
if (ver == 10) { if (ver == 10) {
sqlite3_exec(db, sql_exe_ret(db,
"DROP TABLE IF EXISTS hidelist;" "DROP TABLE IF EXISTS hidelist;"
"DELETE FROM settings WHERE key='magiskhide';", "DELETE FROM settings WHERE key='magiskhide';",
nullptr, nullptr, &err); nullptr, nullptr);
err_ret(err); fn_run_ret(create_denylist);
create_denylist();
err_ret(err);
ver = 11; ver = 11;
upgrade = true; upgrade = true;
} }
if (ver == 11) { if (ver == 11) {
sqlite3_exec(db, sql_exe_ret(db,
"BEGIN TRANSACTION;" "BEGIN TRANSACTION;"
"ALTER TABLE policies RENAME TO policies_tmp;" "ALTER TABLE policies RENAME TO policies_tmp;"
"CREATE TABLE IF NOT EXISTS policies " "CREATE TABLE IF NOT EXISTS policies "
@@ -264,8 +265,7 @@ static char *open_and_init_db(sqlite3 *&db) {
"SELECT uid, policy, until, logging, notification FROM policies_tmp;" "SELECT uid, policy, until, logging, notification FROM policies_tmp;"
"DROP TABLE policies_tmp;" "DROP TABLE policies_tmp;"
"COMMIT;", "COMMIT;",
nullptr, nullptr, &err); nullptr, nullptr);
err_ret(err);
ver = 12; ver = 12;
upgrade = true; upgrade = true;
} }
@@ -274,28 +274,25 @@ static char *open_and_init_db(sqlite3 *&db) {
// Set version // Set version
char query[32]; char query[32];
sprintf(query, "PRAGMA user_version=%d", ver); sprintf(query, "PRAGMA user_version=%d", ver);
sqlite3_exec(db, query, nullptr, nullptr, &err); sql_exe_ret(db, query, nullptr, nullptr);
err_ret(err);
} }
return nullptr; return {};
} }
char *db_exec(const char *sql) { db_result db_exec(const char *sql) {
char *err = nullptr;
if (mDB == nullptr) { if (mDB == nullptr) {
err = open_and_init_db(mDB); auto res = open_and_init_db(mDB);
db_err_cmd(err, if (res.check_err()) {
// Open fails, remove and reconstruct // Open fails, remove and reconstruct
unlink(MAGISKDB); unlink(MAGISKDB);
err = open_and_init_db(mDB); res = open_and_init_db(mDB);
err_ret(err); if (!res) return res;
); }
} }
if (mDB) { if (mDB) {
sqlite3_exec(mDB, sql, nullptr, nullptr, &err); sql_exe_ret(mDB, sql, nullptr, nullptr);
return err;
} }
return nullptr; return {};
} }
static int sqlite_db_row_callback(void *cb, int col_num, char **data, char **col_name) { static int sqlite_db_row_callback(void *cb, int col_num, char **data, char **col_name) {
@@ -306,26 +303,24 @@ static int sqlite_db_row_callback(void *cb, int col_num, char **data, char **col
return func(row) ? 0 : 1; return func(row) ? 0 : 1;
} }
char *db_exec(const char *sql, const db_row_cb &fn) { db_result db_exec(const char *sql, const db_row_cb &fn) {
char *err = nullptr;
if (mDB == nullptr) { if (mDB == nullptr) {
err = open_and_init_db(mDB); auto res = open_and_init_db(mDB);
db_err_cmd(err, if (res.check_err()) {
// Open fails, remove and reconstruct // Open fails, remove and reconstruct
unlink(MAGISKDB); unlink(MAGISKDB);
err = open_and_init_db(mDB); res = open_and_init_db(mDB);
err_ret(err); if (!res) return res;
); }
} }
if (mDB) { if (mDB) {
sqlite3_exec(mDB, sql, sqlite_db_row_callback, (void *) &fn, &err); sql_exe_ret(mDB, sql, sqlite_db_row_callback, (void *) &fn);
return err;
} }
return nullptr; return {};
} }
int get_db_settings(db_settings &cfg, int key) { int get_db_settings(db_settings &cfg, int key) {
char *err = nullptr; db_result res;
auto settings_cb = [&](db_row &row) -> bool { auto settings_cb = [&](db_row &row) -> bool {
cfg[row["key"]] = parse_int(row["value"]); cfg[row["key"]] = parse_int(row["value"]);
DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data()); DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data());
@@ -334,26 +329,22 @@ int get_db_settings(db_settings &cfg, int key) {
if (key >= 0) { if (key >= 0) {
char query[128]; char query[128];
ssprintf(query, sizeof(query), "SELECT * FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]); ssprintf(query, sizeof(query), "SELECT * FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]);
err = db_exec(query, settings_cb); res = db_exec(query, settings_cb);
} else { } else {
err = db_exec("SELECT * FROM settings", settings_cb); res = db_exec("SELECT * FROM settings", settings_cb);
} }
db_err_cmd(err, return 1); return res.check_err() ? 1 : 0;
return 0;
} }
int set_db_settings(int key, int value) { int set_db_settings(int key, int value) {
char *err;
char sql[128]; char sql[128];
ssprintf(sql, sizeof(sql), "INSERT OR REPLACE INTO settings VALUES ('%s', %d)", ssprintf(sql, sizeof(sql), "INSERT OR REPLACE INTO settings VALUES ('%s', %d)",
DB_SETTING_KEYS[key], value); DB_SETTING_KEYS[key], value);
err = db_exec(sql); return db_exec(sql).check_err() ? 1 : 0;
db_err_cmd(err, return 1)
return 0;
} }
int get_db_strings(db_strings &str, int key) { int get_db_strings(db_strings &str, int key) {
char *err = nullptr; db_result res;
auto string_cb = [&](db_row &row) -> bool { auto string_cb = [&](db_row &row) -> bool {
str[row["key"]] = row["value"]; str[row["key"]] = row["value"];
DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data()); DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data());
@@ -362,26 +353,22 @@ int get_db_strings(db_strings &str, int key) {
if (key >= 0) { if (key >= 0) {
char query[128]; char query[128];
ssprintf(query, sizeof(query), "SELECT * FROM strings WHERE key='%s'", DB_STRING_KEYS[key]); ssprintf(query, sizeof(query), "SELECT * FROM strings WHERE key='%s'", DB_STRING_KEYS[key]);
err = db_exec(query, string_cb); res = db_exec(query, string_cb);
} else { } else {
err = db_exec("SELECT * FROM strings", string_cb); res = db_exec("SELECT * FROM strings", string_cb);
} }
db_err_cmd(err, return 1); return res.check_err() ? 1 : 0;
return 0;
} }
void rm_db_strings(int key) { void rm_db_strings(int key) {
char *err;
char query[128]; char query[128];
ssprintf(query, sizeof(query), "DELETE FROM strings WHERE key == '%s'", DB_STRING_KEYS[key]); ssprintf(query, sizeof(query), "DELETE FROM strings WHERE key == '%s'", DB_STRING_KEYS[key]);
err = db_exec(query); db_exec(query).check_err();
db_err_cmd(err, return);
} }
void exec_sql(int client) { void exec_sql(owned_fd client) {
run_finally f([=]{ close(client); });
string sql = read_string(client); string sql = read_string(client);
char *err = db_exec(sql.data(), [client](db_row &row) -> bool { auto res = db_exec(sql.data(), [fd = (int) client](db_row &row) -> bool {
string out; string out;
bool first = true; bool first = true;
for (auto it : row) { for (auto it : row) {
@@ -391,18 +378,9 @@ void exec_sql(int client) {
out += '='; out += '=';
out += it.second; out += it.second;
} }
write_string(client, out); write_string(fd, out);
return true; return true;
}); });
write_int(client, 0); write_int(client, 0);
db_err_cmd(err, return; ); res.check_err();
}
bool db_err(char *e) {
if (e) {
LOGE("sqlite3_exec: %s\n", e);
sqlite3_free(e);
return true;
}
return false;
} }

View File

@@ -201,7 +201,7 @@ void scan_deny_apps() {
LOGI("denylist rm: [%s]\n", it->first.data()); LOGI("denylist rm: [%s]\n", it->first.data());
ssprintf(sql, sizeof(sql), "DELETE FROM denylist WHERE package_name='%s'", ssprintf(sql, sizeof(sql), "DELETE FROM denylist WHERE package_name='%s'",
it->first.data()); it->first.data());
db_err(db_exec(sql)); db_exec(sql).check_err();
it = pkg_to_procs.erase(it); it = pkg_to_procs.erase(it);
} else { } else {
update_app_id(app_id, it->first, false); update_app_id(app_id, it->first, false);
@@ -222,11 +222,12 @@ static bool ensure_data() {
LOGI("denylist: initializing internal data structures\n"); LOGI("denylist: initializing internal data structures\n");
default_new(pkg_to_procs_); default_new(pkg_to_procs_);
char *err = db_exec("SELECT * FROM denylist", [](db_row &row) -> bool { auto res = db_exec("SELECT * FROM denylist", [](db_row &row) -> bool {
add_hide_set(row["package_name"].data(), row["process"].data()); add_hide_set(row["package_name"].data(), row["process"].data());
return true; return true;
}); });
db_err_cmd(err, goto error) if (res.check_err())
goto error;
default_new(app_id_to_pkgs_); default_new(app_id_to_pkgs_);
scan_deny_apps(); scan_deny_apps();
@@ -262,9 +263,7 @@ static int add_list(const char *pkg, const char *proc) {
char sql[4096]; char sql[4096];
ssprintf(sql, sizeof(sql), ssprintf(sql, sizeof(sql),
"INSERT INTO denylist (package_name, process) VALUES('%s', '%s')", pkg, proc); "INSERT INTO denylist (package_name, process) VALUES('%s', '%s')", pkg, proc);
char *err = db_exec(sql); return db_exec(sql).check_err() ? DenyResponse::ERROR : DenyResponse::OK;
db_err_cmd(err, return DenyResponse::ERROR)
return DenyResponse::OK;
} }
int add_list(int client) { int add_list(int client) {
@@ -308,9 +307,7 @@ static int rm_list(const char *pkg, const char *proc) {
else else
ssprintf(sql, sizeof(sql), ssprintf(sql, sizeof(sql),
"DELETE FROM denylist WHERE package_name='%s' AND process='%s'", pkg, proc); "DELETE FROM denylist WHERE package_name='%s' AND process='%s'", pkg, proc);
char *err = db_exec(sql); return db_exec(sql).check_err() ? DenyResponse::ERROR : DenyResponse::OK;
db_err_cmd(err, return DenyResponse::ERROR)
return DenyResponse::OK;
} }
int rm_list(int client) { int rm_list(int client) {

View File

@@ -124,14 +124,21 @@ struct su_access {
using db_row = std::map<std::string_view, std::string_view>; using db_row = std::map<std::string_view, std::string_view>;
using db_row_cb = std::function<bool(db_row&)>; using db_row_cb = std::function<bool(db_row&)>;
struct owned_fd;
struct db_result {
db_result() = default;
db_result(const char *s) : err(s) {}
bool check_err();
operator bool() { return err.empty(); }
private:
std::string err;
};
int get_db_settings(db_settings &cfg, int key = -1); int get_db_settings(db_settings &cfg, int key = -1);
int set_db_settings(int key, int value); int set_db_settings(int key, int value);
int get_db_strings(db_strings &str, int key = -1); int get_db_strings(db_strings &str, int key = -1);
void rm_db_strings(int key); void rm_db_strings(int key);
void exec_sql(int client); void exec_sql(owned_fd client);
char *db_exec(const char *sql); db_result db_exec(const char *sql);
char *db_exec(const char *sql, const db_row_cb &fn); db_result db_exec(const char *sql, const db_row_cb &fn);
bool db_err(char *e);
#define db_err_cmd(e, cmd) if (db_err(e)) { cmd; }

View File

@@ -1,7 +1,6 @@
#![feature(format_args_nl)] #![feature(format_args_nl)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(option_take_if)]
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
use base::Utf8CStr; use base::Utf8CStr;
@@ -10,7 +9,7 @@ use daemon::{daemon_entry, find_apk_path, get_magiskd, MagiskD};
use logging::{ use logging::{
android_logging, magisk_logging, zygisk_close_logd, zygisk_get_logd, zygisk_logging, android_logging, magisk_logging, zygisk_close_logd, zygisk_get_logd, zygisk_logging,
}; };
use mount::{find_preinit_device, revert_unmount, setup_mounts}; use mount::{find_preinit_device, revert_unmount, setup_mounts, clean_mounts};
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop}; use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
mod cert; mod cert;
@@ -93,6 +92,7 @@ pub mod ffi {
fn find_apk_path(pkg: Utf8CStrRef, data: &mut [u8]) -> usize; fn find_apk_path(pkg: Utf8CStrRef, data: &mut [u8]) -> usize;
fn read_certificate(fd: i32, version: i32) -> Vec<u8>; fn read_certificate(fd: i32, version: i32) -> Vec<u8>;
fn setup_mounts(); fn setup_mounts();
fn clean_mounts();
fn find_preinit_device() -> String; fn find_preinit_device() -> String;
fn revert_unmount(pid: i32); fn revert_unmount(pid: i32);
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>); unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>);

View File

@@ -157,11 +157,9 @@ void tmpfs_node::mount() {
if (!isa<tmpfs_node>(parent())) { if (!isa<tmpfs_node>(parent())) {
auto worker_dir = worker_path(); auto worker_dir = worker_path();
mkdirs(worker_dir.data(), 0); mkdirs(worker_dir.data(), 0);
bind_mount("tmpfs", worker_dir.data(), worker_dir.data());
clone_attr(exist() ? node_path().data() : parent()->node_path().data(), worker_dir.data()); clone_attr(exist() ? node_path().data() : parent()->node_path().data(), worker_dir.data());
dir_node::mount(); dir_node::mount();
VLOGD(replace() ? "replace" : "move", worker_dir.data(), node_path().data()); bind_mount(replace() ? "replace" : "move", worker_dir.data(), node_path().data());
xmount(worker_dir.data(), node_path().data(), nullptr, MS_MOVE, nullptr);
xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr); xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr);
} else { } else {
const string dest = worker_path(); const string dest = worker_path();
@@ -213,6 +211,8 @@ public:
const string src = get_magisk_tmp() + "/magisk"s; const string src = get_magisk_tmp() + "/magisk"s;
(void) is64bit; (void) is64bit;
#endif #endif
if (access(src.data(), F_OK))
return;
create_and_mount("zygisk", src, true); create_and_mount("zygisk", src, true);
} }
@@ -333,10 +333,7 @@ void load_modules() {
} }
// cleanup mounts // cleanup mounts
ssprintf(buf, sizeof(buf), "%s/" WORKERDIR, get_magisk_tmp()); clean_mounts();
xumount2(buf, MNT_DETACH);
ssprintf(buf, sizeof(buf), "%s/" MODULEMNT, get_magisk_tmp());
xumount2(buf, MNT_DETACH);
} }
/************************ /************************

View File

@@ -94,36 +94,40 @@ pub fn setup_mounts() {
ptr::null(), ptr::null(),
) )
.as_os_err()?; .as_os_err()?;
libc::mount( }
ptr::null(), };
}
pub fn clean_mounts() {
let magisk_tmp = get_magisk_tmp();
let mut buf = Utf8CStrBufArr::default();
let module_mnt = FsPathBuf::new(&mut buf).join(magisk_tmp).join(MODULEMNT);
let _: LoggedResult<()> = try {
unsafe {
libc::umount2(
module_mnt.as_ptr(), module_mnt.as_ptr(),
ptr::null(), libc::MNT_DETACH,
libc::MS_PRIVATE,
ptr::null(),
) )
.as_os_err()?; .as_os_err()?;
} }
}; };
// Prepare worker
let worker_dir = FsPathBuf::new(&mut buf).join(magisk_tmp).join(WORKERDIR); let worker_dir = FsPathBuf::new(&mut buf).join(magisk_tmp).join(WORKERDIR);
let _: LoggedResult<()> = try { let _: LoggedResult<()> = try {
worker_dir.mkdir(0)?;
unsafe { unsafe {
libc::mount( libc::mount(
worker_dir.as_ptr(), ptr::null(),
worker_dir.as_ptr(), worker_dir.as_ptr(),
ptr::null(), ptr::null(),
libc::MS_BIND, libc::MS_PRIVATE | libc::MS_REC,
ptr::null(), ptr::null(),
) )
.as_os_err()?; .as_os_err()?;
libc::mount( libc::umount2(
ptr::null(),
worker_dir.as_ptr(), worker_dir.as_ptr(),
ptr::null(), libc::MNT_DETACH,
libc::MS_PRIVATE,
ptr::null(),
) )
.as_os_err()?; .as_os_err()?;
} }
@@ -201,12 +205,16 @@ pub fn find_preinit_device() -> String {
let (_, preinit_info, _) = matched_info.select_nth_unstable_by( let (_, preinit_info, _) = matched_info.select_nth_unstable_by(
0, 0,
|(ap, MountInfo { fs_type: at, .. }), (bp, MountInfo { fs_type: bt, .. })| match ( |(ap, MountInfo { fs_type: at, .. }), (bp, MountInfo { fs_type: bt, .. })| match (
ap,
bp,
at.as_str() == "ext4", at.as_str() == "ext4",
bt.as_str() == "ext4", bt.as_str() == "ext4",
) { ) {
// take ext4 over others (f2fs) because f2fs has a kernel bug that causes kernel panic // metadata is not affected by f2fs kernel bug
(true, false) => Less, (PartId::Metadata, _, _, true) | (_, PartId::Metadata, true, _) => ap.cmp(bp),
(false, true) => Greater, // otherwise, take ext4 f2fs because f2fs has a kernel bug that causes kernel panic
(_, _, true, false) => Less,
(_, _, false, true) => Greater,
// if both has the same fs type, compare the mount point // if both has the same fs type, compare the mount point
_ => ap.cmp(bp), _ => ap.cmp(bp),
}, },

View File

@@ -222,6 +222,7 @@ void install_module(const char *file) {
setenv("OUTFD", "1", 1); setenv("OUTFD", "1", 1);
setenv("ZIPFILE", zip, 1); setenv("ZIPFILE", zip, 1);
setenv("ASH_STANDALONE", "1", 1); setenv("ASH_STANDALONE", "1", 1);
setenv("MAGISKTMP", get_magisk_tmp(), 0);
free(zip); free(zip);
int fd = xopen("/dev/null", O_RDONLY); int fd = xopen("/dev/null", O_RDONLY);

View File

@@ -63,11 +63,11 @@ void su_info::check_db() {
} }
if (eval_uid > 0) { if (eval_uid > 0) {
char query[256], *err; char query[256];
ssprintf(query, sizeof(query), ssprintf(query, sizeof(query),
"SELECT policy, logging, notification FROM policies " "SELECT policy, logging, notification FROM policies "
"WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr)); "WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr));
err = db_exec(query, [&](db_row &row) -> bool { auto res = db_exec(query, [&](db_row &row) -> bool {
access.policy = (policy_t) parse_int(row["policy"]); access.policy = (policy_t) parse_int(row["policy"]);
access.log = parse_int(row["logging"]); access.log = parse_int(row["logging"]);
access.notify = parse_int(row["notification"]); access.notify = parse_int(row["notification"]);
@@ -75,7 +75,8 @@ void su_info::check_db() {
access.policy, access.log, access.notify); access.policy, access.log, access.notify);
return true; return true;
}); });
db_err_cmd(err, return); if (res.check_err())
return;
} }
// We need to check our manager // We need to check our manager
@@ -123,15 +124,16 @@ bool uid_granted_root(int uid) {
bool granted = false; bool granted = false;
char query[256], *err; char query[256];
ssprintf(query, sizeof(query), ssprintf(query, sizeof(query),
"SELECT policy FROM policies WHERE uid=%d AND (until=0 OR until>%li)", "SELECT policy FROM policies WHERE uid=%d AND (until=0 OR until>%li)",
uid, time(nullptr)); uid, time(nullptr));
err = db_exec(query, [&](db_row &row) -> bool { auto res = db_exec(query, [&](db_row &row) -> bool {
granted = parse_int(row["policy"]) == ALLOW; granted = parse_int(row["policy"]) == ALLOW;
return true; return true;
}); });
db_err_cmd(err, return false); if (res.check_err())
return false;
return granted; return granted;
} }
@@ -140,9 +142,7 @@ void prune_su_access() {
cached.reset(); cached.reset();
vector<bool> app_no_list = get_app_no_list(); vector<bool> app_no_list = get_app_no_list();
vector<int> rm_uids; vector<int> rm_uids;
char query[256], *err; auto res = db_exec("SELECT uid FROM policies", [&](db_row &row) -> bool {
strscpy(query, "SELECT uid FROM policies", sizeof(query));
err = db_exec(query, [&](db_row &row) -> bool {
int uid = parse_int(row["uid"]); int uid = parse_int(row["uid"]);
int app_id = to_app_id(uid); int app_id = to_app_id(uid);
if (app_id >= AID_APP_START && app_id <= AID_APP_END) { if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
@@ -154,11 +154,13 @@ void prune_su_access() {
} }
return true; return true;
}); });
db_err_cmd(err, return); if (res.check_err())
return;
for (int uid : rm_uids) { for (int uid : rm_uids) {
char query[256];
ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid); ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid);
db_err(db_exec(query)); db_exec(query).check_err();
} }
} }

View File

@@ -41,16 +41,16 @@ static string extract_quoted_str_until(chars<escapes...>, chars<breaks...>,
} }
// Parse string into key value pairs. // Parse string into key value pairs.
// The string format: [delim][key][padding]=[padding][value][delim] // The string format: [delim][key][padding][eq][padding][value][delim]
template<char delim, char... padding> template<char delim, char eq, char... padding>
static kv_pairs parse_impl(chars<padding...>, string_view str) { static kv_pairs parse_impl(chars<padding...>, string_view str) {
kv_pairs kv; kv_pairs kv;
char skip_array[] = {'=', padding...}; char skip_array[] = {eq, padding...};
string_view skip(skip_array, std::size(skip_array)); string_view skip(skip_array, std::size(skip_array));
bool quoted = false; bool quoted = false;
for (size_t pos = 0u; pos < str.size(); pos = str.find_first_not_of(delim, pos)) { for (size_t pos = 0u; pos < str.size(); pos = str.find_first_not_of(delim, pos)) {
auto key = extract_quoted_str_until( auto key = extract_quoted_str_until(
chars<padding..., delim>{}, chars<'='>{}, str, pos, quoted); chars<padding..., delim>{}, chars<eq>{}, str, pos, quoted);
pos = str.find_first_not_of(skip, pos); pos = str.find_first_not_of(skip, pos);
if (pos == string_view::npos || str[pos] == delim) { if (pos == string_view::npos || str[pos] == delim) {
kv.emplace_back(key, ""); kv.emplace_back(key, "");
@@ -63,10 +63,13 @@ static kv_pairs parse_impl(chars<padding...>, string_view str) {
} }
static kv_pairs parse_cmdline(string_view str) { static kv_pairs parse_cmdline(string_view str) {
return parse_impl<' '>(chars<>{}, str); return parse_impl<' ', '='>(chars<>{}, str);
} }
static kv_pairs parse_bootconfig(string_view str) { static kv_pairs parse_bootconfig(string_view str) {
return parse_impl<'\n'>(chars<' '>{}, str); return parse_impl<'\n', '='>(chars<' '>{}, str);
}
static kv_pairs parse_partition_map(std::string_view str) {
return parse_impl<';', ','>(chars<>{}, str);
} }
#define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) #define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8)))
@@ -207,11 +210,35 @@ void load_kernel_info(BootConfig *config) {
config->print(); config->print();
} }
// `androidboot.partition_map` allows associating a partition name for a raw block device
// through a comma separated and semicolon deliminated list. For example,
// `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
// `userdata`.
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191
kv_pairs load_partition_map() {
const string_view kPartitionMapKey = "androidboot.partition_map";
for (const auto &[key, value] : parse_cmdline(full_read("/proc/cmdline"))) {
if (key == kPartitionMapKey)
return parse_partition_map(value);
}
for (const auto &[key, value] : parse_bootconfig(full_read("/proc/bootconfig"))) {
if (key == kPartitionMapKey)
return parse_partition_map(value);
}
return {};
}
bool check_two_stage() { bool check_two_stage() {
if (access("/apex", F_OK) == 0) if (access("/first_stage_ramdisk", F_OK) == 0)
return true;
if (access("/second_stage_resources", F_OK) == 0)
return true; return true;
if (access("/system/bin/init", F_OK) == 0) if (access("/system/bin/init", F_OK) == 0)
return true; return true;
// Use the apex folder to determine whether 2SI (Android 10+)
if (access("/apex", F_OK) == 0)
return true;
// If we still have no indication, parse the original init and see what's up // If we still have no indication, parse the original init and see what's up
mmap_data init(backup_init()); mmap_data init(backup_init());
return init.contains("selinux_setup"); return init.contains("selinux_setup");

View File

@@ -6,14 +6,18 @@
#include <xz.h> #include <xz.h>
#include <base.hpp> #include <base.hpp>
#include <embed.hpp>
#include "init.hpp" #include "init.hpp"
using namespace std; using namespace std;
#ifdef USE_CRT0 #ifdef USE_CRT0
__asm__(".global vfprintf \n vfprintf = tfp_vfprintf"); __BEGIN_DECLS
int tiny_vfprintf(FILE *stream, const char *format, va_list arg);
int vfprintf(FILE *stream, const char *format, va_list arg) {
return tiny_vfprintf(stream, format, arg);
}
__END_DECLS
#endif #endif
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes) { bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes) {

View File

@@ -29,6 +29,7 @@ extern std::vector<std::string> mount_list;
int magisk_proxy_main(int argc, char *argv[]); int magisk_proxy_main(int argc, char *argv[]);
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes); bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
void load_kernel_info(BootConfig *config); void load_kernel_info(BootConfig *config);
kv_pairs load_partition_map();
bool check_two_stage(); bool check_two_stage();
const char *backup_init(); const char *backup_init();
void restore_ramdisk_init(); void restore_ramdisk_init();

View File

@@ -29,21 +29,23 @@ bool avd_hack = false;
static void parse_device(devinfo *dev, const char *uevent) { static void parse_device(devinfo *dev, const char *uevent) {
dev->partname[0] = '\0'; dev->partname[0] = '\0';
dev->devpath[0] = '\0'; dev->devpath[0] = '\0';
dev->dmname[0] = '\0';
dev->devname[0] = '\0';
parse_prop_file(uevent, [=](string_view key, string_view value) -> bool { parse_prop_file(uevent, [=](string_view key, string_view value) -> bool {
if (key == "MAJOR") if (key == "MAJOR")
dev->major = parse_int(value.data()); dev->major = parse_int(value.data());
else if (key == "MINOR") else if (key == "MINOR")
dev->minor = parse_int(value.data()); dev->minor = parse_int(value.data());
else if (key == "DEVNAME") else if (key == "DEVNAME")
strcpy(dev->devname, value.data()); strscpy(dev->devname, value.data(), sizeof(dev->devname));
else if (key == "PARTNAME") else if (key == "PARTNAME")
strcpy(dev->partname, value.data()); strscpy(dev->partname, value.data(), sizeof(dev->devname));
return true; return true;
}); });
} }
static void collect_devices() { static void collect_devices(const auto &partition_map) {
char path[PATH_MAX]; char path[PATH_MAX];
devinfo dev{}; devinfo dev{};
if (auto dir = xopen_dir("/sys/dev/block"); dir) { if (auto dir = xopen_dir("/sys/dev/block"); dir) {
@@ -55,7 +57,13 @@ static void collect_devices() {
sprintf(path, "/sys/dev/block/%s/dm/name", entry->d_name); sprintf(path, "/sys/dev/block/%s/dm/name", entry->d_name);
if (access(path, F_OK) == 0) { if (access(path, F_OK) == 0) {
auto name = rtrim(full_read(path)); auto name = rtrim(full_read(path));
strcpy(dev.dmname, name.data()); strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
}
if (auto it = std::ranges::find_if(partition_map, [&](const auto &i) {
return i.first == dev.devname;
}); dev.partname[0] == '\0' && it != partition_map.end()) {
// use androidboot.partition_map as partname fallback.
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
} }
sprintf(path, "/sys/dev/block/%s", entry->d_name); sprintf(path, "/sys/dev/block/%s", entry->d_name);
xrealpath(path, dev.devpath, sizeof(dev.devpath)); xrealpath(path, dev.devpath, sizeof(dev.devpath));
@@ -70,8 +78,9 @@ static struct {
} blk_info; } blk_info;
static dev_t setup_block() { static dev_t setup_block() {
static const auto partition_map = load_partition_map();
if (dev_list.empty()) if (dev_list.empty())
collect_devices(); collect_devices(partition_map);
for (int tries = 0; tries < 3; ++tries) { for (int tries = 0; tries < 3; ++tries) {
for (auto &dev : dev_list) { for (auto &dev : dev_list) {
@@ -93,7 +102,7 @@ static dev_t setup_block() {
// Wait 10ms and try again // Wait 10ms and try again
usleep(10000); usleep(10000);
dev_list.clear(); dev_list.clear();
collect_devices(); collect_devices(partition_map);
} }
// The requested partname does not exist // The requested partname does not exist
@@ -191,8 +200,7 @@ mount_root:
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755"); xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
mount_list.emplace_back("/dev"); mount_list.emplace_back("/dev");
// Use the apex folder to determine whether 2SI (Android 10+) bool is_two_stage = access("/system/bin/init", F_OK) == 0;
bool is_two_stage = access("/apex", F_OK) == 0;
LOGD("is_two_stage: [%d]\n", is_two_stage); LOGD("is_two_stage: [%d]\n", is_two_stage);
// For API 28 AVD, it uses legacy SAR setup that requires // For API 28 AVD, it uses legacy SAR setup that requires
@@ -236,6 +244,7 @@ void MagiskInit::setup_tmp(const char *path) {
xmkdir(INTLROOT, 0711); xmkdir(INTLROOT, 0711);
xmkdir(DEVICEDIR, 0711); xmkdir(DEVICEDIR, 0711);
xmkdir(WORKERDIR, 0);
mount_preinit_dir(preinit_dev); mount_preinit_dir(preinit_dev);
@@ -249,5 +258,21 @@ void MagiskInit::setup_tmp(const char *path) {
xmount(".", path, nullptr, MS_BIND, nullptr); xmount(".", path, nullptr, MS_BIND, nullptr);
chdir(path);
// Prepare worker
xmount(WORKERDIR, WORKERDIR, nullptr, MS_BIND, nullptr);
// Use isolated devpts if kernel support
if (access("/dev/pts/ptmx", F_OK) == 0) {
xmkdirs(SHELLPTS, 0755);
xmount("devpts", SHELLPTS, "devpts", MS_NOSUID | MS_NOEXEC, "newinstance");
xmount(nullptr, SHELLPTS, nullptr, MS_PRIVATE, nullptr);
if (access(SHELLPTS "/ptmx", F_OK)) {
umount2(SHELLPTS, MNT_DETACH);
rmdir(SHELLPTS);
}
}
chdir("/"); chdir("/");
} }

View File

@@ -12,10 +12,31 @@
using namespace std; using namespace std;
static vector<string> rc_list; static vector<string> rc_list;
static string magic_mount_list;
#define NEW_INITRC_DIR "/system/etc/init/hw" #define NEW_INITRC_DIR "/system/etc/init/hw"
#define INIT_RC "init.rc" #define INIT_RC "init.rc"
static void magic_mount(const string &sdir, const string &ddir = "") {
auto dir = xopen_dir(sdir.data());
if (!dir) return;
for (dirent *entry; (entry = xreaddir(dir.get()));) {
string src = sdir + "/" + entry->d_name;
string dest = ddir + "/" + entry->d_name;
if (access(dest.data(), F_OK) == 0) {
if (entry->d_type == DT_DIR) {
// Recursive
magic_mount(src, dest);
} else {
LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data());
xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr);
magic_mount_list += dest;
magic_mount_list += '\n';
}
}
}
}
static void patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) { static void patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) {
auto src_dir = xopen_dir(src_path); auto src_dir = xopen_dir(src_path);
if (!src_dir) return; if (!src_dir) return;
@@ -105,6 +126,43 @@ static void patch_rc_scripts(const char *src_path, const char *tmp_path, bool wr
}); });
fclone_attr(fileno(src.get()), fileno(dest.get())); fclone_attr(fileno(src.get()), fileno(dest.get()));
} }
if (faccessat(src_fd, "init.fission_host.rc", F_OK, 0) == 0) {
{
LOGD("Patching fissiond\n");
mmap_data fissiond("/system/bin/fissiond", false);
for (size_t off : fissiond.patch("ro.build.system.fission_single_os", "ro.build.system.xxxxxxxxxxxxxxxxx")) {
LOGD("Patch @ %08zX [ro.build.system.fission_single_os] -> [ro.build.system.xxxxxxxxxxxxxxxxx]\n", off);
}
mkdirs(ROOTOVL "/system/bin", 0755);
if (auto target_fissiond = xopen_file(ROOTOVL "/system/bin/fissiond", "we")) {
fwrite(fissiond.buf(), 1, fissiond.sz(), target_fissiond.get());
clone_attr("/system/bin/fissiond", ROOTOVL "/system/bin/fissiond");
}
}
LOGD("hijack isolated\n");
auto hijack = xopen_file("/sys/devices/system/cpu/isolated", "re");
mkfifo(INTLROOT "/isolated", 0777);
xmount(INTLROOT "/isolated", "/sys/devices/system/cpu/isolated", nullptr, MS_BIND, nullptr);
if (!xfork()) {
auto dest = xopen_file(INTLROOT "/isolated", "we");
LOGD("hijacked isolated\n");
xumount2("/sys/devices/system/cpu/isolated", MNT_DETACH);
unlink(INTLROOT "/isolated");
string content;
full_read(fileno(hijack.get()), content);
{
string target = "/dev/cells/cell2"s + tmp_path;
xmkdirs(target.data(), 0);
xmount(tmp_path, target.data(), nullptr, MS_BIND | MS_REC,nullptr);
magic_mount(ROOTOVL, "/dev/cells/cell2");
auto mount = xopen_file(ROOTMNT, "w");
fwrite(magic_mount_list.data(), 1, magic_mount_list.length(), mount.get());
}
fprintf(dest.get(), "%s", content.data());
exit(0);
}
}
} }
static void load_overlay_rc(const char *overlay) { static void load_overlay_rc(const char *overlay) {
@@ -164,31 +222,10 @@ static void recreate_sbin(const char *mirror, bool use_bind_mount) {
} }
} }
static string magic_mount_list;
static void magic_mount(const string &sdir, const string &ddir = "") {
auto dir = xopen_dir(sdir.data());
if (!dir) return;
for (dirent *entry; (entry = xreaddir(dir.get()));) {
string src = sdir + "/" + entry->d_name;
string dest = ddir + "/" + entry->d_name;
if (access(dest.data(), F_OK) == 0) {
if (entry->d_type == DT_DIR) {
// Recursive
magic_mount(src, dest);
} else {
LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data());
xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr);
magic_mount_list += dest;
magic_mount_list += '\n';
}
}
}
}
static void extract_files(bool sbin) { static void extract_files(bool sbin) {
const char *magisk_xz = sbin ? "/sbin/magisk.xz" : "magisk.xz"; const char *magisk_xz = sbin ? "/sbin/magisk.xz" : "magisk.xz";
const char *stub_xz = sbin ? "/sbin/stub.xz" : "stub.xz"; const char *stub_xz = sbin ? "/sbin/stub.xz" : "stub.xz";
const char *init_ld_xz = sbin ? "/sbin/init-ld.xz" : "init-ld.xz";
if (access(magisk_xz, F_OK) == 0) { if (access(magisk_xz, F_OK) == 0) {
mmap_data magisk(magisk_xz); mmap_data magisk(magisk_xz);
@@ -206,6 +243,14 @@ static void extract_files(bool sbin) {
unxz(ch, stub); unxz(ch, stub);
close(fd); close(fd);
} }
if (access(init_ld_xz, F_OK) == 0) {
mmap_data init_ld(init_ld_xz);
unlink(init_ld_xz);
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
fd_stream ch(fd);
unxz(ch, init_ld);
close(fd);
}
} }
void MagiskInit::parse_config_file() { void MagiskInit::parse_config_file() {
@@ -279,16 +324,19 @@ void MagiskInit::patch_ro_root() {
patch_rc_scripts("/", tmp_dir.data(), false); patch_rc_scripts("/", tmp_dir.data(), false);
} }
// Extract magisk // Extract overlay archives
extract_files(false); extract_files(false);
// Oculus Go will use a special sepolicy if unlocked // Oculus Go will use a special sepolicy if unlocked
if (access("/sepolicy.unlocked", F_OK) == 0) { if (access("/sepolicy.unlocked", F_OK) == 0) {
patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked"); patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked");
} else if ((access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0) || } else {
!hijack_sepolicy()) { bool patch = access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0;
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy"); if (patch || !hijack_sepolicy()) {
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy");
}
} }
unlink("init-ld");
// Mount rootdir // Mount rootdir
magic_mount(ROOTOVL); magic_mount(ROOTOVL);
@@ -338,12 +386,14 @@ void MagiskInit::patch_rw_root() {
setup_tmp(PRE_TMPDIR); setup_tmp(PRE_TMPDIR);
chdir(PRE_TMPDIR); chdir(PRE_TMPDIR);
// Extract magisk // Extract overlay archives
extract_files(true); extract_files(true);
if ((!treble && access("/sepolicy", F_OK) == 0) || !hijack_sepolicy()) { bool patch = !treble && access("/sepolicy", F_OK) == 0;
if (patch || !hijack_sepolicy()) {
patch_sepolicy("/sepolicy", "/sepolicy"); patch_sepolicy("/sepolicy", "/sepolicy");
} }
unlink("init-ld");
chdir("/"); chdir("/");

View File

@@ -14,7 +14,6 @@ pub fn inject_magisk_rc(fd: RawFd, tmp_dir: &Utf8CStr) {
file, file,
r#" r#"
on post-fs-data on post-fs-data
start logd
exec {0} 0 0 -- {1}/magisk --post-fs-data exec {0} 0 0 -- {1}/magisk --post-fs-data
on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_restart_framework

View File

@@ -2,7 +2,6 @@
#include <consts.hpp> #include <consts.hpp>
#include <sepolicy.hpp> #include <sepolicy.hpp>
#include <embed.hpp>
#include "init.hpp" #include "init.hpp"
@@ -31,16 +30,6 @@ void MagiskInit::patch_sepolicy(const char *in, const char *out) {
} }
} }
static void dump_preload() {
int fd = xopen("/dev/preload.so", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
if (fd < 0)
return;
fd_stream ch(fd);
if (!unxz(ch, byte_view(init_ld_xz, sizeof(init_ld_xz))))
return;
close(fd);
}
#define MOCK_COMPAT SELINUXMOCK "/compatible" #define MOCK_COMPAT SELINUXMOCK "/compatible"
#define MOCK_LOAD SELINUXMOCK "/load" #define MOCK_LOAD SELINUXMOCK "/load"
#define MOCK_ENFORCE SELINUXMOCK "/enforce" #define MOCK_ENFORCE SELINUXMOCK "/enforce"
@@ -53,7 +42,7 @@ bool MagiskInit::hijack_sepolicy() {
// This meant that instead of going through convoluted methods trying to alter // This meant that instead of going through convoluted methods trying to alter
// and block init's control flow, we can just LD_PRELOAD and replace the // and block init's control flow, we can just LD_PRELOAD and replace the
// security_load_policy function with our own implementation. // security_load_policy function with our own implementation.
dump_preload(); cp_afc("init-ld", "/dev/preload.so");
setenv("LD_PRELOAD", "/dev/preload.so", 1); setenv("LD_PRELOAD", "/dev/preload.so", 1);
} }
@@ -100,18 +89,10 @@ bool MagiskInit::hijack_sepolicy() {
// Read all custom rules into memory // Read all custom rules into memory
string rules; string rules;
if (auto dir = xopen_dir("/data/" PREINITMIRR)) { auto rule = "/data/" PREINITMIRR "/sepolicy.rule";
for (dirent *entry; (entry = xreaddir(dir.get()));) { if (xaccess(rule, R_OK) == 0) {
auto name = "/data/" PREINITMIRR "/"s + entry->d_name; LOGD("Loading custom sepolicy patch: [%s]\n", rule);
auto rule_file = name + "/sepolicy.rule"; rules = full_read(rule);
if (xaccess(rule_file.data(), R_OK) == 0 &&
access((name + "/disable").data(), F_OK) != 0 &&
access((name + "/remove").data(), F_OK) != 0) {
LOGD("Load custom sepolicy patch: [%s]\n", rule_file.data());
full_read(rule_file.data(), rules);
rules += '\n';
}
}
} }
// Create a new process waiting for init operations // Create a new process waiting for init operations
if (xfork()) { if (xfork()) {

View File

@@ -118,10 +118,6 @@ impl SepolicyExt for sepolicy {
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) { fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
reader.foreach_lines(|line| { reader.foreach_lines(|line| {
let line = line.trim();
if line.is_empty() {
return true;
}
parse_statement(self.as_mut(), line); parse_statement(self.as_mut(), line);
true true
}); });

View File

@@ -101,9 +101,8 @@ impl SepolicyMagisk for sepolicy {
"system_app", "priv_app", "untrusted_app", "untrusted_app_all"], "system_app", "priv_app", "untrusted_app", "untrusted_app_all"],
[proc], ["unix_stream_socket"], ["connectto", "getopt"]); [proc], ["unix_stream_socket"], ["connectto", "getopt"]);
// Let selected domains access tmpfs files // For tmpfs overlay on 2SI. We allow all domains to access tmpfs files.
// For tmpfs overlay on 2SI, Zygisk on lower Android versions and AVD scripts allow(["domain"], ["tmpfs"], ["file"], all);
allow(["init", "zygote", "shell"], ["tmpfs"], ["file"], all);
// Allow magiskinit daemon to handle mock selinuxfs // Allow magiskinit daemon to handle mock selinuxfs
allow(["kernel"], ["tmpfs"], ["fifo_file"], ["write"]); allow(["kernel"], ["tmpfs"], ["fifo_file"], ["write"]);

View File

@@ -271,6 +271,10 @@ bool sepol_impl::add_rule(const char *s, const char *t, const char *c, const cha
#define ioctl_func(x) (x & 0xFF) #define ioctl_func(x) (x & 0xFF)
void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, const Xperm &p, int effect) { void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, const Xperm &p, int effect) {
if (db->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) {
LOGW("policy version %u does not support ioctl extended permissions rules\n", db->policyvers);
return;
}
if (src == nullptr) { if (src == nullptr) {
for_each_attr(db->p_types.table, [&](type_datum_t *type) { for_each_attr(db->p_types.table, [&](type_datum_t *type) {
add_xperm_rule(type, tgt, cls, p, effect); add_xperm_rule(type, tgt, cls, p, effect);

View File

@@ -3,7 +3,6 @@ use std::io::stderr;
use std::{iter::Peekable, pin::Pin, vec::IntoIter}; use std::{iter::Peekable, pin::Pin, vec::IntoIter};
use base::{error, warn, FmtAdaptor}; use base::{error, warn, FmtAdaptor};
use crate::ffi::Xperm; use crate::ffi::Xperm;
use crate::sepolicy; use crate::sepolicy;
@@ -436,15 +435,16 @@ fn extract_token<'a>(s: &'a str, tokens: &mut Vec<Token<'a>>) {
fn tokenize_statement(statement: &str) -> Vec<Token> { fn tokenize_statement(statement: &str) -> Vec<Token> {
let mut tokens = Vec::new(); let mut tokens = Vec::new();
for s in statement.split_whitespace() { for s in statement.split_whitespace() {
if s.starts_with('#') {
break;
}
extract_token(s, &mut tokens); extract_token(s, &mut tokens);
} }
tokens tokens
} }
pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) { pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) {
let statement = statement.trim();
if statement.is_empty() || statement.starts_with('#') {
return;
}
let mut tokens = tokenize_statement(statement).into_iter().peekable(); let mut tokens = tokenize_statement(statement).into_iter().peekable();
let result = exec_statement(sepolicy, &mut tokens); let result = exec_statement(sepolicy, &mut tokens);
if let Err(e) = result { if let Err(e) = result {

View File

@@ -2,10 +2,14 @@
# Magisk app internal scripts # Magisk app internal scripts
################################## ##################################
# $1 = delay
# $2 = command
run_delay() { run_delay() {
(sleep $1; $2)& (sleep $1; $2)&
} }
# $1 = version string
# $2 = version code
env_check() { env_check() {
for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do
[ -f "$MAGISKBIN/$file" ] || return 1 [ -f "$MAGISKBIN/$file" ] || return 1
@@ -21,6 +25,8 @@ env_check() {
return 0 return 0
} }
# $1 = dir to copy
# $2 = destination (optional)
cp_readlink() { cp_readlink() {
if [ -z $2 ]; then if [ -z $2 ]; then
cd $1 cd $1
@@ -39,6 +45,7 @@ cp_readlink() {
cd / cd /
} }
# $1 = install dir
fix_env() { fix_env() {
# Cleanup and make dirs # Cleanup and make dirs
rm -rf $MAGISKBIN/* rm -rf $MAGISKBIN/*
@@ -49,6 +56,8 @@ fix_env() {
chown -R 0:0 $MAGISKBIN chown -R 0:0 $MAGISKBIN
} }
# $1 = install dir
# $2 = boot partition
direct_install() { direct_install() {
echo "- Flashing new boot image" echo "- Flashing new boot image"
flash_image $1/new-boot.img $2 flash_image $1/new-boot.img $2
@@ -70,6 +79,7 @@ direct_install() {
return 0 return 0
} }
# $1 = uninstaller zip
run_uninstaller() { run_uninstaller() {
rm -rf /dev/tmp rm -rf /dev/tmp
mkdir -p /dev/tmp/install mkdir -p /dev/tmp/install
@@ -77,24 +87,16 @@ run_uninstaller() {
INSTALLER=/dev/tmp/install sh /dev/tmp/install/assets/uninstaller.sh dummy 1 "$1" INSTALLER=/dev/tmp/install sh /dev/tmp/install/assets/uninstaller.sh dummy 1 "$1"
} }
# $1 = boot partition
restore_imgs() { restore_imgs() {
[ -z $SHA1 ] && return 1 local SHA1=$(grep_prop SHA1 $MAGISKTMP/.magisk/config)
local BACKUPDIR=/data/magisk_backup_$SHA1 local BACKUPDIR=/data/magisk_backup_$SHA1
[ -d $BACKUPDIR ] || return 1 [ -d $BACKUPDIR ] || return 1
get_flags
find_boot_image
for name in dtb dtbo; do
[ -f $BACKUPDIR/${name}.img.gz ] || continue
local IMAGE=$(find_block $name$SLOT)
[ -z $IMAGE ] && continue
flash_image $BACKUPDIR/${name}.img.gz $IMAGE
done
[ -f $BACKUPDIR/boot.img.gz ] || return 1 [ -f $BACKUPDIR/boot.img.gz ] || return 1
flash_image $BACKUPDIR/boot.img.gz $BOOTIMAGE flash_image $BACKUPDIR/boot.img.gz $1
} }
# $1 = path to bootctl executable
post_ota() { post_ota() {
cd /data/adb cd /data/adb
cp -f $1 bootctl cp -f $1 bootctl
@@ -131,6 +133,8 @@ EOF
cd / cd /
} }
# $1 = APK
# $2 = package name
adb_pm_install() { adb_pm_install() {
local tmp=/data/local/tmp/temp.apk local tmp=/data/local/tmp/temp.apk
cp -f "$1" $tmp cp -f "$1" $tmp
@@ -189,6 +193,15 @@ printvar() {
eval echo $1=\$$1 eval echo $1=\$$1
} }
run_action() {
local MODID="$1"
cd "/data/adb/modules/$MODID"
sh ./action.sh
local RES=$?
cd /
return $RES
}
########################## ##########################
# Non-root util_functions # Non-root util_functions
########################## ##########################
@@ -232,7 +245,6 @@ app_init() {
check_boot_ramdisk && RAMDISKEXIST=true check_boot_ramdisk && RAMDISKEXIST=true
get_flags >/dev/null get_flags >/dev/null
run_migrations >/dev/null run_migrations >/dev/null
SHA1=$(grep_prop SHA1 $MAGISKTMP/.magisk/config)
check_encryption check_encryption
# Dump variables # Dump variables

View File

@@ -71,13 +71,14 @@ export KEEPFORCEENCRYPT=true
echo "KEEPVERITY=$KEEPVERITY" > config echo "KEEPVERITY=$KEEPVERITY" > config
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
echo "PREINITDEVICE=$(./magisk --preinit-device)" >> config echo "PREINITDEVICE=$(./magisk --preinit-device)" >> config
# For API 28, we also patch advancedFeatures.ini to disable SAR # For API 28, we also manually disable SystemAsRoot
# Manually override skip_initramfs by setting RECOVERYMODE=true # Explicitly override skip_initramfs by setting RECOVERYMODE=true
[ $API = "28" ] && echo 'RECOVERYMODE=true' >> config [ $API = "28" ] && echo 'RECOVERYMODE=true' >> config
cat config cat config
./magiskboot compress=xz magisk magisk.xz ./magiskboot compress=xz magisk magisk.xz
./magiskboot compress=xz stub.apk stub.xz ./magiskboot compress=xz stub.apk stub.xz
./magiskboot compress=xz init-ld init-ld.xz
./magiskboot cpio ramdisk.cpio \ ./magiskboot cpio ramdisk.cpio \
"add 0750 init magiskinit" \ "add 0750 init magiskinit" \
@@ -85,12 +86,13 @@ cat config
"mkdir 0750 overlay.d/sbin" \ "mkdir 0750 overlay.d/sbin" \
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \ "add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
"add 0644 overlay.d/sbin/stub.xz stub.xz" \ "add 0644 overlay.d/sbin/stub.xz stub.xz" \
"add 0644 overlay.d/sbin/init-ld.xz init-ld.xz" \
"patch" \ "patch" \
"backup ramdisk.cpio.orig" \ "backup ramdisk.cpio.orig" \
"mkdir 000 .backup" \ "mkdir 000 .backup" \
"add 000 .backup/.magisk config" "add 000 .backup/.magisk config"
rm -f ramdisk.cpio.orig config magisk*.xz stub.xz rm -f ramdisk.cpio.orig config *.xz
if $IS_RAMDISK; then if $IS_RAMDISK; then
./magiskboot compress=gzip ramdisk.cpio "$OUTPUT_FILE" ./magiskboot compress=gzip ramdisk.cpio "$OUTPUT_FILE"
else else

Some files were not shown because too many files have changed in this diff Show More