diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 184968b..0000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: Build - -on: - push: - branches: - - master - workflow_dispatch: - -env: - MODULE_NAME: 'mountify' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - fetch-depth: 2 - - - name: Build webui - run: | - cd webui - npm ci - npm run build - - - name: Set variables - run: | - VERSION=$(jq -r .version update.json) - COMMIT_ID=$(git rev-parse --short HEAD) - echo "ZIP_NAME=${{ env.MODULE_NAME }}_${VERSION}-${COMMIT_ID}" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ env.ZIP_NAME }} - path: 'module' diff --git a/.github/workflows/gki-build-lkm.yaml b/.github/workflows/gki-build-lkm.yaml deleted file mode 100644 index 4a27ad5..0000000 --- a/.github/workflows/gki-build-lkm.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Build LKM for ALL GKI - -on: - workflow_dispatch: - -jobs: - build-lkm: - strategy: - matrix: - include: - - version: "android12-5.10" - os_patch_level: 2025-05 - - version: "android13-5.10" - os_patch_level: 2025-03 - - version: "android13-5.15" - os_patch_level: 2025-03 - - version: "android14-5.15" - os_patch_level: 2025-03 - - version: "android14-6.1" - os_patch_level: 2025-05 - - version: "android15-6.6" - os_patch_level: 2025-05 - - uses: ./.github/workflows/gki-kernel.yaml - with: - version: ${{ matrix.version }} - os_patch_level: ${{ matrix.os_patch_level }} - diff --git a/.github/workflows/gki-kernel.yaml b/.github/workflows/gki-kernel.yaml deleted file mode 100644 index 973f52a..0000000 --- a/.github/workflows/gki-kernel.yaml +++ /dev/null @@ -1,129 +0,0 @@ -name: Build nuke_ext4 LKM - -on: - workflow_call: - inputs: - version: - description: "GKI version (e.g. android14-6.1)" - required: true - type: string - os_patch_level: - description: "Patch level (e.g. 2025-10)" - required: true - type: string - - workflow_dispatch: - inputs: - version: - description: "GKI version (e.g. android14-6.1)" - required: true - type: string - os_patch_level: - description: "Patch level (e.g. 2025-10)" - required: true - type: string - -jobs: - build: - runs-on: ubuntu-latest - name: Build LKM for ${{ inputs.version }}.${{ inputs.sub_level }} - - steps: - - name: Maximize build space - uses: easimon/maximize-build-space@master - with: - root-reserve-mb: 8192 - temp-reserve-mb: 2048 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Install required packages - run: | - echo lol - sudo apt-get update - sudo apt-get install -y bc build-essential flex bison libssl-dev libelf-dev git python3 unzip wget cpio gcc-aarch64-linux-gnu llvm-15 - - - name: Clone AOSP GKI kernel - run: | - mkdir android-kernel && cd android-kernel - TAG="${{ inputs.version }}-${{ inputs.os_patch_level }}" - echo "Fetching GKI tag: ${TAG}" - # git clone --depth=1 https://github.com/aosp-mirror/kernel_common/ -b ${TAG} common - curl https://storage.googleapis.com/git-repo-downloads/repo > repo - chmod +x repo - ./repo init --depth=1 https://android.googlesource.com/kernel/manifest -b "common-${TAG}" - ./repo sync -c -j $(nproc) - - - name: Prepare GKI - working-directory: android-kernel - run: | - export ARCH=arm64 - export SUBARCH=arm64 - export CROSS_COMPILE=aarch64-linux-gnu- - export CC=clang - - pwd - - cd common - mv ../../nuke_ext4_lkm drivers/nuke_ext4_lkm - ls -lha drivers/nuke_ext4_lkm - - sed -i 's/endmenu//g' drivers/Kconfig - echo "source \"drivers/nuke_ext4_lkm/Kconfig\"" >> drivers/Kconfig - echo "endmenu" >> drivers/Kconfig - echo 'obj-y += nuke_ext4_lkm/' >> drivers/Makefile - - # stop this exports check - sed -i '/check_exports(mod)/d' scripts/mod/modpost.c - - # force exports of these, just like ksu - [ -f "android/abi_gki_aarch64" ] && echo " register_kprobe" >> android/abi_gki_aarch64 && echo " unregister_kprobe" >> android/abi_gki_aarch64 - - tail -n10 drivers/Kconfig - tail -n10 drivers/Makefile - - echo $PATH ; pwd - - cd ../ - ls -la - - # bazel build, android14-5.15, android14-6.1 use bazel - if [ ! -e build/build.sh ]; then - sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found" - if [ -e common/modules.bzl ]; then - sed -i 's/_COMMON_GKI_MODULES_LIST = \[/_COMMON_GKI_MODULES_LIST = \[ "drivers\/nuke_ext4_lkm\/nuke.ko",/g' common/modules.bzl - fi - else - TARGET_FILE="build/kernel/build.sh" - if [ ! -e "$TARGET_FILE" ]; then - TARGET_FILE="build/build.sh" - fi - sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' $TARGET_FILE || echo "No unknown symbol in $TARGET_FILE" - sed -i 's/if ! diff -u "\${KERNEL_DIR}\/\${MODULES_ORDER}" "\${OUT_DIR}\/modules\.order"; then/if false; then/g' $TARGET_FILE - sed -i 's@${ROOT_DIR}/build/abi/compare_to_symbol_list@echo@g' $TARGET_FILE - sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found" - fi - - if [ -e build/build.sh ]; then - LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="clang" - else - tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist - fi - - if [ -f ./dist/nuke.ko ]; then - mv ./dist/nuke.ko nuke.ko - else - mv out/${{ inputs.version }}/common/drivers/nuke_ext4_lkm/nuke.ko nuke.ko - fi - - - name: Upload nuke.ko - uses: actions/upload-artifact@v4 - with: - name: nuke_ext4-${{ inputs.version }}.${{ inputs.sub_level }} - path: android-kernel/nuke.ko - diff --git a/.github/workflows/ngki-build-lkm.yaml b/.github/workflows/ngki-build-lkm.yaml deleted file mode 100644 index e67810b..0000000 --- a/.github/workflows/ngki-build-lkm.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Build LKM for Non-GKI - -on: - workflow_dispatch: - -jobs: - build-lkm: - strategy: - matrix: - include: - - version: "android-4.14-stable" - - uses: ./.github/workflows/ngki-kernel.yaml - with: - version: ${{ matrix.version }} - diff --git a/.github/workflows/ngki-kernel.yaml b/.github/workflows/ngki-kernel.yaml deleted file mode 100644 index 21a5d58..0000000 --- a/.github/workflows/ngki-kernel.yaml +++ /dev/null @@ -1,90 +0,0 @@ -name: Build nuke_ext4 LKM (non-gki) - -on: - workflow_call: - inputs: - version: - description: "branch (e.g. android-4.14-stable)" - required: true - type: string - - workflow_dispatch: - inputs: - version: - description: "branch (e.g. android-4.14-stable)" - required: true - type: string - -jobs: - build: - runs-on: ubuntu-latest - name: Build LKM for ${{ inputs.version }}.${{ inputs.sub_level }} - - steps: - - name: Maximize build space - uses: easimon/maximize-build-space@master - with: - root-reserve-mb: 8192 - temp-reserve-mb: 2048 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Install required packages - run: | - echo lol - sudo apt-get update - sudo apt-get install -y bc build-essential flex bison libssl-dev libelf-dev git python3 unzip wget cpio gcc-aarch64-linux-gnu llvm-15 - - - name: Clone AOSP GKI kernel - run: | - TAG="${{ inputs.version }}" - echo "Fetching GKI tag: deprecated/${TAG}" - git clone --depth=1 https://github.com/aosp-mirror/kernel_common/ -b "deprecated/${TAG}" kernel - - - name: Prepare GKI - working-directory: kernel - run: | - export ARCH=arm64 - export SUBARCH=arm64 - export CROSS_COMPILE=aarch64-linux-gnu- - export CC="clang -Wno-error" - - pwd - - mv ../nuke_ext4_lkm drivers/nuke_ext4_lkm - ls -lha drivers/nuke_ext4_lkm - - sed -i 's/endmenu//g' drivers/Kconfig - echo "source \"drivers/nuke_ext4_lkm/Kconfig\"" >> drivers/Kconfig - echo "endmenu" >> drivers/Kconfig - echo 'obj-y += nuke_ext4_lkm/' >> drivers/Makefile - - # stop this exports check - sed -i '/check_exports(mod)/d' scripts/mod/modpost.c - - tail -n10 drivers/Kconfig - tail -n10 drivers/Makefile - - echo $PATH ; pwd - mkdir out - - [ -f arch/arm64/configs/cuttlefish_defconfig ] && cat arch/arm64/configs/cuttlefish_defconfig > out/.config - [ -f arch/arm64/configs/gki_defconfig ] && cat arch/arm64/configs/gki_defconfig > out/.config - - make O=out ARCH=arm64 olddefconfig - make -j$(nproc) ARCH=arm64 SUBARCH=arm64 O=out - - llvm-strip-15 -d out/drivers/nuke_ext4_lkm/nuke.ko - ls -la out/drivers/nuke_ext4_lkm - - - name: Upload nuke.ko - uses: actions/upload-artifact@v4 - with: - name: nuke_ext4-${{ inputs.version }} - path: kernel/out/drivers/nuke_ext4_lkm/nuke.ko - diff --git a/.gitignore b/.gitignore deleted file mode 100644 index dcbe5a6..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -module/webroot diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index b6babb5..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,19 +0,0 @@ -# Mountify -Globally mounted modules and whiteouts via OverlayFS. - -## Changelog -## 187 -- webui/js: modular append function -- webui/js: add moutnify prefix in local storage -- webui/js: fix config not saved -- scripts: account for non-tmpfs /mnt/vendor - -## 186 -- scripts: handle sepolicy for ksu pr 3019 -- scripts/post-fs-data: redo sparse sepolicy handling -- scripts/post-fs-data: fix ext4 image context (#25) -- scripts: fixup capability test -- scripts/service: remove log folder after boot complete - -### Full Changelog -- [Commit history](https://github.com/backslashxx/mountify/commits/master/) diff --git a/README.md b/README.md index 557fa38..70df0eb 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,11 @@ -# Mountify - -#### Globally mounted modules via OverlayFS. - -- acts as a KernelSU [metamodule](https://kernelsu.org/guide/metamodule.html) -- works on APatch and Magisk too -- **CONFIG_OVERLAY_FS=y** is required -- **CONFIG_TMPFS_XATTR=y** is highly encouraged -- tries to mimic an OEM mount, like /mnt/vendor/my_bigball -- for module devs, you can also use [this standalone script](https://github.com/backslashxx/mountify/tree/standalone-script) - -## Methodology -### tmpfs mode -#### - tmpfs backed -1. `touch /data/adb/modules/module_id/skip_mount` -2. copies contents of `/data/adb/modules/module_id` to `/mnt/vendor/fake_folder_name` -3. mirrors SELinux context of every file from `/data/adb/modules/module_id` to `/mnt/vendor/fake_folder_name` -4. loops 2 and 3 for all modules -5. overlays `/mnt/vendor/fake_folder_name/system/bin` to `/system/bin` and other folders - -### ext4 sparse mode -#### - ext4-sparse-on-tmpfs backed -1. `touch /data/adb/modules/module_id/skip_mount` -2. create an ext4 sparse image, mount it on `/mnt/vendor/fake_folder_name` -3. copies contents of `/data/adb/modules/module_id` to `/mnt/vendor/fake_folder_name` -4. mirrors SELinux context of every file from `/data/adb/modules/module_id` to `/mnt/vendor/fake_folder_name` -5. loops 3 and 4 for all modules -6. unmounts, resizes and remounts sparse image to `/mnt/vendor/fake_folder_name` -7. overlays `/mnt/vendor/fake_folder_name/system/bin` to `/system/bin` and other folders - -## Why? -- Magic mount drastically increases mount count, making detection possible (zimperium) -- OverlayFS mounting with ext4 image upperdir is detectable due to it creating device nodes on /proc/fs, while yes ext4 /data as overlay source is possible, this is rare nowadays. -- F2FS /data as overlay source fails with native casefolding (ovl_dentry_weird), so only sdcardfs users can use /data as overlay source. -- Frankly, I dont see a way to this module mounting situation, this shit is more of a shitty band-aid - -### but ext4 sparse mode creates ext4 nodes! -- this is added to accomodate something like GPU drivers -- this causes detections but YMMV. -- this is not my problem, this is a fallback, not the main recommendation. -- and yes this is basically how Official KernelSU used to do it. -- if you're on GKI 5.10+, theres an experimental LKM that nukes these nodes. -- if you're on KernelSU 22105+ this is automatically handled. - -## Usage -- user-friendly config editing is available on the WebUI -- otherwise you can modify /data/adb/mountify/config.sh - -### General -- by default, mountify mounts all modules with a system folder. `mountify_mounts=2` -- to mount specific modules only, edit config.sh, `mountify_mounts=1` then modify modules.txt to list modules you want mounted - -``` -module_id -Adreno_Gpu_Driver -DisplayFeatures -ViPER4Android-RE-Fork -mountify_whiteouts -``` -- `FAKE_MOUNT_NAME="mountify"` to set a custom fake folder name -- `mountify_stop_start=1` to restart android at service (needed for certain modules) - -#### tmpfs specific -- `test_decoy_mount=1` to enable testing for decoy mounts on tmpfs mode - -#### ext4 specific -- `use_ext4_sparse=1` to force using ext4 mode if your setup is tmpfs_xattr capable -- `spoof_sparse=1` to try spoof sparse mount as an android service -- `FAKE_APEX_NAME="com.android.mntservice"` to customize that android service spoofed name -- `sparse_size="2048"` to set your sparse size (in MB) to whatever you want -- `enable_lkm_nuke=1` to try load an experimental LKM. -- `lkm_filename="nuke.ko"` to define LKM's filename - -### Need Unmount? -- use either NeoZygisk, NoHello, ReZygisk, Zygisk Assistant -- if you use Zygisk Next, then set Denylist Policy to "Enforced" or "Unmount Only" -- then edit config.sh - - `MOUNT_DEVICE_NAME="APatch"` if you're on APatch - - `MOUNT_DEVICE_NAME="KSU"` if you're on KernelSU forks - - `MOUNT_DEVICE_NAME="magisk"` if you're on Magisk -- `mountify_custom_umount=0` modify this value to enable known in-kernel umount methods. - - NOTE: zygisk provider umount is still better, this is here as a second choice. - -#### I need mountify to skip mounting my module! -- this is easy, add `skip_mountify` to your module's folder. -- mountify checks this on /data/adb/modules/module_name -- `[ -f /data/adb/modules/module_name/skip_mountify ]` - -## Limitations / Recommendations -- fails with [De-Bloater](https://github.com/sunilpaulmathew/De-Bloater), as it [uses dummy text, NOT proper whiteouts](https://github.com/sunilpaulmathew/De-Bloater/blob/cadd523f0ad8208eab31e7db51f855b89ed56ffe/app/src/main/java/com/sunilpaulmathew/debloater/utils/Utils.java#L112) -- I recommend [System App Nuker](https://github.com/ChiseWaguri/systemapp_nuker/releases) instead. It uses proper whiteouts. - -## License -- module is on [The Unlicense](https://github.com/backslashxx/mountify/blob/master/LICENSE) -- LKM is on [GPLv2](https://github.com/backslashxx/mountify/blob/master/nuke_ext4_lkm/LICENSE) -- WebUI is on [MIT](https://github.com/backslashxx/mountify/blob/master/webui/LICENSE) - -## Support / Warranty -- None, none at all. I am handing you a sharp knife, it is not on me if you stab yourself with it. - -## Links -[Download](https://github.com/backslashxx/mountify/releases) - - +## standalone scripts +- tmpfs mode only! +- you can put this onto post-fs-data of modules that you want globally mounted. +- heavily commented, read them. +- do not put me as another author on your modules using this! + - this is on The Unlicensed, no attribution needed. + - I don't want to get blamed for module issues. + +### integration demo +- [ChiseWaguri/systemapp_nuker](https://github.com/ChiseWaguri/systemapp_nuker) +- [KOWX712/unlock-cn-gms](https://github.com/KOWX712/unlock-cn-gms) diff --git a/global_mount.sh b/global_mount.sh new file mode 100644 index 0000000..4b94906 --- /dev/null +++ b/global_mount.sh @@ -0,0 +1,185 @@ +#!/bin/sh +# global_mount.sh +# mountify standalone script +# you can put or execute this on post-fs-data.sh or service.sh of a module. +# testing for overlayfs and tmpfs_xattr is on test-sysreq.sh +# No warranty. +# No rights reserved. +# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. +PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH +MODDIR="${0%/*}" + +# you can mimic vendor mounts like, my_bigball, vendor_dklm, mi_ext +# whatever. use what you want. provided here is just an example +FAKE_MOUNT_NAME="mountify_1" + +# mount device name +# you can use APatch, KSU or magisk here to let a zygisk provider unmount +# otherwise, just use "overlay" as default +MOUNT_DEVICE_NAME="overlay" + +# you can also use random characters whatever, but this might be a bad meme +# as we are trying to mimic a vendor mount, but its here if you want +# uncomment to use +# FAKE_MOUNT_NAME="$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 10)" + +SUSFS_BIN=/data/adb/ksu/bin/ksu_susfs +KSUD_BIN=/data/adb/ksud +# kernel umount is not needed but you can tweak it here if you want to +# set to 0 to disable +# set to 1 for susfs4ksu +# set to 2 for ksud kernel umount +mountify_kernel_umount=0 + +# separate shit with lines +IFS=" +" + +# targets for specially handled mounts +targets="odm +product +system_ext +vendor +mi_ext +my_bigball +my_carrier +my_company +my_engineering +my_heytap +my_manifest +my_preload +my_product +my_region +my_reserve +my_stock" + +# functions + +# controlled depth ($targets fuckery) +controlled_depth() { + if [ -z "$1" ] || [ -z "$2" ]; then return ; fi + for DIR in $(ls -d $1/*/ | sed 's/.$//' ); do + busybox mount -t overlay -o "lowerdir=$(pwd)/$DIR:$2$DIR" "$MOUNT_DEVICE_NAME" "$2$DIR" + [ $mountify_kernel_umount = 1 ] && ${SUSFS_BIN} add_try_umount "$2$DIR" 1 > /dev/null 2>&1 + [ $mountify_kernel_umount = 2 ] && ${KSUD_BIN} kernel umount add "$2$DIR" --flags 2 > /dev/null 2>&1 + done +} + +# handle single depth (/system/bin, /system/etc, et. al) +single_depth() { + for DIR in $( ls -d */ | sed 's/.$//' | grep -vE "(odm|product|system_ext|vendor)$" 2>/dev/null ); do + busybox mount -t overlay -o "lowerdir=$(pwd)/$DIR:/system/$DIR" "$MOUNT_DEVICE_NAME" "/system/$DIR" + [ $mountify_kernel_umount = 1 ] && ${SUSFS_BIN} add_try_umount "/system/$DIR" 1 > /dev/null 2>&1 + [ $mountify_kernel_umount = 2 ] && ${KSUD_BIN} kernel umount add "/system/$DIR" --flags 2 > /dev/null 2>&1 + done +} + +# getfattr compat +if /system/bin/getfattr -d /system/bin > /dev/null 2>&1; then + getfattr() { /system/bin/getfattr "$@"; } +else + getfattr() { /system/bin/toybox getfattr "$@"; } +fi + +# routine start +echo "mountify/standalone: start!" >> /dev/kmsg + +# make sure $MODDIR/skip_mount exists! +# this way manager won't mount it +# as we handle the mounting ourselves +[ ! -f $MODDIR/skip_mount ] && touch $MODDIR/skip_mount +# mountify 131 added this +# this way mountify wont remount this module +[ ! -f $MODDIR/skip_mountify ] && touch $MODDIR/skip_mountify + +# this is a fast lookup for a writable dir +# these tends to be always available +[ -w /mnt ] && MNT_FOLDER=/mnt +[ -w /mnt/vendor ] && MNT_FOLDER=/mnt/vendor + +# folder hierarchy prep +# undo_handle_partition +# because ksu moves them e.g. MODDIR/system/product to MODDIR/product +# this undoes that +undo_handle_partition() { + partition_to_undo="$1" + if [ -L "$MODDIR/system/$partition_to_undo" ] && [ -d "$MODDIR/$partition_to_undo" ]; then + rm -f "$MODDIR/system/$partition_to_undo" + mv -f "$MODDIR/$partition_to_undo" "$MODDIR/system/$partition_to_undo" + fi +} + +undo_handle_partition vendor +undo_handle_partition product +undo_handle_partition system_ext +undo_handle_partition odm + +# make sure fake_mount name does not exist +if [ -d "$MNT_FOLDER/$FAKE_MOUNT_NAME" ]; then + echo "mountify/standalone: folder with name $FAKE_MOUNT_NAME already exists!" >> /dev/kmsg + exit 1 +fi + +# create our folder +mkdir -p "$MNT_FOLDER/$FAKE_MOUNT_NAME" + +# mount our own tmpfs +echo "mountify/standalone: mounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg +busybox mount -t tmpfs tmpfs "$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" + +# then we make sure its there +if [ ! -d "$MNT_FOLDER/$FAKE_MOUNT_NAME" ]; then + echo "standalone lol exit" + exit 1 +fi + +# create placeholder +touch "$MNT_FOLDER/$FAKE_MOUNT_NAME/placeholder" + +# our base directory on magic mount +BASE_DIR="$MODDIR/system" + +# copy over our files: follow symlinks, recursive, force. +echo "mountify/standalone: processing $MODDIR" >> /dev/kmsg +cp -Lrf "$BASE_DIR"/* "$MNT_FOLDER/$FAKE_MOUNT_NAME" + +# go inside +cd "$MNT_FOLDER/$FAKE_MOUNT_NAME" + +# here we mirror selinux context, if we dont, we get "u:object_r:tmpfs:s0" +for file in $( find -L $BASE_DIR | sed "s|$BASE_DIR||g" ) ; do + # echo "mountify_debug chcorn $BASE_DIR$file to $MNT_FOLDER/$FAKE_MOUNT_NAME$file" >> /dev/kmsg + busybox chcon --reference="$BASE_DIR$file" "$MNT_FOLDER/$FAKE_MOUNT_NAME$file" +done + +# catch opaque dirs, requires getfattr +for dir in $( find -L $BASE_DIR -type d ) ; do + if getfattr -d "$dir" | grep -q "trusted.overlay.opaque" ; then + # echo "mountify_debug: opaque dir $dir found!" >> /dev/kmsg + opaque_dir=$(echo "$dir" | sed "s|$BASE_DIR|.|") + busybox setfattr -n trusted.overlay.opaque -v y "$opaque_dir" + # echo "mountify_debug: replaced $opaque_dir!" >> /dev/kmsg + fi +done + +# now here we mount +# handle single depth +single_depth +# handle this stance when /product is a symlink to /system/product +for folder in $targets ; do + # reset cwd due to loop + cd "$MNT_FOLDER/$FAKE_MOUNT_NAME" + if [ -L "/$folder" ] && [ ! -L "/system/$folder" ]; then + # legacy, so we mount at /system + controlled_depth "$folder" "/system/" + else + # modern, so we mount at root + controlled_depth "$folder" "/" + fi +done + +# unmount the tmpfs we created +echo "mountify/standalone: unmounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg +busybox umount -l "$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" + +# EOF diff --git a/module/META-INF/com/google/android/update-binary b/module/META-INF/com/google/android/update-binary deleted file mode 100644 index c75b463..0000000 --- a/module/META-INF/com/google/android/update-binary +++ /dev/null @@ -1,31 +0,0 @@ -#!/sbin/sh - -################# -# Initialization -################# - -umask 022 - -# echo before loading util_functions -ui_print() { echo "$1"; } - -require_new_magisk() { - ui_print " Requires Magisk v20.4+! " - exit 1 -} - -######################### -# Load util_functions.sh -######################### - -OUTFD=$2 -ZIPFILE=$3 - -mount /data 2>/dev/null - -[ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk -. /data/adb/magisk/util_functions.sh -[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk - -install_module -exit 0 diff --git a/module/META-INF/com/google/android/updater-script b/module/META-INF/com/google/android/updater-script deleted file mode 100644 index 11d5c96..0000000 --- a/module/META-INF/com/google/android/updater-script +++ /dev/null @@ -1 +0,0 @@ -#MAGISK diff --git a/module/action.sh b/module/action.sh deleted file mode 100644 index c1829b9..0000000 --- a/module/action.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# action.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="/data/adb/modules/mountify" -PERSISTENT_DIR="/data/adb/mountify" -. $PERSISTENT_DIR/config.sh - -echo "[+] mountify" -echo "[+] extended status" -printf "\n\n" - -# check if fake alias exists, if fail use overlay -if ! grep "nodev" /proc/filesystems | grep -q "$FS_TYPE_ALIAS" > /dev/null 2>&1; then - FS_TYPE_ALIAS="overlay" -fi - -if [ -f "$MODDIR/mount_diff" ]; then - cat "$MODDIR/mount_diff" -else - echo "[!] no logs found!" -fi - -# ksu and apatch auto closes -# make it wait 20s so we can read -if [ -z "$MMRL" ] && [ -z "$KSU_NEXT" ] && { [ "$KSU" = "true" ] || [ "$APATCH" = "true" ]; }; then - sleep 20 -fi - -# EOF diff --git a/module/boot-completed.sh b/module/boot-completed.sh deleted file mode 100644 index 3d76f18..0000000 --- a/module/boot-completed.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# boot-completed.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="/data/adb/modules/mountify" -# read config -PERSISTENT_DIR="/data/adb/mountify" -. $PERSISTENT_DIR/config.sh - -# unused - -# EOF diff --git a/module/config.sh b/module/config.sh deleted file mode 100644 index b7a5c85..0000000 --- a/module/config.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -# config.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. - -# mountify config - -# module mounting config -# 0 to disable -# 1 for manual mode (this will mount modules found on modules.txt) -# 2 for auto mode (this will mount all modules with a system folder) -mountify_mounts=2 - -# fake mount name -# mount folder name -FAKE_MOUNT_NAME="mountify" - -# Test for decoy mounting. -# This is meant for tmpfs mode. -# 0 to disable -# 1 to enable -test_decoy_mount=0 - -# restart android at at service -# certain modules might need this -# this is a workaround for 'racey' modules such as bootanimations and gpu drivers -# if you do NOT have a problem, you do NOT need this. -# 0 to disable -# 1 to enable -mountify_stop_start=0 - -# customized overlayfs driver -# this is only useful if you patched your overlayfs to register another alias -# e.g. MODULE_ALIAS_FS("my_weird_overlay"); -FS_TYPE_ALIAS="overlay" - -# this one below is its device name -# you can put "KSU", "APatch" here so a zygisk provider can umount -# e.g. NeoZygisk, NoHello, ReZygisk, Shamiko, Zygisk Assistant, ZygiskNext-UM/DE -# otherwise leave default. this is if you need unmount. -MOUNT_DEVICE_NAME="overlay" - -# You can enable in-kernel umount methods here -# 0 = disable -# 1 = susfs4ksu -# 2 = ksud kernel umount (ksu 22106+) -# NOTE: if you have a zygisk provider, you do NOT need this -mountify_custom_umount=0 - -# WARNING! -# This disables mountify's safety checks. mostly for debugging and development purposes. -# 0 - disable -# 1 - enable -# YOU HAVE BEEN WARNED -mountify_expert_mode=0 - -# -# settings below are mostly for sparse mode users !!! -# - -# ext4 sparse mode override. -# For tmpfs xattr capable setups that prefers using an ext4 sparse image to mount. -# 0 - disable -# 1 - enable -use_ext4_sparse=0 - -# Spoof sparse as an apex mount. -# Goes well with a custom MOUNT_DEVICE_NAME. -# NOTE: when this is enabled, nuking is disabled. -# 0 to disable -# 1 to enable -spoof_sparse=0 - -# Customize spoofed apex mount name. -# While futile, this tries to make it look legit. -FAKE_APEX_NAME="com.android.mntservice" - -# Set a custom sparse size. -# Modify this to any unsigned number. -# - sparse size in MB -sparse_size="2048" - -# WARNING! -# Experimental feature. Don't expect 100% success rate. -# Loads a oneshot LKM that unregisters ext4 sysfs nodes. -# 0 - disable -# 1 - enable -# NOTE: on KernelSU 22105+ this is handled on ksud -enable_lkm_nuke=0 -lkm_filename="nuke.ko" - -# EOF diff --git a/module/customize.sh b/module/customize.sh deleted file mode 100644 index 1569d04..0000000 --- a/module/customize.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/sh -# customize.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH - -# warn adventurous people -WARNING_STRING="WARNING: this file is part of mountify's autoconfiguration! DO NOT DELETE." - -# some bullshit just to use clear -if [ "$MMRL" = "true" ] || { [ "$KSU" = "true" ] && [ "$KSU_VER_CODE" -ge 11998 ]; } || - { [ "$KSU_NEXT" = "true" ] && [ "$KSU_VER_CODE" -ge 12144 ]; } || - { [ "$APATCH" = "true" ] && [ "$APATCH_VER_CODE" -ge 11022 ]; }; then - clear - loops=20 - while [ $loops -gt 1 ]; do - for i in '[-]' '[/]' '[|]' '[\]'; do - echo "$i" - sleep 0.1 - clear - loops=$((loops - 1)) - done - done -else - # sleep a bit to make it look like something is happening!! - sleep 2 -fi - -# routine start -[ -w "/mnt" ] && MNT_FOLDER="/mnt" -# keep the (/mnt/vendor is mounted) check here! we dont want to write shit on it if its mounted! -[ -w "/mnt/vendor" ] && ! busybox grep -q " /mnt/vendor " "/proc/mounts" && MNT_FOLDER="/mnt/vendor" - -test_ext4_image() { - mkdir -p "$MNT_FOLDER/mountify-mount-test" - busybox dd if=/dev/zero of="$MNT_FOLDER/mountify-ext4-test" bs=1M count=0 seek=8 >/dev/null 2>&1 || ext4_fail=1 - /system/bin/mkfs.ext4 -O ^has_journal "$MNT_FOLDER/mountify-ext4-test" >/dev/null 2>&1 || ext4_fail=1 - - # https://github.com/tiann/KernelSU/pull/3019 - [ "$KSU" = "true" ] && busybox chcon "u:object_r:ksu_file:s0" "$MNT_FOLDER/mountify-ext4-test" - - busybox mount -o loop,rw "$MNT_FOLDER/mountify-ext4-test" "$MNT_FOLDER/mountify-mount-test" >/dev/null 2>&1 || ext4_fail=1 - busybox umount -l "$MNT_FOLDER/mountify-mount-test" || ext4_fail=1 - - # cleanup - rm -rf "$MNT_FOLDER/mountify-ext4-test" "$MNT_FOLDER/mountify-mount-test" - - if [ "$ext4_fail" = "1" ]; then - abort "[!] ext4 fallback mode test fail!" - fi -} - -echo "[+] mountify" -echo "[+] SysReq test" - -# test for overlayfs -if grep -q "overlay" /proc/filesystems > /dev/null 2>&1; then \ - echo "[+] CONFIG_OVERLAY_FS" - echo "[+] overlay found in /proc/filesystems" -else - abort "[!] CONFIG_OVERLAY_FS is required for this module!" -fi - -# test for tmpfs xattr - -testfile="$MNT_FOLDER/tmpfs_xattr_testfile" -rm "$testfile" > /dev/null 2>&1 -busybox mknod "$testfile" c 0 0 > /dev/null 2>&1 -if busybox setfattr -n trusted.overlay.whiteout -v y "$testfile" > /dev/null 2>&1 ; then - echo "[+] CONFIG_TMPFS_XATTR" - echo "[+] tmpfs extended attribute test passed" - rm "$testfile" > /dev/null 2>&1 -else - rm "$testfile" > /dev/null 2>&1 - echo "[!] CONFIG_TMPFS_XATTR fail!" - echo "[+] testing for ext4 sparse image fallback mode" - # check for tools - if [ -f "/system/bin/mkfs.ext4" ] && [ -f "/system/bin/resize2fs" ]; then - test_ext4_image - echo "$WARNING_STRING" > "$MODPATH/no_tmpfs_xattr" - echo "[+] ext4 sparse fallback mode enabled" - else - abort "[!] tools not found, bail out." - fi -fi - -# grab version code -module_prop="/data/adb/modules/mountify/module.prop" -if [ -f $module_prop ]; then - mountify_versionCode=$(grep versionCode $module_prop | sed 's/versionCode=//g' ) -else - mountify_versionCode=0 -fi - -PERSISTENT_DIR="/data/adb/mountify" -[ ! -d $PERSISTENT_DIR ] && mkdir -p $PERSISTENT_DIR - - -# full migration if 166+ -if [ "$mountify_versionCode" -lt 166 ]; then - echo "[!] using fresh config.sh" - cat "$MODPATH/config.sh" > "$PERSISTENT_DIR/config.sh" -fi - -configs="modules.txt whiteouts.txt config.sh" - -for file in $configs; do - if [ ! -f "$PERSISTENT_DIR/$file" ]; then - echo "[+] moving $file" - cat "$MODPATH/$file" > "$PERSISTENT_DIR/$file" - fi -done - -# give exec to whiteout_gen.sh -chmod +x "$MODPATH/whiteout_gen.sh" - -# warn on OverlayFS managers -# while this is supported (half-assed), this is not a recommended configuration -if { [ "$KSU" = true ] && [ ! "$KSU_MAGIC_MOUNT" = true ] && [ "$KSU_VER_CODE" -lt 22098 ]; } || { [ "$APATCH" = true ] && [ ! "$APATCH_BIND_MOUNT" = true ]; }; then - printf "\n\n" - echo "[!] ERROR: Root manager is on sparse-backed overlayfs!" - echo "[!] This setup can cause issues and is NOT recommended." - echo "[!] modify customize.sh to force installation!" - abort "[!] Installation aborted!" - # ^ just change abort to echo or something -fi - -SUSFS_BIN="/data/adb/ksu/bin/ksu_susfs" -SUSFS_VERSION="$( ${SUSFS_BIN} show version | head -n1 | sed 's/v//; s/\.//g' )" -if [ "$KSU" = true ] && [ -f ${SUSFS_BIN} ] && { [ "$SUSFS_VERSION" -eq 1510 ] || [ "$SUSFS_VERSION" -eq 1511 ]; }; then - printf "\n\n" - echo "[!] ERROR: Mountify causes conflicts with this susfs version." - echo "[!] This setup can cause issues and is NOT recommended." - echo "[!] modify customize.sh to force installation!" - abort "[!] Installation aborted!" - # ^ just change abort to echo or something -fi - -# ahemm -if [ -f "$PERSISTENT_DIR/explicit_I_want_symlink" ]; then - echo "[!] forcing symlink script as post-fs-data!" - cat "$MODPATH/symlink/mountify-symlink.sh" > "$MODPATH/post-fs-data.sh" -fi - -# workaround for awry versioning on KernelSU forks -# we cannot rely on just ksu vercode -if [ "$KSU" = true ] && [ ! "$KSU_MAGIC_MOUNT" = true ] && [ "$KSU_VER_CODE" -ge 22098 ] && - ( grep -q "metamodule=true" $MODPATH/module.prop >/dev/null 2>&1 || grep -q "metamodule=1" $MODPATH/module.prop >/dev/null 2>&1 ); then - echo "[+] mountify will be installed in metamodule mode!" - mv "$MODPATH/post-fs-data.sh" "$MODPATH/metamount.sh" -fi - -# since even mm ksud can have this feature, we check this and add a flag that we can check -if [ "$KSU" = true ] && /data/adb/ksud kernel 2>&1 | grep -q "nuke-ext4-sysfs" >/dev/null 2>&1; then - echo "$WARNING_STRING" > "$MODPATH/ksud_has_nuke_ext4" -fi - -rm -rf "$MODPATH/symlink" -rm "$MODPATH/modules.txt" -rm "$MODPATH/whiteouts.txt" -rm "$MODPATH/config.sh" - -# EOF diff --git a/module/lkm/list.txt b/module/lkm/list.txt deleted file mode 100644 index 9386bb5..0000000 --- a/module/lkm/list.txt +++ /dev/null @@ -1,7 +0,0 @@ -4d7390ae984793e4c2007ecf5dd42e8c234ed77b1fec58827d3267ee0c11d914 nuke-android12-5.10.ko -3e6132e8ef25179b54453a4f1a82f8fa6b0a700ab5c087ece6d44a66eb3e0dc9 nuke-android13-5.10.ko -4732345c12f40fb620f55c27db1fdde84ac139fd9a4624b2afe231434f7e2f44 nuke-android13-5.15.ko -6bd872d666b9c221798a76327bb5e96218d42c3c41ef6b560fe494fd7e0f751e nuke-android14-5.15.ko -e7d506c573adcdacbf600059f89413f127dfbb8441eb72680ce698d08bc4ff0d nuke-android14-6.1.ko -a96f6974a2d557c38ef0ca7ec00f46861ed629c47aa6a66d913d23d3f74ca182 nuke-android15-6.6.ko -57be3153e336a34c0bfad60bf75f61b1fba9212f3e4a48a9f84750b0d3f54438 nuke-android-4.14.ko diff --git a/module/lkm/nuke-android-4.14.ko b/module/lkm/nuke-android-4.14.ko deleted file mode 100644 index 6e67985..0000000 Binary files a/module/lkm/nuke-android-4.14.ko and /dev/null differ diff --git a/module/lkm/nuke-android12-5.10.ko b/module/lkm/nuke-android12-5.10.ko deleted file mode 100644 index f7f3b31..0000000 Binary files a/module/lkm/nuke-android12-5.10.ko and /dev/null differ diff --git a/module/lkm/nuke-android13-5.10.ko b/module/lkm/nuke-android13-5.10.ko deleted file mode 100644 index 61d664b..0000000 Binary files a/module/lkm/nuke-android13-5.10.ko and /dev/null differ diff --git a/module/lkm/nuke-android13-5.15.ko b/module/lkm/nuke-android13-5.15.ko deleted file mode 100644 index ca683ff..0000000 Binary files a/module/lkm/nuke-android13-5.15.ko and /dev/null differ diff --git a/module/lkm/nuke-android14-5.15.ko b/module/lkm/nuke-android14-5.15.ko deleted file mode 100755 index d0a45db..0000000 Binary files a/module/lkm/nuke-android14-5.15.ko and /dev/null differ diff --git a/module/lkm/nuke-android14-6.1.ko b/module/lkm/nuke-android14-6.1.ko deleted file mode 100755 index 4df9b09..0000000 Binary files a/module/lkm/nuke-android14-6.1.ko and /dev/null differ diff --git a/module/lkm/nuke-android15-6.6.ko b/module/lkm/nuke-android15-6.6.ko deleted file mode 100755 index 8b2b61e..0000000 Binary files a/module/lkm/nuke-android15-6.6.ko and /dev/null differ diff --git a/module/metainstall.sh b/module/metainstall.sh deleted file mode 100644 index a513546..0000000 --- a/module/metainstall.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -# metainstall.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. - -# so other modules can identify -# mind you mountify restores magic mount folder hierarchy! -export KSU_HAS_METAMODULE="true" -export KSU_METAMODULE="mountify" -export MOUNTIFY="true" - -# restore REPLACE -mark_replace() { - # REPLACE must be directory!!! - # https://docs.kernel.org/filesystems/overlayfs.html#whiteouts-and-opaque-directories - mkdir -p $1 2>/dev/null - setfattr -n trusted.overlay.opaque -v y $1 - chmod 644 $1 -} - -# we no-op handle_partition -# because ksu moves them e.g. MODDIR/system/product to MODDIR/product -# this way we can support normal hierarchy that ksu changes -handle_partition() { - echo 0 > /dev/null ; true -} - -# give symlink -# mountify does NOT need this but, some modules still assume -# access to these folders on $MODDIR root -mountify_handle_partition() { - partition="$1" - - if [ ! -d "$MODPATH/system/$partition" ]; then - return - fi - - if [ -L "/system/$partition" ] && [ -d "/$partition" ]; then - ui_print "- Handle partition /$partition" - ln -sf "./system/$partition" "$MODPATH/$partition" - fi -} - -# call install function, this is important! -install_module - -mountify_handle_partition system_ext -mountify_handle_partition vendor -mountify_handle_partition product -mountify_handle_partition odm - -# EOF - diff --git a/module/module.prop b/module/module.prop deleted file mode 100644 index 95641e0..0000000 --- a/module/module.prop +++ /dev/null @@ -1,8 +0,0 @@ -id=mountify -name=mountify -version=v1.8.7 -versionCode=187 -author=xx, KOWX712 -metamodule=true -description=Globally mounted modules via OverlayFS. -updateJson=https://raw.githubusercontent.com/backslashxx/mountify/master/update.json diff --git a/module/modules.txt b/module/modules.txt deleted file mode 100644 index 74bbb8f..0000000 --- a/module/modules.txt +++ /dev/null @@ -1,6 +0,0 @@ -Adreno_Gpu_Driver -weebu-addon -DisplayFeatures -fake_service -mountify_whiteouts - diff --git a/module/post-fs-data.sh b/module/post-fs-data.sh deleted file mode 100644 index 92eac87..0000000 --- a/module/post-fs-data.sh +++ /dev/null @@ -1,433 +0,0 @@ -#!/bin/sh -# post-fs-data.sh / metamount.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -# variables -MODDIR="/data/adb/modules/mountify" -# config -mountify_mounts=2 -FAKE_MOUNT_NAME="mountify" -MOUNT_DEVICE_NAME="overlay" -FS_TYPE_ALIAS="overlay" -use_ext4_sparse=0 -spoof_sparse=0 -FAKE_APEX_NAME="com.android.mntservice" -sparse_size="2048" -test_decoy_mount=0 -DECOY_MOUNT_FOLDER="/oem" -mountify_expert_mode=0 -enable_lkm_nuke=0 -lkm_filename="nuke.ko" -# read config -PERSISTENT_DIR="/data/adb/mountify" -. $PERSISTENT_DIR/config.sh -# exit if disabled -if [ $mountify_mounts = 0 ]; then - exit 0 -fi - -# set prefix -# this is to handle it properly on kernelsu's metamodule mode -# we move this as metamount.sh on customize -DMESG_PREFIX="mountify/post-fs-data" -if [ -f "$MODDIR/metamount.sh" ]; then - DMESG_PREFIX="mountify/metamount" -fi - -# single instance run -# on ksu's metamodule mode, it seems post-fs-data runs twice -MOUNTIFY_LOCK="/dev/mountify_single_instance" -if [ -f "$MOUNTIFY_LOCK" ]; then - echo "$DMESG_PREFIX: mountify already ran!" >> /dev/kmsg - exit 1 -fi -touch "$MOUNTIFY_LOCK" - -# add simple anti bootloop logic -BOOTCOUNT=0 -[ -f "$MODDIR/count.sh" ] && . "$MODDIR/count.sh" - -BOOTCOUNT=$(( BOOTCOUNT + 1)) - -if [ ! -f "$PERSISTENT_DIR/explicit_I_want_a_bootloop" ] && [ $BOOTCOUNT -gt 1 ]; then - touch $MODDIR/disable - rm "$MODDIR/count.sh" - string="description=anti-bootloop triggered. module disabled. enable to activate." - sed -i "s/^description=.*/$string/g" $MODDIR/module.prop - exit 1 -else - echo "BOOTCOUNT=1" > "$MODDIR/count.sh" -fi - -# grab start time -echo "$DMESG_PREFIX: start!" >> /dev/kmsg - -# find and create logging folder -[ -w "/mnt" ] && MNT_FOLDER="/mnt" -[ -w "/mnt/vendor" ] && MNT_FOLDER="/mnt/vendor" -LOG_FOLDER="/dev/mountify_logs" -mkdir -p "$LOG_FOLDER" -# log before -cat /proc/mounts > "$LOG_FOLDER/before" - -# module mount section -IFS=" -" -targets="odm -product -system_ext -vendor -apex -mi_ext -my_bigball -my_carrier -my_company -my_engineering -my_heytap -my_manifest -my_preload -my_product -my_region -my_reserve -my_stock -oem -optics -prism" - -decoy_folder_candidates="/oem -/second_stage_resources -/patch_hw -/postinstall -/system_dlkm -/oem_dlkm -/acct -" - -# check if fake alias exists, if fail use overlay -if ! grep "nodev" /proc/filesystems | grep -q "$FS_TYPE_ALIAS" > /dev/null 2>&1; then - FS_TYPE_ALIAS="overlay" -fi - -if [ "$test_decoy_mount" = "1" ] && [ ! -f "$MODDIR/no_tmpfs_xattr" ]; then - # test for decoy mount - # it needs to be a blank folder - for dir in $decoy_folder_candidates; do - if [ -d "$dir" ] && [ "$(ls -A "$dir" 2>/dev/null | wc -l)" -eq 0 ]; then - DECOY_MOUNT_FOLDER="$dir" - echo "$DMESG_PREFIX: decoy folder $DECOY_MOUNT_FOLDER" >> /dev/kmsg - decoy_mount_enabled="1" - break - fi - done -fi - -# functions - -# controlled depth ($targets fuckery) -controlled_depth() { - if [ -z "$1" ] || [ -z "$2" ]; then return ; fi - mount_success=0 - for DIR in $(ls -d $1/*/ | sed 's/.$//' ); do - if [ "$decoy_mount_enabled" = "1" ] && [ -w "$DECOY_MOUNT_FOLDER" ]; then - mkdir -p "$DECOY_MOUNT_FOLDER/$2$DIR" - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$DECOY_MOUNT_FOLDER$2$DIR:$(pwd)/$DIR:$2$DIR" "$MOUNT_DEVICE_NAME" "$2$DIR" && mount_success=1 - else - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$(pwd)/$DIR:$2$DIR" "$MOUNT_DEVICE_NAME" "$2$DIR" && mount_success=1 - fi - [ "$mount_success" = 1 ] && echo "$2$DIR" >> "$LOG_FOLDER/mountify_mount_list" - done -} - -# handle single depth (/system/bin, /system/etc, et. al) -single_depth() { - mount_success=0 - for DIR in $( ls -d */ | sed 's/.$//' | grep -vE "^(odm|product|system_ext|vendor)$" 2>/dev/null ); do - if [ "$decoy_mount_enabled" = "1" ] && [ -w "$DECOY_MOUNT_FOLDER" ]; then - mkdir -p "$DECOY_MOUNT_FOLDER/system/$DIR" - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$DECOY_MOUNT_FOLDER/system/$DIR:$(pwd)/$DIR:/system/$DIR" "$MOUNT_DEVICE_NAME" "/system/$DIR" && mount_success=1 - else - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$(pwd)/$DIR:/system/$DIR" "$MOUNT_DEVICE_NAME" "/system/$DIR" && mount_success=1 - fi - [ "$mount_success" = 1 ] && echo "/system/$DIR" >> "$LOG_FOLDER/mountify_mount_list" - done -} - -# handle getfattr, it is sometimes not symlinked on /system/bin yet toybox has it -# I fucking hope magisk's busybox ships it sometime -if /system/bin/getfattr -d /system/bin > /dev/null 2>&1; then - getfattr() { /system/bin/getfattr "$@"; } -else - getfattr() { /system/bin/toybox getfattr "$@"; } -fi - -mountify_copy() { - # return for missing args - if [ -z "$1" ]; then - # echo "$(basename "$0" ) module_id fake_folder_name" - echo "$DMESG_PREFIX: missing arguments, fuck off" >> /dev/kmsg - return - fi - - MODULE_ID="$1" - - # return for certain modules - # De-bloater uses dummy text, not whiteouts, which does not really work - if [ "$MODULE_ID" = "De-bloater" ]; then - echo "$DMESG_PREFIX: module with name $MODULE_ID is blacklisted" >> /dev/kmsg - return - fi - - # test for various stuff - # you dont want to global mount hosts file - TARGET_DIR="/data/adb/modules/$MODULE_ID" - if [ ! -d "$TARGET_DIR/system" ] || [ -f "$TARGET_DIR/disable" ] || [ -f "$TARGET_DIR/remove" ] || - [ -f "$TARGET_DIR/skip_mountify" ] || [ -f "$TARGET_DIR/system/etc/hosts" ]; then - echo "$DMESG_PREFIX: module with name $MODULE_ID not meant to be mounted" >> /dev/kmsg - return - fi - - # lets just add another clause for ksu metamodule mode - # this way its easier to maintain - # on metamodule mode, we can actually respect skip_mount - if [ -f "$MODDIR/metamount.sh" ] && [ -f "$TARGET_DIR/skip_mount" ]; then - echo "$DMESG_PREFIX: module with name $MODULE_ID has skip_mount" >> /dev/kmsg - return - fi - - echo "$DMESG_PREFIX: processing $MODULE_ID" >> /dev/kmsg - - # skip_mount is not needed on .nomount MKSU - 5ec1cff/KernelSU/commit/76bfccd - # skip_mount is also not needed for litemode APatch - bmax121/APatch/commit/7760519 - if { [ "$KSU_MAGIC_MOUNT" = "true" ] && [ -f /data/adb/ksu/.nomount ]; } || - { [ "$APATCH_BIND_MOUNT" = "true" ] && [ -f /data/adb/.litemode_enable ]; } || - [ -f "$MODDIR/metamount.sh" ]; then - - # ^ HACK: the metamodule check is here just so it wont create a skip_mount flag. - # we do NOT have 'goto' in shell so we to keep it this way. - # since we already check it above, it should NOT be here! - - # we can delete skip_mount if nomount / litemode - [ -f "$TARGET_DIR/skip_mount" ] && rm "$TARGET_DIR/skip_mount" - [ -f "$PERSISTENT_DIR/skipped_modules" ] && rm "$PERSISTENT_DIR/skipped_modules" - else - if [ ! -f "$TARGET_DIR/skip_mount" ]; then - touch "$TARGET_DIR/skip_mount" - # log modules that got skip_mounted - # we can likely clean those at uninstall - echo "$MODULE_ID" >> $PERSISTENT_DIR/skipped_modules - fi - fi - - # we can copy over contents of system folder only - BASE_DIR="/data/adb/modules/$MODULE_ID/system" - - # copy over our files: follow symlinks, recursive, force. - cd "$MNT_FOLDER" && cp -Lrf "$BASE_DIR"/* "$FAKE_MOUNT_NAME" - - # go inside - cd "$MNT_FOLDER/$FAKE_MOUNT_NAME" - - # make sure to mirror selinux context - # else we get "u:object_r:tmpfs:s0" - for file in $( find -L $BASE_DIR | sed "s|$BASE_DIR||g" ) ; do - # echo "mountify_debug chcorn $BASE_DIR$file to $MNT_FOLDER/$FAKE_MOUNT_NAME$file" >> /dev/kmsg - busybox chcon --reference="$BASE_DIR$file" "$MNT_FOLDER/$FAKE_MOUNT_NAME$file" - done - - # catch opaque dirs, requires getfattr - for dir in $( find -L $BASE_DIR -type d ) ; do - if getfattr -d "$dir" | grep -q "trusted.overlay.opaque" ; then - # echo "mountify_debug: opaque dir $dir found!" >> /dev/kmsg - opaque_dir=$(echo "$dir" | sed "s|$BASE_DIR|.|") - busybox setfattr -n trusted.overlay.opaque -v y "$opaque_dir" - # echo "mountify_debug: replaced $opaque_dir!" >> /dev/kmsg - fi - done - - # if it reached here, module probably copied, log it - echo "$MODULE_ID" >> "$LOG_FOLDER/modules" -} - -# prevent this fuckup since on expert mode this isnt checked -if [ "$FAKE_MOUNT_NAME" = "persist" ]; then - echo "$DMESG_PREFIX: folder name named $FAKE_MOUNT_NAME is not allowed!" >> /dev/kmsg - exit 1 -fi - -# make sure its not there -if [ ! "$mountify_expert_mode" = 1 ] && [ -d "$MNT_FOLDER/$FAKE_MOUNT_NAME" ]; then - # anti fuckup - # this is important as someone might actually use legit folder names - # and same shit exists on MNT_FOLDER, prevent this issue. - echo "$DMESG_PREFIX: exiting since fake folder name $FAKE_MOUNT_NAME already exists!" >> /dev/kmsg - exit 1 -fi - -# lets also mount our own /mnt folder -# so hierarchy becomes -# stage1 /mnt or /mnt/vendor always tmpfs -# stage2 /mnt/fake_folder_name or /mnt/vendor/fake_folder_name is either tmpfs or ext4 -if [ -d "$MNT_FOLDER" ]; then - echo "$DMESG_PREFIX: stage1: mounting $(realpath "$MNT_FOLDER")" >> /dev/kmsg - - # mount and test, if it fails fuck it, we bail - if ! busybox mount -t tmpfs tmpfs "$(realpath "$MNT_FOLDER")"; then - echo "$DMESG_PREFIX: mounting $MNT_FOLDER fail! bail out!" >> /dev/kmsg - exit 1 - fi - -fi - -# create it -mkdir -p "$MNT_FOLDER/$FAKE_MOUNT_NAME" -if [ ! -f "$MODDIR/no_tmpfs_xattr" ] && [ ! "$use_ext4_sparse" = "1" ]; then - echo "$DMESG_PREFIX: stage2/tmpfs: mounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg - busybox mount -t tmpfs tmpfs "$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" -fi -touch "$MNT_FOLDER/$FAKE_MOUNT_NAME/placeholder" - -# then make sure its there -if [ ! -d "$MNT_FOLDER/$FAKE_MOUNT_NAME" ]; then - # weird if it happens - echo "$DMESG_PREFIX: failed creating folder with fake_folder_name $FAKE_MOUNT_NAME !" >> /dev/kmsg - exit 1 -fi - -if [ "$decoy_mount_enabled" = "1" ] && [ -d "$DECOY_MOUNT_FOLDER" ] && [ "$(ls -A "$DECOY_MOUNT_FOLDER" 2>/dev/null | wc -l)" -eq 0 ]; then - echo "$DMESG_PREFIX: mounting $DECOY_MOUNT_FOLDER" >> /dev/kmsg - mount -t tmpfs tmpfs "$DECOY_MOUNT_FOLDER" -fi - -if [ -f "$MODDIR/no_tmpfs_xattr" ] || [ "$use_ext4_sparse" = "1" ]; then - # create 2GB sparse - busybox dd if=/dev/zero of="$MNT_FOLDER/mountify-ext4" bs=1M count=0 seek="$sparse_size" - /system/bin/mkfs.ext4 -O ^has_journal "$MNT_FOLDER/mountify-ext4" - - # https://github.com/tiann/KernelSU/pull/3019 - # this way only sparse mode on ksu gets the rule - [ "$KSU" = "true" ] && busybox chcon "u:object_r:ksu_file:s0" "$MNT_FOLDER/mountify-ext4" - - echo "$DMESG_PREFIX: stage2/ext4: mounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg - busybox mount -o loop,rw "$MNT_FOLDER/mountify-ext4" "$MNT_FOLDER/$FAKE_MOUNT_NAME" -fi - -# if manual mode and modules.txt has contents -if [ $mountify_mounts = 1 ] && grep -qv "#" "$PERSISTENT_DIR/modules.txt" >/dev/null 2>&1 ; then - # manual mode - for line in $( sed '/#/d' "$PERSISTENT_DIR/modules.txt" ); do - module_id=$( echo $line | awk {'print $1'} ) - mountify_copy "$module_id" - done -else - # auto mode - for module in /data/adb/modules/*/system; do - module_id="$(echo $module | cut -d / -f 5 )" - mountify_copy "$module_id" - done -fi - -if [ -f "$MODDIR/no_tmpfs_xattr" ] || [ "$use_ext4_sparse" = "1" ]; then - # unmount, sync and remount ext4 image as ro - busybox umount -l "$MNT_FOLDER/$FAKE_MOUNT_NAME" - busybox sync - /system/bin/resize2fs -M "$MNT_FOLDER/mountify-ext4" - - echo "$DMESG_PREFIX: stage2/ext4: remounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg - - if [ "$spoof_sparse" = "1" ] && [ -w "/apex" ] && [ ! -e "/apex/$FAKE_APEX_NAME" ]; then - # here we copy how android does it - mkdir -p "/apex/$FAKE_APEX_NAME@1" - busybox mount -o loop,ro,dirsync,seclabel,nodev,noatime "$MNT_FOLDER/mountify-ext4" "/apex/$FAKE_APEX_NAME@1" - mkdir -p "/apex/$FAKE_APEX_NAME" # then prepare the original for it - busybox mount --bind,ro "/apex/$FAKE_APEX_NAME@1" "/apex/$FAKE_APEX_NAME" - rm -rf "$MNT_FOLDER/$FAKE_MOUNT_NAME" - busybox ln -sf "/apex/$FAKE_APEX_NAME" "$MNT_FOLDER/$FAKE_MOUNT_NAME" - else - busybox mount -o loop,ro "$MNT_FOLDER/mountify-ext4" "$MNT_FOLDER/$FAKE_MOUNT_NAME" - fi - - # or another bind mount ?? this creates another mount, but hey, it werks - # busybox mount --bind,ro "/apex/com.android.mntservice" "$MNT_FOLDER/$FAKE_MOUNT_NAME" - -fi - -# mount -cd "$MNT_FOLDER/$FAKE_MOUNT_NAME" -single_depth -# handle this stance when /product is a symlink to /system/product -for folder in $targets ; do - # reset cwd due to loop - cd "$MNT_FOLDER/$FAKE_MOUNT_NAME" - if [ -L "/$folder" ] && [ ! -L "/system/$folder" ]; then - # legacy, so we mount at /system - controlled_depth "$folder" "/system/" - else - # modern, so we mount at root - controlled_depth "$folder" "/" - fi -done - -if [ "$decoy_mount_enabled" = "1" ] && [ -d "$DECOY_MOUNT_FOLDER" ]; then - echo "$DMESG_PREFIX: unmounting $DECOY_MOUNT_FOLDER" >> /dev/kmsg - busybox umount -l "$DECOY_MOUNT_FOLDER" -fi - -# insmod compat - system provided insmod most of the times is betterer -if command -v /system/bin/insmod > /dev/null 2>&1; then - insmod() { /system/bin/insmod "$@"; } -else - insmod() { busybox insmod "$@"; } -fi - -# nuke ext4 sysfs -# this unregisters an ext4 node used on ext4 mode (duh) -# this way theres no nodes are lingering on /proc/fs -if [ ! -f "$MODDIR/ksud_has_nuke_ext4" ] && [ $enable_lkm_nuke = 1 ] && [ -f "$MODDIR/lkm/$lkm_filename" ] && - { [ -f "$MODDIR/no_tmpfs_xattr" ] || [ "$use_ext4_sparse" = "1" ]; } && - [ "$spoof_sparse" = "0" ]; then - - mnt="$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" - kptr_set=$(cat /proc/sys/kernel/kptr_restrict) - echo 1 > /proc/sys/kernel/kptr_restrict - ptr_address=$(grep " ext4_unregister_sysfs$" /proc/kallsyms | awk {'print "0x"$1'}) - echo "$DMESG_PREFIX: stage2/ext4: loading LKM with mount_point=$mnt symaddr=$ptr_address" >> /dev/kmsg - insmod "$MODDIR/lkm/$lkm_filename" mount_point="$mnt" symaddr="$ptr_address" > /dev/null 2>&1 - echo $kptr_set > /proc/sys/kernel/kptr_restrict - -fi - -# ksud kernel nuke-ext4-sysfs -# uses official ksud interface -if [ -f "$MODDIR/ksud_has_nuke_ext4" ] && [ "$spoof_sparse" = "0" ] && - { [ -f "$MODDIR/no_tmpfs_xattr" ] || [ "$use_ext4_sparse" = "1" ]; }; then - - mnt="$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" - echo "$DMESG_PREFIX: stage2/ext4: ksud kernel nuke-ext4-sysfs $mnt" >> /dev/kmsg - /data/adb/ksud kernel nuke-ext4-sysfs "$mnt" - -fi - -# we can commonize umount instead -# its the same for tmpfs and ext4 anyway -if [ "$spoof_sparse" = "0" ]; then - echo "$DMESG_PREFIX: stage2: unmounting $(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" >> /dev/kmsg - busybox umount -l "$(realpath "$MNT_FOLDER/$FAKE_MOUNT_NAME")" -fi - -# delete the sparse -if [ -f "$MODDIR/no_tmpfs_xattr" ] || [ "$use_ext4_sparse" = "1" ]; then - [ -f "$MNT_FOLDER/mountify-ext4" ] && rm "$MNT_FOLDER/mountify-ext4" -fi - -# unmount stage1 -echo "$DMESG_PREFIX: stage1: unmounting $(realpath "$MNT_FOLDER")" >> /dev/kmsg -busybox umount -l "$MNT_FOLDER" - -# log after -cat /proc/mounts > "$LOG_FOLDER/after" -echo "$DMESG_PREFIX: finished!" >> /dev/kmsg - -# EOF diff --git a/module/service.sh b/module/service.sh deleted file mode 100644 index ef2995e..0000000 --- a/module/service.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/sh -# service.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="/data/adb/modules/mountify" -mountify_stop_start=0 -# read config -PERSISTENT_DIR="/data/adb/mountify" -. $PERSISTENT_DIR/config.sh - -# stop; start -# restart android at service -# this is a bit of a workaround for "racey" modules. -# I do NOT know how to explain it, but it is like on some modules -# mounting is LATE. this happens especially with certain gpu drivers -# and even as simple as bootanimation modules. -# if you do NOT have the issue, you do NOT need this. -# this is disabled by default on config.sh -if [ $mountify_stop_start = 1 ]; then - stop; start -fi - -# handle kernel umount -LOG_FOLDER="/dev/mountify_logs" - -# requires susfs add_try_umount -do_susfs_umount() { -for mount in $(cat "$LOG_FOLDER/mountify_mount_list") ; do - # workaround for oplus devices - if echo "$mount" | grep -q "/my_" ; then - /data/adb/ksu/bin/ksu_susfs add_try_umount "/mnt/vendor$mount" 1 - fi - /data/adb/ksu/bin/ksu_susfs add_try_umount "$mount" 1 -done -} - -# requires ksu 22105+ -do_ksud_umount() { -for mount in $(cat "$LOG_FOLDER/mountify_mount_list"); do - /data/adb/ksud kernel umount add $mount --flags 2 > /dev/null 2>&1 - # now inform ksud so that the kernel unlocks the feature - /data/adb/ksud kernel notify-module-mounted >/dev/null 2>&1 -done -} - -if [ "$mountify_custom_umount" = 1 ]; then - do_susfs_umount -fi - -if [ "$mountify_custom_umount" = 2 ]; then - do_ksud_umount -fi - -# cleanup -# prep logs for status -busybox diff "$LOG_FOLDER/before" "$LOG_FOLDER/after" | grep " $FS_TYPE_ALIAS " > "$MODDIR/mount_diff" - -# handle operating mode -case $mountify_mounts in - 1) mode="manual 🤓" ;; - 2) mode="auto 🤖" ;; - *) mode="disabled 💀" ;; # ?? -esac - -if [ -f "$LOG_FOLDER/mountify_symlink" ]; then - mode="$mode | ???: symlink 🔗" -elif [ "$use_ext4_sparse" = "1" ] || [ -f "$MODDIR/no_tmpfs_xattr" ]; then - mode="$mode | fstype: ext4 🛠️" -else - mode="$mode | fstype: tmpfs 🦾" -fi - -# display if on nomount/litemode -if [ "$KSU_MAGIC_MOUNT" = "true" ] && [ -f /data/adb/ksu/.nomount ]; then - mode="$mode | nomount: ✅" -fi -if [ "$APATCH_BIND_MOUNT" = "true" ] && [ -f /data/adb/.litemode_enable ]; then - mode="$mode | litemode: ✅" -fi - -# update description accrdingly -string="description=mode: $mode | no modules mounted" -if [ -f $LOG_FOLDER/modules ]; then - string="description=mode: $mode | modules: $( for module in $(cat "$LOG_FOLDER/modules" ) ; do printf "$module " ; done ) " -fi -sed -i "s/^description=.*/$string/g" $MODDIR/module.prop - -# wait for boot-complete -until [ "$(getprop sys.boot_completed)" = "1" ]; do - sleep 1 -done - -# reset bootcount (anti-bootloop routine) -echo "BOOTCOUNT=0" > "$MODDIR/count.sh" - -if [ ! "$APATCH" = true ] && [ ! "$KSU" = true ]; then - sh "$MODDIR/boot-completed.sh" & -fi - -# remove mountify single instance lock -MOUNTIFY_LOCK="/dev/mountify_single_instance" -if [ -f "$MOUNTIFY_LOCK" ]; then - echo "mountify/service: lifting single instance lock" >> /dev/kmsg - rm "$MOUNTIFY_LOCK" -fi - -# clean log folder -[ -d "$LOG_FOLDER" ] && rm -rf "$LOG_FOLDER" - -# EOF diff --git a/module/symlink/mountify-symlink.sh b/module/symlink/mountify-symlink.sh deleted file mode 100644 index 13a68cf..0000000 --- a/module/symlink/mountify-symlink.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/bin/sh -# post-fs-data.sh -# this script is part of mountify (symlink ver) -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="/data/adb/modules/mountify" - -# config -mountify_mounts=2 -mountify_expert_mode=0 -MOUNT_DEVICE_NAME="overlay" -FS_TYPE_ALIAS="overlay" -FAKE_MOUNT_NAME="mountify" -PERSISTENT_DIR="/data/adb/mountify" -# read config -. $PERSISTENT_DIR/config.sh -# exit if disabled -if [ $mountify_mounts = 0 ]; then - exit 0 -fi - -# add simple anti bootloop logic -BOOTCOUNT=0 -[ -f "$MODDIR/count.sh" ] && . "$MODDIR/count.sh" - -BOOTCOUNT=$(( BOOTCOUNT + 1)) - -if [ $BOOTCOUNT -gt 1 ]; then - touch $MODDIR/disable - rm "$MODDIR/count.sh" - string="description=anti-bootloop triggered. module disabled. enable to activate." - sed -i "s/^description=.*/$string/g" $MODDIR/module.prop - exit 1 -else - echo "BOOTCOUNT=1" > "$MODDIR/count.sh" -fi - -# this is a fast lookup for a writable dir -# these tends to be always available -[ -w "/mnt" ] && MNT_FOLDER="/mnt" -[ -w "/mnt/vendor" ] && MNT_FOLDER="/mnt/vendor" -LOG_FOLDER="/dev/mountify_logs" -mkdir -p "$LOG_FOLDER" -# log before -cat /proc/mounts > "$LOG_FOLDER/before" - -IFS=" -" -targets="odm -product -system_ext -vendor -apex -mi_ext -my_bigball -my_carrier -my_company -my_engineering -my_heytap -my_manifest -my_preload -my_product -my_region -my_reserve -my_stock -oem -optics -prism" - -# set prefix -# this is to handle it properly on kernelsu's metamodule mode -# we move this as metamount.sh on customize -DMESG_PREFIX="mountify/post-fs-data" -if [ -f "$MODDIR/metamount.sh" ]; then - DMESG_PREFIX="mountify/metamount" -fi - -# check if fake alias exists, if fail use overlay -if ! grep "nodev" /proc/filesystems | grep -q "$FS_TYPE_ALIAS" > /dev/null 2>&1; then - FS_TYPE_ALIAS="overlay" -fi - -# functions -controlled_depth() { - if [ -z "$1" ] || [ -z "$2" ]; then return ; fi - mount_success=0 - for DIR in $(ls -d $1/*/ | sed 's/.$//' ); do - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$(pwd)/$DIR:$2$DIR" "$MOUNT_DEVICE_NAME" "$2$DIR" && mount_success=1 - done - [ "$mount_success" = 1 ] && echo "$2$DIR" >> "$LOG_FOLDER/mountify_mount_list" -} - -single_depth() { - mount_success=0 - for DIR in $( ls -d */ | sed 's/.$//' | grep -vE "^(odm|product|system_ext|vendor)$" 2>/dev/null ); do - busybox mount -t "$FS_TYPE_ALIAS" -o "lowerdir=$(pwd)/$DIR:/system/$DIR" "$MOUNT_DEVICE_NAME" "/system/$DIR" && mount_success=1 - done - [ "$mount_success" = 1 ] && echo "/system/$DIR" >> "$LOG_FOLDER/mountify_mount_list" -} - -mountify_symlink() { -if [ -z "$1" ] || [ -z "$2" ]; then - echo "$DMESG_PREFIX: missing arguments, fuck off" >> /dev/kmsg - return -fi - -TARGET_DIR="/data/adb/modules/$1" - -if [ -f "$TARGET_DIR/disable" ] || [ -f "$TARGET_DIR/remove" ] || [ ! -d "$TARGET_DIR/system" ] || - [ -f "$TARGET_DIR/skip_mountify" ] || [ -f "$TARGET_DIR/system/etc/hosts" ]; then - echo "$DMESG_PREFIX: $1 not meant to be mounted" >> /dev/kmsg - return -fi - -if [ -f "$TARGET_DIR/skip_mount" ] && [ -f "$MODDIR/metamount.sh" ]; then - echo "$DMESG_PREFIX: $1 has skip_mount" >> /dev/kmsg - return -fi - -echo "$DMESG_PREFIX: processing $1" >> /dev/kmsg - -# skip_mount is not needed on .nomount MKSU - 5ec1cff/KernelSU/commit/76bfccd -# skip_mount is also not needed for litemode APatch - bmax121/APatch/commit/7760519 -if { [ "$KSU_MAGIC_MOUNT" = "true" ] && [ -f /data/adb/ksu/.nomount ]; } || - { [ "$APATCH_BIND_MOUNT" = "true" ] && [ -f /data/adb/.litemode_enable ]; } || - [ -f "$MODDIR/metamount.sh" ]; then - - # ^ HACK: the metamodule check is here just so it wont create a skip_mount flag. - # we do NOT have 'goto' in shell so we to keep it this way. - # since we already check it above, it should NOT be here! - - [ -f "$TARGET_DIR/skip_mount" ] && rm "$TARGET_DIR/skip_mount" - [ -f "$MODDIR/skipped_modules" ] && rm "$MODDIR/skipped_modules" -else - if [ ! -f "$TARGET_DIR/skip_mount" ]; then - touch "$TARGET_DIR/skip_mount" - # log modules that got skip_mounted - # we can likely clean those at uninstall - echo "$1" >> $MODDIR/skipped_modules - fi -fi - -MODULE_BASEDIR="$TARGET_DIR/system" -SUBFOLDER_NAME="$2" - -# here we create the symlink -busybox ln -sf "$MODULE_BASEDIR" "$MNT_FOLDER/$FAKE_MOUNT_NAME/$SUBFOLDER_NAME" - -if [ ! -d "$MNT_FOLDER/$FAKE_MOUNT_NAME/$SUBFOLDER_NAME" ]; then - return -fi -cd "$MNT_FOLDER/$FAKE_MOUNT_NAME/$SUBFOLDER_NAME" - -# single_depth -single_depth -# controlled depth -for folder in $targets ; do - # reset cwd due to loop - cd "$MNT_FOLDER/$FAKE_MOUNT_NAME/$SUBFOLDER_NAME" - if [ -L "/$folder" ] && [ ! -L "/system/$folder" ]; then - # legacy, so we mount at /system - controlled_depth "$folder" "/system/" - else - # modern, so we mount at root - controlled_depth "$folder" "/" - fi -done - -# if it reached here, module probably copied, log it -echo "$1" >> "$LOG_FOLDER/modules" - -} # mountify_symlink - -# I dont think chaining is possible right away -# logic seems hard as we have to /mnt/vendor/module1/system/app:/mnt/vendor/module2/system/app -# PR welcome if somebody sees a way to do it easily. -# so just spam it for now - -# prevent this fuckup since on expert mode this isnt checked -if [ "$FAKE_MOUNT_NAME" = "persist" ]; then - echo "$DMESG_PREFIX: folder name named $FAKE_MOUNT_NAME is not allowed!" >> /dev/kmsg - exit 1 -fi - -# make sure its not there -if [ ! "$mountify_expert_mode" = 1 ] && [ -d "$MNT_FOLDER/$FAKE_MOUNT_NAME" ]; then - # anti fuckup - # this is important as someone might actually use legit folder names - # and same shit exists on MNT_FOLDER, prevent this issue. - echo "$DMESG_PREFIX: exiting since fake folder name $FAKE_MOUNT_NAME already exists!" >> /dev/kmsg - exit 1 -fi - -mkdir -p "$MNT_FOLDER/$FAKE_MOUNT_NAME" - -# create our own tmpfs -mount -t tmpfs tmpfs "$MNT_FOLDER/$FAKE_MOUNT_NAME" - -count=0 -if [ $mountify_mounts = 1 ] && grep -qv "#" "$PERSISTENT_DIR/modules.txt" >/dev/null 2>&1 ; then - for line in $( sed '/#/d' "$PERSISTENT_DIR/modules.txt" ); do - module_id=$( echo $line | awk {'print $1'} ) - mountify_symlink "$module_id" "0000$count" - count=$(( count + 1 )) - done -else - # auto mode - for module in /data/adb/modules/*/system; do - module_id="$(echo $module | cut -d / -f 5 )" - mountify_symlink "$module_id" "0000$count" - count=$(( count + 1 )) - done -fi - -# unmout our own tmpfs -umount -l "$MNT_FOLDER/$FAKE_MOUNT_NAME" - -# log after -cat /proc/mounts > "$LOG_FOLDER/after" -touch "$LOG_FOLDER/mountify_symlink" -echo "$DMESG_PREFIX: finished!" >> /dev/kmsg - -# EOF diff --git a/module/uninstall.sh b/module/uninstall.sh deleted file mode 100644 index a430d41..0000000 --- a/module/uninstall.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -# uninstall.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -FLAGS="/data/adb/ksu/.nomount -/data/adb/ksu/.notmpfs -/data/adb/.litemode_enable" - -# remove skip_mount on modules we skip_mounted -for module in $(cat /data/adb/mountify/skipped_modules) ; do - rm /data/adb/modules/"$module"/skip_mount > /dev/null 2>&1 -done - -# remove flags created by mountify webui -for flag in $FLAGS; do - if [ -f "$flag" ] && grep -q "mountify" "$flag"; then - rm -f "$flag" - fi -done - -# delete config directory -[ -d "/data/adb/mountify/" ] && rm -rf "/data/adb/mountify/" - -# EOF diff --git a/module/whiteout/action.sh b/module/whiteout/action.sh deleted file mode 100644 index a4e3950..0000000 --- a/module/whiteout/action.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# action.sh -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="${0%/*}" - -echo "[+] mountify" -echo "[+] whiteouts" -printf "\n\n" - -if [ -d $MODDIR/system ]; then - busybox tree $MODDIR/system -fi - -# ksu and apatch auto closes -# make it wait 20s so we can read -if [ -z "$MMRL" ] && [ -z "$KSU_NEXT" ] && { [ "$KSU" = "true" ] || [ "$APATCH" = "true" ]; }; then - sleep 20 -fi - -# EOF diff --git a/module/whiteout/module.prop b/module/whiteout/module.prop deleted file mode 100644 index fd97633..0000000 --- a/module/whiteout/module.prop +++ /dev/null @@ -1,7 +0,0 @@ -id=mountify_whiteouts -name=whiteouts -version=v1 -versionCode=1 -author=mountify -description=whiteouts generated by mountify - diff --git a/module/whiteout_gen.sh b/module/whiteout_gen.sh deleted file mode 100644 index ba7f8c9..0000000 --- a/module/whiteout_gen.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/sh -# whiteout_gen.sh -# mountify's whiteout module creator -# this script is part of mountify -# No warranty. -# No rights reserved. -# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. -PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH -MODDIR="/data/adb/modules/mountify" -MODULE_UPDATES_DIR="/data/adb/modules_update/mountify_whiteouts" -MODULE_DIR="/data/adb/modules/mountify_whiteouts" -PERSISTENT_DIR="/data/adb/mountify" - -echo "[+] mountify's whiteout generator" - -if [ -z $1 ] || [ ! -f $1 ]; then - echo "[!] list missing or not specified!" - echo "[!] using whiteouts.txt" - TEXTFILE="$PERSISTENT_DIR/whiteouts.txt" - if [ ! -f $TEXTFILE ]; then - echo "[!] whiteouts.txt not found!" - exit 1 - fi -else - TEXTFILE="$(realpath $1)" -fi - -# mark module for update -mkdir -p $MODULE_DIR ; touch $MODULE_DIR/update -# create -mkdir -p $MODULE_UPDATES_DIR ; cd $MODULE_UPDATES_DIR -busybox chcon --reference="/system" "$MODULE_UPDATES_DIR" - -whiteout_create() { - echo "$MODULE_UPDATES_DIR${1%/*}" - echo "$MODULE_UPDATES_DIR$1" - mkdir -p "$MODULE_UPDATES_DIR${1%/*}" - busybox mknod "$MODULE_UPDATES_DIR$1" c 0 0 - busybox chcon --reference="/system" "$MODULE_UPDATES_DIR$1" - # not really required, mountify() does NOT even copy the attribute but ok - busybox setfattr -n trusted.overlay.whiteout -v y "$MODULE_UPDATES_DIR$1" - chmod 644 "$MODULE_UPDATES_DIR$1" -} - -for line in $( sed '/#/d' "$TEXTFILE" ); do - if echo "$line" | grep -Eq "^/(product|vendor|odm|system_ext)/" && ! echo "$line" | grep -q "^/system/"; then - line="/system$line" - elif ! echo "$line" | grep -q "^/system/"; then - echo "[!] Invalid input $line. Skipping..." - continue - fi - whiteout_create "$line" > /dev/null 2>&1 - ls "$MODULE_UPDATES_DIR$line" 2>/dev/null -done - -# special dirs -# handle this properly so this script can be used standalone -# so yeah, symlinks. -IFS=" -" -targets="odm -product -system_ext -vendor -apex -mi_ext -my_bigball -my_carrier -my_company -my_engineering -my_heytap -my_manifest -my_preload -my_product -my_region -my_reserve -my_stock -oem -optics -prism" - -# this assumes magic mount -for dir in $targets; do - if [ -d /$dir ] && [ ! -L /$dir ] && [ -d "$MODULE_UPDATES_DIR/system/$dir" ]; then - if [ -L "$MODULE_UPDATES_DIR/$dir" ]; then - # Check if the symlink points to the correct location - if [ $(readlink -f $MODULE_UPDATES_DIR/$dir) != $(realpath $MODULE_UPDATES_DIR/system/$dir) ]; then - echo "[!] Incorrect symlink for /$dir, fixing..." - rm -f $MODULE_UPDATES_DIR/$dir - ln -sf ./system/$dir $MODULE_UPDATES_DIR/$dir - else - echo "[+] Symlink for /$dir is correct, skipping..." - fi - else - echo "[+] Creating symlink for /$dir" - ln -sf ./system/$dir $MODULE_UPDATES_DIR/$dir - fi - fi -done - -# import resources for whiteout module -cat "$MODDIR/whiteout/module.prop" > "$MODULE_UPDATES_DIR/module.prop" -cat "$MODDIR/whiteout/action.sh" > "$MODULE_UPDATES_DIR/action.sh" - -# EOF diff --git a/module/whiteouts.txt b/module/whiteouts.txt deleted file mode 100644 index 00b57ec..0000000 --- a/module/whiteouts.txt +++ /dev/null @@ -1,12 +0,0 @@ -/system/vendor/bin/install-recovery.sh -/system/vendor/bin/msm_irqbalance -/system/bin/install-recovery.sh -/system/system_ext/app/MatLog -/system/system_ext/priv-app/AudioFX -/system/product/app/PowerOffAlarm -/system/product/app/Twelve -/system/etc/nikgapps_logs_archive -/system/etc/nikgapps_logs -/system/bin/servicemanager -/system/odm/etc/NOTICE.xml.gz - diff --git a/nuke_ext4_lkm/Kconfig b/nuke_ext4_lkm/Kconfig deleted file mode 100644 index 57c983a..0000000 --- a/nuke_ext4_lkm/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -menu "nuke ext4 sysfs" - -config NUKE_EXT4_SYSFS - tristate "nuke ex4 sysfs" - default m - depends on MODULES - help - this LKM unregisters an ext4 sysfs node given with mount point. - Usage: - "insmod nuke_sysfs.ko mount_point=/data/adb/modules symaddr=0xfffff12345" - -endmenu diff --git a/nuke_ext4_lkm/LICENSE b/nuke_ext4_lkm/LICENSE deleted file mode 100644 index d159169..0000000 --- a/nuke_ext4_lkm/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/nuke_ext4_lkm/Makefile b/nuke_ext4_lkm/Makefile deleted file mode 100644 index 4d3264c..0000000 --- a/nuke_ext4_lkm/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-m += nuke.o -ccflags-y += -g0 -Os -ccflags-y += -Wno-declaration-after-statement diff --git a/nuke_ext4_lkm/README.md b/nuke_ext4_lkm/README.md deleted file mode 100644 index 501fb6c..0000000 --- a/nuke_ext4_lkm/README.md +++ /dev/null @@ -1,25 +0,0 @@ -### nuke - -A small LKM to unregister an ext4 sysfs node. - -Usage: - -```shell -#!/bin/sh - -kptr_set=$(cat /proc/sys/kernel/kptr_restrict) -echo 1 > /proc/sys/kernel/kptr_restrict -ptr_address=$(grep " ext4_unregister_sysfs$" /proc/kallsyms | awk {'print "0x"$1'}) -insmod nuke.ko mount_point="/data/adb/modules" symaddr="$ptr_address" -echo $kptr_set > /proc/sys/kernel/kptr_restrict -``` - -Compatibility: -- Linux 4.4 ~ 6.17. -- CONFIG_KALLSYMS=y - -[Older version](https://github.com/backslashxx/mountify/tree/f0108a151e3be123e4aaf7319890db160692c309/nuke_ext4_lkm) -- uses kp.addr / kallsyms_lookup_name - -Credits: -- KernelSU - [de29115](https://github.com/tiann/KernelSU/commit/de291151f1c2bd63cae1f797d938bfb14cbf2dc0) diff --git a/nuke_ext4_lkm/nuke.c b/nuke_ext4_lkm/nuke.c deleted file mode 100644 index 6bd0ef9..0000000 --- a/nuke_ext4_lkm/nuke.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MODULE -#error "This is for LKM builds only. Do not compile built-in (CONFIG_NUKE_EXT4_SYSFS=y). Its bullshit." -#endif - -/* - * USAGE: - * - * kptr_set=$(cat /proc/sys/kernel/kptr_restrict) - * echo 1 > /proc/sys/kernel/kptr_restrict - * ptr_address=$(grep ext4_unregister_sysfs /proc/kallsyms | awk {'print "0x"$1'}) - * insmod nuke.ko mount_point="/data/adb/modules" symaddr="$ptr_address" - * echo $kptr_set > /proc/sys/kernel/kptr_restrict - * - */ - -static unsigned long symaddr; -module_param(symaddr, ulong, 0000); -MODULE_PARM_DESC(symaddr, "ext4_unregister_sysfs symbol address"); - -static char *mount_point = "/data/adb/modules"; -module_param(mount_point, charp, 0000); -MODULE_PARM_DESC(mount_point, "nuke an ext4 sysfs node"); - -static void __exit nuke_exit(void) {} - -static int ext4_unregister_sysfs_fn(struct super_block *sb) -{ - void (*ext4_unregister_sysfs_ptr)(struct super_block *); - const char *sym = "ext4_unregister_sysfs"; - char buf[KSYM_SYMBOL_LEN] = {0}; - - if (!symaddr) { - pr_info("mountify/nuke_ext4: symaddr not provided!\n"); - return -EINVAL; - } - - // https://elixir.bootlin.com/linux/v6.17.1/source/kernel/kallsyms.c#L474 - // turns out we can confirm the symbol! - sprint_symbol(buf, symaddr); - buf[KSYM_SYMBOL_LEN - 1] = '\0'; - - // if strstarts symbol - // output is like "ext4_unregister_sysfs+0x0/0x70" - if (!!strncmp(buf, sym, strlen(sym))) { - pr_info("mountify/nuke_ext4: wrong symbol!? %s found!\n", buf); - return -EAGAIN; - } - - pr_info("mountify/nuke_ext4: sprint_symbol 0x%lx: %s\n", symaddr, buf); - ext4_unregister_sysfs_ptr = (void (*)(struct super_block *))symaddr; - ext4_unregister_sysfs_ptr(sb); - return 0; -} - -static int __init nuke_entry(void) -{ - struct path path; - pr_info("mountify/nuke_ext4: init with symaddr: 0x%lx mount_point: %s\n", symaddr, mount_point); - - // kang from ksu - int err = kern_path(mount_point, 0, &path); - if (err) { - pr_info("mountify/nuke_ext4: kern_path failed: %d\n", err); - return -EAGAIN; - } - - struct super_block* sb = path.dentry->d_inode->i_sb; - const char* name = sb->s_type->name; - if (strcmp(name, "ext4") != 0) { - pr_info("mountify/nuke_ext4: not ext4\n"); - path_put(&path); - return -EAGAIN; - } - - pr_info("mountify/nuke_ext4: unregistering sysfs node for ext4 volume (%s)\n", sb->s_id); - ext4_unregister_sysfs_fn(sb); - - // now recheck if the node still exists - // this is on /proc/fs/ext4 - char procfs_path[64] = {0}; - snprintf(procfs_path, sizeof(procfs_path), "/proc/fs/ext4/%s", sb->s_id); - - // release ref here, we now have a copy of sb->s_id on procfs_path - path_put(&path); - - // reuse &path - err = kern_path(procfs_path, 0, &path); - if (!err) { - pr_info("mountify/nuke_ext4: procfs node still exists at %s\n", procfs_path); - path_put(&path); - } else - pr_info("mountify/nuke_ext4: procfs node nuked (%s is gone)\n", procfs_path); - - pr_info("mountify/nuke_ext4: unload\n"); - return -EAGAIN; -} - -module_init(nuke_entry); -module_exit(nuke_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("xx"); -MODULE_DESCRIPTION("nuke ext4 sysfs"); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) -MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); -#endif diff --git a/test-sysreq.sh b/test-sysreq.sh new file mode 100644 index 0000000..e91e3c4 --- /dev/null +++ b/test-sysreq.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# test-sysreq.sh +# system requirement test for mountify standalone +# you can put or execute this on customize.sh of a module. +# No warranty. +# No rights reserved. +# This is free software; you can redistribute it and/or modify it under the terms of The Unlicense. +PATH=/data/adb/ap/bin:/data/adb/ksu/bin:/data/adb/magisk:$PATH + +# routine start +echo "[+] mountify" +echo "[+] SysReq test" + +# test for overlayfs +if grep -q "overlay" /proc/filesystems > /dev/null 2>&1; then \ + echo "[+] CONFIG_OVERLAY_FS" + echo "[+] overlay found in /proc/filesystems" +else + abort "[!] CONFIG_OVERLAY_FS is required for this module!" +fi + +# test for tmpfs xattr +[ -w /mnt ] && MNT_FOLDER=/mnt +[ -w /mnt/vendor ] && MNT_FOLDER=/mnt/vendor +testfile="$MNT_FOLDER/tmpfs_xattr_testfile" +rm $testfile > /dev/null 2>&1 +busybox mknod "$testfile" c 0 0 > /dev/null 2>&1 +if busybox setfattr -n trusted.overlay.whiteout -v y "$testfile" > /dev/null 2>&1 ; then + echo "[+] CONFIG_TMPFS_XATTR" + echo "[+] tmpfs extended attribute test passed" + rm $testfile > /dev/null 2>&1 +else + rm $testfile > /dev/null 2>&1 + abort "[!] CONFIG_TMPFS_XATTR is required for this module!" +fi + +# warn on OverlayFS managers +# while this is supported (half-assed), this is not a recommended configuration +if { [ "$KSU" = true ] && [ ! "$KSU_MAGIC_MOUNT" = true ]; } || { [ "$APATCH" = true ] && [ ! "$APATCH_BIND_MOUNT" = true ]; }; then + printf "\n\n" + echo "[!] WARNING: Root manager is NOT on magic mount." + echo "[!] This setup can cause issues and is NOT recommended." +fi + +# mountify 131 added this +# this way mountify wont remount this module +[ ! -f $MODPATH/skip_mountify ] && touch $MODPATH/skip_mountify + +# EOF diff --git a/update.json b/update.json deleted file mode 100644 index f3dac42..0000000 --- a/update.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": "v1.8.7", - "versionCode": 187, - "zipUrl": "https://github.com/backslashxx/mountify/releases/latest/download/mountify.zip", - "changelog": "https://raw.githubusercontent.com/backslashxx/mountify/refs/heads/master/CHANGELOG.md" -} diff --git a/webui/.gitignore b/webui/.gitignore deleted file mode 100644 index 5a1836e..0000000 --- a/webui/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -public/config.sh diff --git a/webui/LICENSE b/webui/LICENSE deleted file mode 100644 index 41d67fc..0000000 --- a/webui/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 KOWX712 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/webui/file.js b/webui/file.js deleted file mode 100644 index 5f59864..0000000 --- a/webui/file.js +++ /dev/null @@ -1,101 +0,0 @@ -import { exec, spawn, toast } from 'kernelsu-alt'; -import { config } from './index.js' - -const moddir = '/data/adb/modules/mountify'; - -export function loadVersion() { - exec(`grep "^version=" ${moddir}/module.prop | cut -d= -f2`).then((result) => { - if (result.errno !== 0) return; - document.getElementById('version').innerHTML = result.stdout.trim(); - }).catch(() => {}); -} - -export async function loadConfig() { - try { - const response = await fetch('./config.sh'); - if (!response.ok) throw new Error('response failed'); - const conf = (await response.text()) - .split('\n') - .filter(line => line.trim() !== '' && !line.startsWith('#')) - .map(line => line.split('=')) - .reduce((acc, [key, value]) => { - if (key && value) { - const val = value.trim(); - if (val.startsWith('"') && val.endsWith('"')) { - acc[key.trim()] = val.substring(1, val.length - 1); - } else { - acc[key.trim()] = parseInt(val, 10); - } - } - return acc; - }, {}); - return conf; - } catch (e) { - exec(` - CONFIG="/data/adb/mountify/config.sh" - if [ -f "/data/adb/mountify/config.sh" ]; then - CONFIG="/data/adb/mountify/config.sh" - fi - ln -s "$CONFIG" "${moddir}/webroot/config.sh" - `).then((result) => { - if (result.errno !== 0) { - toast("Failed to load config"); - return; - } - window.location.reload(); - }).catch(() => {}); - } -} - -export async function loadConfigMetadata() { - try { - const response = await fetch('./config_mountify.json'); - if (!response.ok) { - toast('Failed to load config_mountify.json'); - return {}; - } - return await response.json(); - } catch (e) { - toast('Failed to load config_mountify.json: ' + e); - return {}; - } -} - -export async function writeConfig() { - const oldConfig = await loadConfig(); - if (!oldConfig) { - toast('Failed to save config!'); - return; - } - - const commands = []; - for (const key in config) { - if (Object.prototype.hasOwnProperty.call(config, key) && Object.prototype.hasOwnProperty.call(oldConfig, key)) { - if (config[key] !== oldConfig[key]) { - let value = config[key] - let command; - if (typeof value === 'string') { - value = value.replace(/"/g, '\"').replace(/\\/g, ''); - command = `sed -i 's|^${key}=.*|${key}="${value}"|'`; - } else { - command = `sed -i 's|^${key}=.*|${key}=${value}|'`; - } - commands.push(command + ` "$(realpath ${moddir}/webroot/config.sh)"`); - } - } - } - - if (commands.length > 0) { - let stderr = []; - const command = commands.join(' && '); - const result = spawn(command); - result.stderr.on('data', (data) => { - stderr.push(data); - }); - result.on('exit', (code) => { - if (code !== 0) { - toast('Error saving config: ' + stderr.join(' ')); - } - }); - } -} diff --git a/webui/index.html b/webui/index.html deleted file mode 100644 index 3ebf461..0000000 --- a/webui/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - mountify - - - - -
-
-
- mountify - language - power_settings_new -
- - General - Ext4 - Advanced - -
-
- - -
-
- -
- -
Reboot
-
Reboot now?
-
- Cancel - Reboot -
-
- - -
-
-
- Close -
-
- - -
Select Modules
-
- -
-
- Save -
-
- - -
Select Language
-
-
- -
-
-
- Cancel -
-
-
- - diff --git a/webui/index.js b/webui/index.js deleted file mode 100644 index 9622c34..0000000 --- a/webui/index.js +++ /dev/null @@ -1,520 +0,0 @@ -import { exec, toast } from 'kernelsu-alt'; -import '@material/web/all.js'; -import * as file from './file.js'; -import { loadTranslations, translations } from './language.js'; - -const moddir = '/data/adb/modules/mountify'; -export let config = {}; -let configMetadata = {}; -const functions = { isKsu }; - -async function checkReq(req) { - for (const [reqKey, reqValue] of Object.entries(req)) { - if (reqKey === "JavaScript") { - if (typeof reqValue !== 'object') continue; - for (const [funcName, expected] of Object.entries(reqValue)) { - if (typeof functions[funcName] !== 'function') { - toast(`invalid function ${funcName}`); - return false; - } - try { - const result = await functions[funcName](); - if (result !== expected) { - return false; - } - } catch (e) { - console.error(e); - return false; - } - } - } else { - if (config[reqKey] !== reqValue) { - return false; - } - } - } - return true; -} - -function showDescription(title, description) { - const dialog = document.getElementById('description-dialog'); - const closeBtn = dialog.querySelector('[value="close"]'); - const headline = dialog.querySelector('[slot="headline"]'); - const content = dialog.querySelector('[slot="content"]'); - headline.innerHTML = title; - content.innerHTML = description.replace(/\n/g, '
'); - closeBtn.onclick = () => dialog.close(); - window.onscroll = () => dialog.close(); - dialog.show(); -} - -async function appendInputGroup() { - for (const key in config) { - if (Object.prototype.hasOwnProperty.call(config, key)) { - const value = config[key]; - const metadata = configMetadata[key] || false; - const options = metadata?.option || []; - const header = key.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' '); - const container = document.getElementById(`content-${metadata.type}`); - const div = document.createElement('div'); - div.className = 'input-group'; - div.dataset.key = key; - - if (!metadata) continue; - if (metadata.option) { - if (metadata.option[0] === 'allow-other') { // Fixed options + custom input - appendTextField(key, value, div, options, header); - } else { // Fixed options only - appendSelect(key, value, div, options, header); - } - } else { // Raw text field - appendTextField(key, value, div, null, header); - } - container.appendChild(div); - } - } - - // Requirement - for (const key in configMetadata) { - const metadata = configMetadata[key]; - if (metadata.require) { - const dependentGroup = document.querySelector(`.input-group[data-key="${key}"]`); - if (!dependentGroup) continue; - const dependentInput = dependentGroup.querySelector('md-outlined-select, md-outlined-text-field'); - if (!dependentInput) continue; - - const checkAndSetDisabled = async () => { - const satisfied = (await Promise.all(metadata.require.map(checkReq))).every(Boolean); - dependentInput.disabled = !satisfied; - }; - - metadata.require.forEach(req => { - Object.keys(req).forEach(reqKey => { - const requirementGroup = document.querySelector(`.input-group[data-key="${reqKey}"]`); - if (requirementGroup) { - const requirementInput = requirementGroup.querySelector('md-outlined-select, md-outlined-text-field'); - if (requirementInput) { - const eventType = requirementInput.tagName.toLowerCase() === 'md-outlined-select' ? 'change' : 'input'; - requirementInput.addEventListener(eventType, checkAndSetDisabled); - } - } - }); - }); - checkAndSetDisabled(); - } - } - - setupKeyboard(); - appendExtras(); -} - -/** - * Append text field with options or raw text field if no option provided - * @param {string} key - config name - * @param {string} value - config value - * @param {HTMLElement} el - Parent element to append - * @param {string[]} options - options to show - * @param {string} header - Help menu header - * @returns {void} - */ -function appendTextField(key, value, el, options, header) { - const textField = document.createElement('md-outlined-text-field'); - textField.label = key; - textField.value = value; - textField.innerHTML = ` - - info - - `; - textField.querySelector('md-icon-button').onclick = () => { - showDescription(header, translations['desc_' + key]); - } - el.appendChild(textField); - - if (!options) { // Raw text field - textField.addEventListener('input', (event) => { - const newValue = event.target.value; - if (typeof config[key] === 'number') { - config[key] = parseInt(newValue) || 0; - } else { - config[key] = newValue; - } - }); - return; - } - - const menu = document.createElement('md-menu'); - menu.defaultFocus = ''; - menu.skipRestoreFocus = true; - menu.anchorCorner = 'start-start'; - menu.menuCorner = 'end-start'; - menu.anchorElement = textField; - el.appendChild(menu); - - // append all options once and toggle visibility with style.display on filter - options.slice(1).forEach(opt => { - const menuItem = document.createElement('md-menu-item'); - menuItem.dataset.option = opt; - menuItem.innerHTML = `
${opt}
`; - menuItem.addEventListener('click', () => { - textField.value = opt; - if (typeof config[key] === 'number') { - config[key] = parseInt(opt) || 0; - } else { - config[key] = opt; - } - menu.close(); - }); - menu.appendChild(menuItem); - }); - - const filterMenuItems = (value) => { - const newValue = String(value || ''); - if (typeof config[key] === 'number') { - config[key] = parseInt(newValue) || 0; - } else { - config[key] = newValue; - } - - const needle = newValue.toLowerCase(); - let visible = 0; - menu.querySelectorAll('md-menu-item').forEach(mi => { - const opt = (mi.dataset.option || '').toLowerCase(); - const show = opt.includes(needle) && opt !== needle; - mi.style.display = show ? '' : 'none'; - if (show) visible++; - }); - - if (visible > 0) { - menu.show(); - } else { - menu.close(); - } - } - - textField.addEventListener('input', (event) => filterMenuItems(event.target.value)); - textField.addEventListener('focus', (event) => { - setTimeout(() => { - if (document.activeElement === textField) filterMenuItems(event.target.value); - }, 100); - }); -} - -/** - * Append select options - * @param {string} key - config name - * @param {string} value - config value - * @param {HTMLElement} el - Parent element to append - * @param {string[]} options - options to show - * @param {string} header - Help menu header - * @returns {void} - */ -function appendSelect(key, value, el, options, header) { - const select = document.createElement('md-outlined-select'); - select.label = key; - select.innerHTML = ` - - info - - `; - select.querySelector('md-icon-button').addEventListener('click', (e) => { - e.stopPropagation(); - showDescription(header, translations['desc_' + key]); - }); - - options.forEach(opt => { - const option = document.createElement('md-select-option'); - option.value = opt; - option.innerHTML = `
${opt}
`; - if (opt == value) option.selected = true; - select.appendChild(option); - }); - - select.addEventListener('change', (event) => { - const newValue = event.target.value; - if (typeof config[key] === 'number') { - config[key] = parseInt(newValue) || 0; - } else { - config[key] = newValue; - } - file.writeConfig(); - }); - el.appendChild(select); -} - -function appendExtras(value) { - document.querySelectorAll('.input-group').forEach(group => { - const key = group.dataset.key; - if (!key) return; - - if (key === 'mountify_mounts') { - const button = document.createElement('md-filled-icon-button'); - button.innerHTML = `checklist_rtl`; - button.onclick = showModuleSelector; - group.appendChild(button); - - const select = group.querySelector('md-outlined-select'); - const toggleButton = () => button.disabled = config[key] !== 1; - - select.addEventListener('change', (event) => { - const newValue = event.target.value; - config[key] = parseInt(newValue) || 0; - file.writeConfig(); - toggleButton(); - }); - toggleButton(); - } - - if (key === 'FAKE_MOUNT_NAME') { - const button = document.createElement('md-filled-icon-button'); - button.innerHTML = `casino`; - button.onclick = () => { - const input = group.querySelector('md-outlined-text-field'); - const randomName = Math.random().toString(36).substring(2, 12); - input.value = randomName; - config['FAKE_MOUNT_NAME'] = randomName; - file.writeConfig(); - }; - group.appendChild(button); - } - }); -} - -async function showModuleSelector() { - const dialog = document.getElementById('module-selector-dialog'); - const saveBtn = dialog.querySelector('md-text-button'); - const list = document.getElementById('module-list'); - list.innerHTML = ''; - dialog.show(); - - const moduleList = await exec(` - dir=/data/adb/modules - for module in $(ls $dir); do - if ls $dir/$module/system >/dev/null 2>&1 && ! ls $dir/$module/system/etc/hosts >/dev/null 2>&1; then - echo $module - fi - done - `); - - exec(`cat /data/adb/mountify/modules.txt`).then((result) => { - const selected = result.stdout.trim().split('\n').map(line => line.trim()).filter(Boolean); - const modules = moduleList.stdout.trim().split('\n').filter(Boolean); - - list.innerHTML = modules.map(module => { - const isChecked = selected.includes(module); - return ` - -
${module}
- -
- `; - }).join(''); - }).catch(() => {}); - - const saveConfig = () => { - const selectedModules = Array.from(list.querySelectorAll('md-checkbox')) - .filter(checkbox => checkbox.checked) - .map(checkbox => checkbox.dataset.moduleName); - - exec(`echo "${selectedModules.join('\n').trim()}" > /data/adb/mountify/modules.txt`).then((result) => { - if (result.errno !== 0) { - toast('Failed to save: ' + result.stderr); - } - }).catch(() => {}); - } - - saveBtn.onclick = () => { - saveConfig(); - dialog.close(); - }; - window.onscroll = () => dialog.close(); -} - -function setupKeyboard() { - const keyboardInset = document.querySelector('.keyboard-inset'); - document.querySelectorAll('md-outlined-text-field').forEach(input => { - input.addEventListener('focus', () => { - keyboardInset.classList.add('active'); - setTimeout(() => { - input.scrollIntoView({ behavior: 'smooth', block: 'center' }); - }, 300); - }); - input.addEventListener('blur', () => { - file.writeConfig(); - setTimeout(() => { - const activeEl = document.activeElement; - if (!activeEl || !['md-outlined-text-field', 'md-outlined-select'].includes(activeEl.tagName.toLowerCase())) { - keyboardInset.classList.remove('active'); - } - }, 100); - }); - }); -} - -function isKsu() { - return new Promise((resolve) => { - // No su (sucompat disabled) - // ksud in PATH when running with su - exec('! command -v su || su -c "ksud -h"').then((result) => { - resolve(result.errno === 0); - }).catch(() => { - resolve(false); - }); - }); -} - -function toggleAdvanced(advanced) { - document.querySelectorAll('.input-group').forEach(group => { - const key = group.dataset.key; - if (!key) return; - const metadata = configMetadata[key] || false; - if (metadata.advanced) { - group.style.display = advanced ? '' : 'none'; - } - }); -} - -function initSwitch(path, id) { - const element = document.getElementById(id); - if (!element) return; - exec(`test -f ${path}`).then((result) => { - if (result.errno === 0) element.selected = true; - }); - element.addEventListener('change', () => { - const cmd = element.selected ? 'echo "mountify" >' : 'rm -f'; - exec(`${cmd} ${path}`).then((result) => { - if (result.errno !== 0) toast('Failed to toggle ' + path + ': ' + result.stderr); - }); - }); -} - -// Overwrite default dialog animation -document.querySelectorAll('md-dialog').forEach(dialog => { - const defaulfOpenAnim = dialog.getOpenAnimation; - const defaultCloseAnim = dialog.getCloseAnimation; - - dialog.getOpenAnimation = () => { - const defaultAnim = defaulfOpenAnim.call(dialog); - const customAnim = {}; - Object.keys(defaultAnim).forEach(key => customAnim[key] = defaultAnim[key]); - - customAnim.dialog = [ - [ - [{ opacity: 0, transform: 'translateY(50px)' }, { opacity: 1, transform: 'translateY(0)' }], - { duration: 300, easing: 'ease' } - ] - ]; - customAnim.scrim = [ - [ - [{'opacity': 0}, {'opacity': 0.32}], - {duration: 300, easing: 'linear'}, - ], - ]; - customAnim.container = []; - - return customAnim; - }; - - dialog.getCloseAnimation = () => { - const defaultAnim = defaultCloseAnim.call(dialog); - const customAnim = {}; - Object.keys(defaultAnim).forEach(key => customAnim[key] = defaultAnim[key]); - - customAnim.dialog = [ - [ - [{ opacity: 1, transform: 'translateY(0)' }, { opacity: 0, transform: 'translateY(-50px)' }], - { duration: 300, easing: 'ease' } - ] - ]; - customAnim.scrim = [ - [ - [{'opacity': 0.32}, {'opacity': 0}], - {duration: 300, easing: 'linear'}, - ], - ]; - customAnim.container = []; - - return customAnim; - }; -}); - -function initUpdateSwitch() { - const updateSwitch = document.getElementById('update'); - function checkUpdateState() { - exec(`grep -q "^updateJson=" ${moddir}/module.prop`).then((result) => { - updateSwitch.selected = result.errno === 0; - }); - } - checkUpdateState(); - updateSwitch.addEventListener('change', () => { - const cmd = updateSwitch.selected ? `"s/updateLink/updateJson/g"` : `"s/updateJson/updateLink/g"`; - exec(`sed -i ${cmd} ${moddir}/module.prop`).then((result) => { - checkUpdateState(); - if (result.errno !== 0) toast('Failed to toggle update: ' + result.stderr); - }).catch(() => {}); - }); -} - -function initRebootButton() { - document.getElementById('reboot').onclick = () => { - const confirmationDialog = document.getElementById('confirm-reboot-dialog'); - confirmationDialog.show(); - window.onscroll = () => confirmationDialog.close(); - confirmationDialog.querySelectorAll('md-text-button').forEach(btn => { - btn.onclick = () => { - confirmationDialog.close(); - if (btn.value === 'reboot') { - exec('/system/bin/reboot').then((result) => { - if (result.errno !== 0) toast('Failed to reboot: ' + result.stderr); - }).catch(() => {}); - } - } - }); - } -} - -function initLanguageButton() { - const langaugeDialog = document.getElementById('language-dialog'); - document.getElementById('language').onclick = () => { - langaugeDialog.show(); - window.onscroll = () => langaugeDialog.close(); - langaugeDialog.querySelectorAll('label, md-text-button').forEach(el => { - el.onclick = () => langaugeDialog.close(); - }); - } -} - -document.addEventListener('DOMContentLoaded', async () => { - await loadTranslations(); - document.querySelectorAll('[unresolved]').forEach(el => el.removeAttribute('unresolved')); - - [config, configMetadata] = await Promise.all([file.loadConfig(), file.loadConfigMetadata()]); - const advanced = document.getElementById('advanced'); - advanced.selected = localStorage.getItem('mountify_advanced') === 'true'; - advanced.addEventListener('change', () => { - localStorage.setItem('mountify_advanced', advanced.selected ? 'true' : 'false'); - if (config) toggleAdvanced(advanced.selected); - }); - if (config) { - await appendInputGroup(); - toggleAdvanced(advanced.selected); - } - file.loadVersion(); - - const controller = document.querySelector('md-tabs'); - controller.addEventListener('change', async () => { - await Promise.resolve(); - controller.querySelectorAll('md-primary-tab').forEach(tab => { - const panelId = tab.getAttribute('aria-controls'); - const isActive = tab.hasAttribute('active'); - const panel = document.getElementById(panelId); - isActive ? panel.removeAttribute('hidden') : panel.setAttribute('hidden', ''); - }); - }); - - initLanguageButton(); - initRebootButton(); - initUpdateSwitch(); - - initSwitch('/data/adb/.litemode_enable', 'litemode'); -}); diff --git a/webui/language.js b/webui/language.js deleted file mode 100644 index 4b4dd98..0000000 --- a/webui/language.js +++ /dev/null @@ -1,179 +0,0 @@ -const rtlLang = [ - 'ar', // Arabic - 'fa', // Persian - 'he', // Hebrew - 'ur', // Urdu - 'ps', // Pashto - 'sd', // Sindhi - 'ku', // Kurdish - 'yi', // Yiddish - 'dv', // Dhivehi -]; - -export let translations = {}; -let baseTranslations = {}; -let availableLanguages = ['en']; -let languageNames = {}; - -/** - * Parse XML translation file into a JavaScript object - * @param {string} xmlText - The XML content as string - * @returns {Object} - Parsed translations - */ -function parseTranslationsXML(xmlText) { - const parser = new DOMParser(); - const xmlDoc = parser.parseFromString(xmlText, 'text/xml'); - const strings = xmlDoc.getElementsByTagName('string'); - const translations = {}; - - for (let i = 0; i < strings.length; i++) { - const string = strings[i]; - const name = string.getAttribute('name'); - const value = string.textContent.replace(/\\n/g, '\n'); - translations[name] = value; - } - - return translations; -} - -/** - * Detect user's default language - * @returns {Promise} - Detected language code - */ -async function detectUserLanguage() { - const userLang = navigator.language || navigator.userLanguage; - const langCode = userLang.split('-')[0]; - - try { - // Fetch available languages - const availableResponse = await fetch('locales/languages.json'); - const availableData = await availableResponse.json(); - availableLanguages = Object.keys(availableData); - languageNames = availableData; - - // Fetch preferred language - const prefered_language_code = localStorage.getItem('mountify_language'); - - // Check if preferred language is valid - if (prefered_language_code !== 'default' && availableLanguages.includes(prefered_language_code)) { - return prefered_language_code; - } else if (availableLanguages.includes(userLang)) { - return userLang; - } else if (availableLanguages.includes(langCode)) { - return langCode; - } else { - localStorage.removeItem('mountify_language'); - return 'en'; - } - } catch (error) { - console.error('Error detecting user language:', error); - return 'en'; - } -} - -/** - * Load translations dynamically based on the selected language - * @returns {Promise} - */ -export async function loadTranslations() { - try { - // load Englsih as base translations - const baseResponse = await fetch('./locales/strings/en.xml'); - const baseXML = await baseResponse.text(); - baseTranslations = parseTranslationsXML(baseXML); - - // load user's language if available - const lang = await detectUserLanguage(); - if (lang !== 'en') { - const response = await fetch(`locales/strings/${lang}.xml`); - const userXML = await response.text(); - const userTranslations = parseTranslationsXML(userXML); - translations = { ...baseTranslations, ...userTranslations }; - } else { - translations = baseTranslations; - } - - // Support for rtl language - const isRTL = rtlLang.includes(lang.split('-')[0]); - document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr'); - - // Generate language menu - await generateLanguageMenu(); - } catch (error) { - console.error('Error loading translations:', error); - translations = baseTranslations; - } - applyTranslations(); -} - -/** - * Apply translations to all elements with data-i18n attributes - * @returns {void} - */ -function applyTranslations() { - document.querySelectorAll("[data-i18n]").forEach((el) => { - const key = el.getAttribute("data-i18n"); - const translation = translations[key]; - if (translation) { - if (el.hasAttribute("placeholder")) { - el.setAttribute("placeholder", translation); - } else if (el.hasAttribute("label")) { - el.setAttribute("label", translation); - } else { - el.textContent = translation; - } - } - }); -} - -/** - * Function to set a language - * @param {string} language - Target langauge to set - * @returns {void} - */ -function setLanguage(language) { - localStorage.setItem('mountify_language', language); - loadTranslations(); -} - -/** - * Generate the language menu dynamically - * Refer available-lang.json in ./locales for list of languages - * @returns {Promise} - */ -async function generateLanguageMenu() { - const languageForm = document.getElementById('language-form'); - languageForm.innerHTML = ''; - - const createOption = (lang, name) => { - const label = document.createElement('label'); - label.className = 'language-option'; - label.innerHTML = ` - - ${name} - `; - - const radio = label.querySelector('md-radio'); - - const currentLang = localStorage.getItem('mountify_language') || 'default'; - if (currentLang === lang) radio.checked = true; - - radio.addEventListener('change', () => { - if (radio.checked) setLanguage(lang); - }); - - languageForm.appendChild(label); - }; - - createOption('default', translations['system_default'] || 'System Default'); - - const sortedLanguages = Object.entries(languageNames) - .map(([lang, name]) => ({ lang, name })) - .sort((a, b) => a.name.localeCompare(b.name)); - - sortedLanguages.forEach(({ lang, name }) => { - createOption(lang, name); - }); - - applyTranslations(); -} diff --git a/webui/material-symbols-outlined.woff2 b/webui/material-symbols-outlined.woff2 deleted file mode 100644 index 81a31e3..0000000 Binary files a/webui/material-symbols-outlined.woff2 and /dev/null differ diff --git a/webui/package-lock.json b/webui/package-lock.json deleted file mode 100644 index c2c5862..0000000 --- a/webui/package-lock.json +++ /dev/null @@ -1,2000 +0,0 @@ -{ - "name": "mountify", - "version": "1.5.6", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "mountify", - "version": "1.5.6", - "license": "MIT", - "dependencies": { - "@material/web": "^2.4.1", - "kernelsu-alt": "^2.1.2" - }, - "devDependencies": { - "vite": "^7.2.4", - "vite-plugin-html": "^3.2.2" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", - "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", - "license": "BSD-3-Clause" - }, - "node_modules/@lit/reactive-element": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", - "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.4.0" - } - }, - "node_modules/@material/web": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@material/web/-/web-2.4.1.tgz", - "integrity": "sha512-0sk9t25acJ72Qv3r0n9r0lgDbPaAKnpm0p+QmEAAwYyZomHxuVbgrrAdtNXaRm7jFyGh+WsTr8bhtvCnpPRFjw==", - "license": "Apache-2.0", - "workspaces": [ - "catalog" - ], - "dependencies": { - "lit": "^2.8.0 || ^3.0.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-expand": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz", - "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/kernelsu-alt": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/kernelsu-alt/-/kernelsu-alt-2.1.2.tgz", - "integrity": "sha512-GgpHmnAM3fNawQfpHnoUE5ME+f2A33lJfMODKdkPXPk2W+OUkzwua7N4hGoLtrN0YC8CZvPrBZ660nK2EZ1rhA==", - "license": "Apache-2.0" - }, - "node_modules/lit": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.1.tgz", - "integrity": "sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit/reactive-element": "^2.1.0", - "lit-element": "^4.2.0", - "lit-html": "^3.3.0" - } - }, - "node_modules/lit-element": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", - "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.4.0", - "@lit/reactive-element": "^2.1.0", - "lit-html": "^3.3.0" - } - }, - "node_modules/lit-html": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", - "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", - "license": "BSD-3-Clause", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-html-parser": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.2.tgz", - "integrity": "sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-select": "^4.2.1", - "he": "1.2.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pathe": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-0.2.0.tgz", - "integrity": "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/vite": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", - "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-plugin-html": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vite-plugin-html/-/vite-plugin-html-3.2.2.tgz", - "integrity": "sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^4.2.0", - "colorette": "^2.0.16", - "connect-history-api-fallback": "^1.6.0", - "consola": "^2.15.3", - "dotenv": "^16.0.0", - "dotenv-expand": "^8.0.2", - "ejs": "^3.1.6", - "fast-glob": "^3.2.11", - "fs-extra": "^10.0.1", - "html-minifier-terser": "^6.1.0", - "node-html-parser": "^5.3.3", - "pathe": "^0.2.0" - }, - "peerDependencies": { - "vite": ">=2.0.0" - } - } - } -} diff --git a/webui/package.json b/webui/package.json deleted file mode 100644 index f4e51b9..0000000 --- a/webui/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "mountify", - "version": "1.5.6", - "description": "", - "scripts": { - "dev": "vite", - "build": "vite build --emptyOutDir" - }, - "keywords": [ - "mountify" - ], - "author": "KOWX712", - "license": "MIT", - "type": "module", - "dependencies": { - "@material/web": "^2.4.1", - "kernelsu-alt": "^2.1.2" - }, - "devDependencies": { - "vite": "^7.2.4", - "vite-plugin-html": "^3.2.2" - } -} diff --git a/webui/public/config.json b/webui/public/config.json deleted file mode 100644 index 73f8523..0000000 --- a/webui/public/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "mountify", - "exitConfirm": false -} \ No newline at end of file diff --git a/webui/public/config_mountify.json b/webui/public/config_mountify.json deleted file mode 100644 index 8d09c15..0000000 --- a/webui/public/config_mountify.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "mountify_mounts": { - "type": "general", - "option": [0, 1, 2] - }, - "FAKE_MOUNT_NAME": { - "type": "general" - }, - "test_decoy_mount": { - "type": "general", - "option": [0, 1] - }, - "mountify_stop_start": { - "type": "general", - "option": [0, 1] - }, - "FS_TYPE_ALIAS": { - "type": "general", - "advanced": true, - "option": ["allow-other", "overlay"] - }, - "MOUNT_DEVICE_NAME": { - "type": "general", - "option": ["allow-other", "overlay", "KSU", "APatch", "magisk"] - }, - "mountify_custom_umount": { - "type": "general", - "require": [ - { "JavaScript": { "isKsu": true } } - ], - "option": [0, 1, 2] - }, - "mountify_expert_mode": { - "type": "general", - "advanced": true, - "option": [0, 1] - }, - "use_ext4_sparse": { - "type": "ext4", - "option": [0, 1] - }, - "spoof_sparse": { - "type": "ext4", - "require": [{"enable_lkm_nuke": 0}], - "option": [0, 1] - }, - "FAKE_APEX_NAME": { - "type": "ext4", - "require": [{"spoof_sparse": 1}], - "option": ["allow-other", "com.android.mntservice"] - }, - "sparse_size": { - "type": "ext4", - "option": ["allow-other", "512", "1024", "2048", "4096"] - }, - "enable_lkm_nuke": { - "type": "ext4", - "require": [{"spoof_sparse": 0}], - "option": [0, 1] - }, - "lkm_filename": { - "type": "ext4", - "require": [{"enable_lkm_nuke": 1}], - "option": [ - "nuke-android12-5.10.ko", - "nuke-android13-5.10.ko", - "nuke-android13-5.15.ko", - "nuke-android14-5.15.ko", - "nuke-android14-6.1.ko", - "nuke-android15-6.6.ko", - "nuke-android-4.14.ko" - ] - } -} diff --git a/webui/public/locales/CONTRIBUTOR.md b/webui/public/locales/CONTRIBUTOR.md deleted file mode 100644 index 349be41..0000000 --- a/webui/public/locales/CONTRIBUTOR.md +++ /dev/null @@ -1,11 +0,0 @@ -# Mountify WebUI Translation Contributor List - -## Chinese (Simplified) - -- [KOWX712](https://github.com/KOWX712) - ---- - -## English - -- [KOWX712](https://github.com/KOWX712) diff --git a/webui/public/locales/GUIDE.md b/webui/public/locales/GUIDE.md deleted file mode 100644 index 2ddc92d..0000000 --- a/webui/public/locales/GUIDE.md +++ /dev/null @@ -1,22 +0,0 @@ -# Mountify WebUI Localization Guideline - -## Add a new langauge - -1. [Fork](https://github.com/backslashxx/mountify/fork) this repository. -2. Make a copy of `webui/public/locales/en.xml` to strings folder. -3. Rename it to `{language-code}.xml` by refering [language codes standard](https://support.crowdin.com/developer/language-codes). -4. Add language entrance in `webui/public/locales/languages.json`, format: "language-code": "Language name in your language". - ```json - { - "en": "English", - "fr": "Français", // Your language, keep alphabetical order - "zh-CN": "简体中文" - } - ``` -5. Do translation to all the string value or update existing string value. -6. Add your info to `webui/public/locales/CONTRIBUTOR.md`. -7. Open pull request. - -## Update existing langauge - -- Same with adding a new language, skip step 2 to 4. diff --git a/webui/public/locales/languages.json b/webui/public/locales/languages.json deleted file mode 100644 index 3b66117..0000000 --- a/webui/public/locales/languages.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "en": "English", - "zh-CN": "简体中文" -} diff --git a/webui/public/locales/strings/en.xml b/webui/public/locales/strings/en.xml deleted file mode 100644 index cec5fc1..0000000 --- a/webui/public/locales/strings/en.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - General - Ext4 - Advanced - Show advanced option - Enable mountify update - Enable litemode - Litemode is introduced in APatch since v11024 - Reboot - Reboot now? - Reboot - Select Modules - System Default - Select Language - - - Cancel - Close - Save - - - Module mounting config.\n0 - disable\n1 - manual mode (mount modules that found on modules.txt)\n2 - auto mode (mount all modules with system folder) - Mount folder name. - Test for decoy mounting.\nThis is meant for tmpfs mode.\n0 - disable\n1 - enable - Restarts android at service, certain modules might need this.\nThis is a workaround for 'racey' modules such as bootanimations and gpu drivers.\n⚠️ if you do NOT have a problem, you do NOT need this\n\n0 - disable\n1 - enable - Change this if you have a customized overlayfs driver registered with another alias. - You can put 'APatch', 'KSU', 'magisk' here so a zygisk provider can umount.\n\nExamples: NeoZygisk, NoHello, ReZygisk, Zygisk Assistant, ZygiskNext-UM/DE - Enable in-kernel umount methods here.\n0 - disable\n1 - susfs4ksu\n2 - ksud kernel umount (22106+)\n\n⚠️ if you have a zygisk provider, you do NOT need this - 🚨 WARNING!\n ⚠️ This disables safety checks.\nMostly for development and debugging purposes.\n0 - disable\n1 - enable - ext4 sparse mode override.\nFor tmpfs xattr capable setups that prefers using an ext4 sparse image to mount.\n0 - disable\n1 - enable - Spoof sparse as an apex mount.\nGoes well with a custom MOUNT_DEVICE_NAME.\nNOTE: when this is enabled, nuking is disabled. - Customize spoofed apex mount name.\nWhile futile, this tries to make it look legit. - Set a custom sparse size.\nModify this to any unsigned number.\n- sparse size in MB. - 🚨 WARNING!\n⚠️ Experimental feature. Don't expect 100% success rate.\nLoads a oneshot LKM that unregisters ext4 sysfs nodes. \n0 - disable\n1 - enable\n\nNOTE: on KernelSU 22105+ this is handled on ksud - Only GKI 5.10+ are properly supported.\nSelect your Android KMI. - diff --git a/webui/public/locales/strings/zh-CN.xml b/webui/public/locales/strings/zh-CN.xml deleted file mode 100644 index 240f21a..0000000 --- a/webui/public/locales/strings/zh-CN.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 常规 - Ext4 - 高级 - 显示高级选项 - 启用 mountify 更新 - 启用 litemode - Litemode 自 APatch v11024 起引入 - 重启 - 立即重启? - 重启 - 选择模块 - 系统默认 - 选择语言 - - - 取消 - 关闭 - 保存 - - - 模块挂载配置。\n0 - 禁用\n1 - 手动模式 (挂载 modules.txt 中发现的模块)\n2 - 自动模式 (挂载所有包含 system 文件夹的模块) - 挂载文件夹名称。 - 诱饵挂载测试。\n这是为 tmpfs 模式设计的。\n0 - 禁用\n1 - 启用 - 在服务处重启 Android,某些模块可能需要此操作。\n这是针对开机动画和 GPU 驱动等“竞争性”模块的变通方法。\n⚠️ 如果你没有遇到问题,则不需要此选项\n\n0 - 禁用\n1 - 启用 - 如果你有注册了其他别名的自定义 overlayfs 驱动,请更改此项。 - 你可以在这里填入 'APatch', 'KSU', 'magisk' 以便 zygisk 卸载。\n\n示例: NeoZygisk, NoHello, ReZygisk, Zygisk Assistant, ZygiskNext-UM/DE - 在此处启用内核内卸载方法。\n0 - 禁用\n1 - susfs4ksu\n2 - ksud 内核卸载 (22106+)\n\n⚠️ 如果你有使用 zygisk,则不需要此选项 - 🚨 警告!\n ⚠️ 这将禁用安全检查。\n主要用于开发和调试目的。\n0 - 禁用\n1 - 启用 - ext4 稀疏模式覆盖。\n适用于偏好使用 ext4 稀疏镜像进行挂载的 tmpfs xattr 兼容设置。\n0 - 禁用\n1 - 启用 - 将稀疏镜像伪装为 apex 挂载。\n与自定义 MOUNT_DEVICE_NAME 配合使用效果更佳。\n注意:启用此选项时,nuking 将被禁用。 - 自定义伪装的 apex 挂载名称。\n虽然徒劳,但这试图让它看起来合法。 - 设置自定义稀疏大小。\n修改为任何无符号数字。\n- 稀疏大小 (MB)。 - 🚨 警告!\n⚠️ 实验性功能。不要指望 100% 成功率。\n加载一个一次性 LKM 来注销 ext4 sysfs 节点。\n0 - 禁用\n1 - 启用\n\n注意:在 KernelSU 22105+ 上,这由 ksud 处理 - 仅正确支持 GKI 5.10+。\n选择你的 Android KMI。 - diff --git a/webui/styles.css b/webui/styles.css deleted file mode 100644 index 88b7701..0000000 --- a/webui/styles.css +++ /dev/null @@ -1,149 +0,0 @@ -@import "./theme.css"; - -body { - background-color: var(--md-sys-color-surface); - color: var(--md-sys-color-on-surface); - padding-top: var(--top-inset); - padding-bottom: calc(var(--bottom-inset) + 80px); - margin: 0; - font-size: 16px; -} - -.root_layout { - width: 100%; - max-width: 768px; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - margin: 0 auto; - transition: opacity 0.2s; -} - -.header { - width: 100vw; - position: fixed; - padding-top: var(--top-inset); - top: 0; - left: 0; - z-index: 2; - background-color: var(--md-sys-color-surface); -} - -.top-bar { - font-size: 1.4em; - height: 64px; - width: 100%; - display: flex; - align-items: center; - justify-content: flex-start; - gap: 0.3em; - width: 100%; - padding: 0 16px; - box-sizing: border-box; -} - -#version { - flex-grow: 1; -} - -md-tabs { - width: 100% -} - -.content-container { - width: 100%; - max-width: 100%; - margin-top: 128px; -} - -.content { - padding: 0 16px; - box-sizing: border-box; -} - -.input-group { - margin-top: 16px; - margin-bottom: 32px; - width: 100%; - display: flex; - align-items: center; - gap: 8px; - position: relative; -} - -md-outlined-text-field, md-outlined-select { - flex-grow: 1; - min-width: 0; -} - -md-filled-icon-button { - flex-shrink: 0; - --md-filled-icon-button-container-height: 56px; - --md-filled-icon-button-container-width: 56px; - --md-filled-icon-button-container-shape: 6px; -} - -md-list { - width: 100%; - background-color: transparent; -} - -.title { - margin-top: 48px; - font-size: 0.8em; - font-weight: bold; - color: var(--md-sys-color-primary); - user-select: none; -} - -label.content { - position: relative; - padding: 16px !important; - font-size: 1.1em; - width: 100%; - display: flex; - align-items: center; - justify-content: space-between; - user-select: none; - - --md-focus-ring-color: transparent; -} - -.warning { - font-size: 0.9em; - color: var(--md-sys-color-outline); - width: 100%; -} - -[slot="headline"] { - user-select: none; -} - -.dialog-wrapper { - z-index: 10; - position: relative; -} - -.keyboard-inset { - flex-shrink: 0; - height: 0px; - transition: height 0.1s ease; -} - -.keyboard-inset.active { - height: 50vh; -} - -[unresolved] { - opacity: 0; - overflow: hidden; -} - -.language-option { - display: flex; - align-items: center; - padding: 12px; - gap: 16px; - user-select: none; -} diff --git a/webui/theme.css b/webui/theme.css deleted file mode 100644 index 66fa94d..0000000 --- a/webui/theme.css +++ /dev/null @@ -1,107 +0,0 @@ -@import url('https://mui.kernelsu.org/internal/insets.css'); -@import url('https://mui.kernelsu.org/internal/colors.css'); - -:root { - --top-inset: var(--window-inset-top, 0px); - --bottom-inset: var(--window-inset-bottom, 0px); - - --md-sys-color-primary: var(--primary, #6750A4); - --md-sys-color-on-primary: var(--onPrimary, #FFFFFF); - --md-sys-color-primary-container: var(--primaryContainer, #EADDFF); - --md-sys-color-on-primary-container: var(--onPrimaryContainer, #4F378B); - --md-sys-color-secondary: var(--secondary, #625B71); - --md-sys-color-on-secondary: var(--onSecondary, #FFFFFF); - --md-sys-color-secondary-container: var(--secondaryContainer, #E8DEF8); - --md-sys-color-on-secondary-container: var(--on-secondaryContainer, #4A4458); - --md-sys-color-tertiary: var(--tertiary, #7D5260); - --md-sys-color-on-tertiary: var(--onTertiary, #FFFFFF); - --md-sys-color-tertiary-container: var(--tertiaryContainer, #FFD8E4); - --md-sys-color-on-tertiary-container: var(--onTertiaryContainer, #633B48); - --md-sys-color-error: var(--error, #B3261E); - --md-sys-color-on-error: var(--onError, #FFFFFF); - --md-sys-color-error-container: var(--errorContainer, #F9DEDC); - --md-sys-color-on-error-container: var(--onErrorContainer, #8C1D18); - --md-sys-color-background: var(--background, #FEF7FF); - --md-sys-color-on-background: var(--onBackground, #1D1B20); - --md-sys-color-surface: var(--surface, #FEF7FF); - --md-sys-color-on-surface: var(--onSurface, #1D1B20); - --md-sys-color-surface-variant: var(--surfaceVariant, #E7E0EC); - --md-sys-color-on-surface-variant: var(--onSurfaceVariant, #49454F); - --md-sys-color-outline: var(--outline, #79747E); - --md-sys-color-outline-variant: var(--outlineVariant, #CAC4D0); - --md-sys-color-shadow: var(--shadow, #000000); - --md-sys-color-inverse-surface: var(--inverseSurface, #322F35); - --md-sys-color-inverse-on-surface: var(--inverseOnSurface, #F5EFF7); - --md-sys-color-inverse-primary: var(--inversePrimary, #D0BCFF); - --md-sys-color-surface-bright: var(--surfaceBright, #FEF7FF); - --md-sys-color-surface-dim: var(--surfaceDim, #DED8E1); - --md-sys-color-surface-container: var(--surfaceContainer, #F3EDF7); - --md-sys-color-surface-container-lowest: var(--surfaceContainerLowest, #FFFFFF); - --md-sys-color-surface-container-low: var(--surfaceContainerLow, #F7F2FA); - --md-sys-color-surface-container-high: var(--surfaceContainerHigh, #ECE6F0); - --md-sys-color-surface-container-highest: var(--surfaceContainerHighest, #E6E0E9); -} - -@media (prefers-color-scheme: dark) { - :root { - --md-sys-color-primary: var(--primary, #D0BCFF); - --md-sys-color-on-primary: var(--onPrimary, #381E72); - --md-sys-color-primary-container: var(--primaryContainer, #4F378B); - --md-sys-color-on-primary-container: var(--onPrimaryContainer, #EADDFF); - --md-sys-color-secondary: var(--secondary, #CCC2DC); - --md-sys-color-on-secondary: var(--onSecondary, #332D41); - --md-sys-color-secondary-container: var(--secondaryContainer, #4A4458); - --md-sys-color-on-secondary-container: var(--onSecondaryContainer, #E8DEF8); - --md-sys-color-tertiary: var(--tertiary, #EFB8C8); - --md-sys-color-on-tertiary: var(--onTertiary, #492532); - --md-sys-color-tertiary-container: var(--tertiaryContainer, #633B48); - --md-sys-color-on-tertiary-container: var(--onTertiaryContainer, #FFD8E4); - --md-sys-color-error: var(--error, #F2B8B5); - --md-sys-color-on-error: var(--onError, #601410); - --md-sys-color-error-container: var(--errorContainer, #8C1D18); - --md-sys-color-on-error-container: var(--onErrorContainer, #F9DEDC); - --md-sys-color-background: var(--background, #141218); - --md-sys-color-on-background: var(--onBackground, #E6E0E9); - --md-sys-color-surface: var(--surface, #141218); - --md-sys-color-on-surface: var(--onSurface, #E6E0E9); - --md-sys-color-surface-variant: var(--surfaceVariant, #49454F); - --md-sys-color-on-surface-variant: var(--onSurfaceVariant, #CAC4D0); - --md-sys-color-outline: var(--outline, #938F99); - --md-sys-color-outline-variant: var(--outlineVariant, #49454F); - --md-sys-color-shadow: var(--shadow, #000000); - --md-sys-color-inverse-surface: var(--inverseSurface, #E6E0E9); - --md-sys-color-inverse-on-surface: var(--inverseOnSurface, #322F35); - --md-sys-color-inverse-primary: var(--inversePrimary, #6750A4); - --md-sys-color-surface-bright: var(--surfaceBright, #3B383E); - --md-sys-color-surface-dim: var(--surfaceDim, #141218); - --md-sys-color-surface-container: var(--surfaceContainer, #211F26); - --md-sys-color-surface-container-lowest: var(--surfaceContainerLowest, #0F0D13); - --md-sys-color-surface-container-low: var(--surfaceContainerLow, #1D1B20); - --md-sys-color-surface-container-high: var(--surfaceContainerHigh, #2B2930); - --md-sys-color-surface-container-highest: var(--surfaceContainerHighest, #36343B); - } -} - -@font-face { - font-family: 'Material Symbols Outlined'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url('/material-symbols-outlined.woff2') format('woff2'); -} - -.material-symbols-outlined { - font-family: 'Material Symbols Outlined'; - font-weight: normal; - font-style: normal; - font-size: 24px; - line-height: 1; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -moz-font-feature-settings: 'liga'; - -moz-osx-font-smoothing: grayscale; -} diff --git a/webui/vite.config.js b/webui/vite.config.js deleted file mode 100644 index 815a102..0000000 --- a/webui/vite.config.js +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'vite'; -import { createHtmlPlugin } from 'vite-plugin-html' - -export default defineConfig({ - base: './', - build: { - outDir: '../module/webroot', - }, - plugins: [ - createHtmlPlugin({ - minify: true - }) - ] -});