├── META-INF ├── CERT.RSA ├── CERT.SF ├── MANIFEST.MF └── com │ └── google │ └── android │ ├── update-binary │ └── updater-script ├── README.md ├── common ├── aapt ├── file_contexts_image ├── post-fs-data.sh ├── service.sh └── system.prop ├── config.sh ├── module.prop ├── system └── bin │ ├── systemize │ └── systemize_magisk └── update-binary /META-INF/CERT.RSA: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veez21/terminal_app_systemizer/c690738ff0ec0cf58d895ca12ed9ffc8e129b13f/META-INF/CERT.RSA -------------------------------------------------------------------------------- /META-INF/CERT.SF: -------------------------------------------------------------------------------- 1 | Signature-Version: 1.0 2 | SHA1-Digest-Manifest: yFhu7TfSRdC5xHROIC9V6tAWGUk= 3 | Created-By: 1.0 (Android SignApk) 4 | 5 | Name: META-INF/com/google/android/updater-script 6 | SHA1-Digest-Manifest: pVUJ9D5th6d2sD8aeNp5zhiBUcs= 7 | 8 | Name: common/aapt 9 | SHA1-Digest-Manifest: 4YV2lGD67XGVdLvutrY2zgnZKf4= 10 | 11 | Name: module.prop 12 | SHA1-Digest-Manifest: d1o8Xh4zlQhHPsiHHPjH4eSCTEw= 13 | 14 | Name: system/bin/systemize_magisk 15 | SHA1-Digest-Manifest: ZwgNn+STGAH602ajyyEv4BzNm30= 16 | 17 | Name: META-INF/com/google/android/update-binary 18 | SHA1-Digest-Manifest: mMBZ4zsqG8nP6tBnQV1WIWkLU6g= 19 | 20 | Name: common/post-fs-data.sh 21 | SHA1-Digest-Manifest: SyX3X/PeDY9ntN8RXeBKc888YZg= 22 | 23 | Name: common/system.prop 24 | SHA1-Digest-Manifest: HbzvC3Tyik76s7nzWE6amQuJyXg= 25 | 26 | Name: common/service.sh 27 | SHA1-Digest-Manifest: TOn/zXTfuf86lkAJLKXrKctujsY= 28 | 29 | Name: config.sh 30 | SHA1-Digest-Manifest: Njo4oCmhgcNamoN0Pf2sqlreJbU= 31 | 32 | Name: README.md 33 | SHA1-Digest-Manifest: 1uh3o9lGFi6E4LlfBM86xz+XrPo= 34 | 35 | Name: common/file_contexts_image 36 | SHA1-Digest-Manifest: d0Z/GcKeayRQbW+lqq5Fe4Ncjps= 37 | 38 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Created-By: 1.0 (Android SignApk) 3 | 4 | Name: META-INF/com/google/android/updater-script 5 | SHA1-Digest: Lzl1y1cC6TvXytLj6okU81/P8AA= 6 | 7 | Name: common/aapt 8 | SHA1-Digest: /QTAnE41/w9WjKi4klTircpywpM= 9 | 10 | Name: module.prop 11 | SHA1-Digest: PNa86qTUqUrMLt2+mes7V7Q0i70= 12 | 13 | Name: system/bin/systemize_magisk 14 | SHA1-Digest: rVkRDPgaDu2ScwfC/5X5aCH+7PY= 15 | 16 | Name: META-INF/com/google/android/update-binary 17 | SHA1-Digest: maDvkk1PGajRzQe4og+OUWtyuGQ= 18 | 19 | Name: common/post-fs-data.sh 20 | SHA1-Digest: W9c/DllxnfxrlloMGo5ef2mC+dc= 21 | 22 | Name: common/system.prop 23 | SHA1-Digest: 7TnZoxe4jX3vocrbr/oRcPziZMQ= 24 | 25 | Name: common/service.sh 26 | SHA1-Digest: hCOn0sjc2mEMqqqcb7TFt4BEcVM= 27 | 28 | Name: config.sh 29 | SHA1-Digest: FXgpbF8WaV3edRFWr4F3G9Kym5w= 30 | 31 | Name: README.md 32 | SHA1-Digest: T1dc3UTUFB4QuvKGVvjw2eIPxcs= 33 | 34 | Name: common/file_contexts_image 35 | SHA1-Digest: 3CMh9/rAwg+csTwthHJENOyhpmE= 36 | 37 | -------------------------------------------------------------------------------- /META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | ########################################################################################## 3 | # 4 | # Magisk Module Template Install Script 5 | # by topjohnwu 6 | # 7 | ########################################################################################## 8 | 9 | # Detect whether in boot mode 10 | ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false 11 | $BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true 12 | 13 | # Default permissions 14 | umask 022 15 | 16 | ########################################################################################## 17 | # Flashable update-binary preparation 18 | ########################################################################################## 19 | 20 | # DETERMINE IF PIXEL (A/B OTA) DEVICE 21 | ABDeviceCheck=$(cat /proc/cmdline | grep slot_suffix | wc -l) 22 | if [ "$ABDeviceCheck" -gt 0 ]; then 23 | isABDevice=true 24 | SYSTEM=/system/system 25 | else 26 | isABDevice=false 27 | SYSTEM=/system 28 | fi 29 | 30 | OUTFD=$2 31 | ZIP=$3 32 | 33 | ui_print() { 34 | if $BOOTMODE; then 35 | echo "$1" 36 | else 37 | echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD 38 | echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD 39 | fi 40 | } 41 | 42 | is_mounted() { 43 | if [ ! -z "$2" ]; then 44 | cat /proc/mounts | grep $1 | grep $2, >/dev/null 45 | else 46 | cat /proc/mounts | grep $1 >/dev/null 47 | fi 48 | return $? 49 | } 50 | 51 | require_new_magisk() { 52 | ui_print "***********************************" 53 | ui_print "! $MAGISKBIN isn't setup properly!" 54 | ui_print "! Please install Magisk v14.0+!" 55 | ui_print "***********************************" 56 | exit 1 57 | } 58 | 59 | # Mount /data and /cache to access MAGISKBIN 60 | mount /data 2>/dev/null 61 | mount /cache 2>/dev/null 62 | 63 | # This path should work in any cases 64 | TMPDIR=/dev/tmp 65 | MOUNTPATH=/magisk 66 | INSTALLER=$TMPDIR/install 67 | if is_mounted /data; then 68 | IMG=/data/magisk.img 69 | MAGISKBIN=/data/magisk 70 | if $BOOTMODE; then 71 | MOUNTPATH=/dev/magisk_merge 72 | IMG=/data/magisk_merge.img 73 | fi 74 | else 75 | IMG=/cache/magisk.img 76 | MAGISKBIN=/cache/data_bin 77 | ui_print "- Data unavailable, using cache workaround" 78 | fi 79 | 80 | # Utility functions must exist 81 | [ -f $MAGISKBIN/util_functions.sh ] || require_new_magisk 82 | # Load utility fuctions 83 | . $MAGISKBIN/util_functions.sh 84 | get_outfd 85 | 86 | rm -rf $TMPDIR 2>/dev/null 87 | mkdir -p $INSTALLER 88 | # Extract common files 89 | unzip -o "$ZIP" module.prop config.sh 'common/*' -d $INSTALLER 2>/dev/null 90 | 91 | ########################################################################################## 92 | # Prepare 93 | ########################################################################################## 94 | 95 | [ ! -f $INSTALLER/config.sh ] && abort "! Unable to extract zip file!" 96 | # Load configurations 97 | . $INSTALLER/config.sh 98 | 99 | # Check the min magisk version 100 | MIN_VER=`grep_prop template $INSTALLER/module.prop` 101 | [ ! -z $MAGISK_VER_CODE -a $MAGISK_VER_CODE -ge $MIN_VER ] || require_new_magisk 102 | MODID=`grep_prop id $INSTALLER/module.prop` 103 | MODPATH=$MOUNTPATH/$MODID 104 | 105 | # Print mod name 106 | print_modname 107 | 108 | # Please leave this message in your flashable zip for credits :) 109 | ui_print "******************************" 110 | ui_print "Powered by Magisk (@topjohnwu)" 111 | ui_print "******************************" 112 | 113 | SPACE=" " 114 | if [ $isABDevice == true ]; then 115 | ui_print " ! A/B OTA device detected!" 116 | WRITE=rw 117 | SPACE=" " 118 | elif [ -f /data/magisk.img ] || [ -f /cache/magisk.img ] || [ -d /magisk ]; then 119 | WRITE=ro 120 | elif [ ! -f /data/magisk.img ] || [ ! -f /cache/magisk.img ] || [ ! -d /magisk ]; then 121 | WRITE=rw 122 | fi 123 | 124 | ui_print "$SPACE Mounting /system($WRITE)..." 125 | mount -o $WRITE /system 2>/dev/null 126 | ui_print "$SPACE Mounting /vendor($WRITE)..." 127 | mount -o $WRITE /vendor 2>/dev/null 128 | 129 | if [ $isABDevice == true ] || [ ! -d $SYSTEM/vendor ]; then 130 | VENDOR=/vendor 131 | else 132 | VENDOR=$SYSTEM/vendor 133 | fi 134 | 135 | if is_mounted /data; then 136 | [ ! -f /data/magisk.img ] && abort "! Magisk is not installed" 137 | else 138 | [ ! -f /cache/magisk.img ] && abort "! Magisk is not installed" 139 | fi 140 | $BOOTMODE && ! is_mounted /magisk && abort "! Magisk is not activated!" 141 | [ ! -f $SYSTEM/build.prop ] && abort "! $SYSTEM could not be mounted!" 142 | 143 | # Detect version and architecture 144 | api_level_arch_detect 145 | 146 | # You can get the Android API version from $API, the CPU architecture from $ARCH 147 | # Useful if you are creating Android version / platform dependent mods 148 | 149 | # We need busybox/binaries to be setup 150 | $BOOTMODE && boot_actions || recovery_actions 151 | 152 | ########################################################################################## 153 | # Install 154 | ########################################################################################## 155 | 156 | request_zip_size_check "$ZIP" 157 | 158 | if [ -f "$IMG" ]; then 159 | ui_print "- Found $IMG" 160 | image_size_check $IMG 161 | if [ "$reqSizeM" -gt "$curFreeM" ]; then 162 | newSizeM=$(((reqSizeM + curUsedM) / 32 * 32 + 64)) 163 | ui_print "- Resizing $IMG to ${newSizeM}M" 164 | $MAGISKBIN/magisk --resizeimg $IMG $newSizeM 165 | fi 166 | else 167 | newSizeM=$((reqSizeM / 32 * 32 + 64)); 168 | ui_print "- Creating $IMG with size ${newSizeM}M" 169 | $MAGISKBIN/magisk --createimg $IMG $newSizeM 170 | fi 171 | 172 | ui_print "- Mounting $IMG to $MOUNTPATH" 173 | MAGISKLOOP=`$MAGISKBIN/magisk --mountimg $IMG $MOUNTPATH` 174 | is_mounted $MOUNTPATH || abort "! $IMG mount failed..." 175 | 176 | if [ "$(cat $MODPATH/module.prop)" == "$(cat $INSTALLER/module.prop)" ]; then 177 | ACTION="Uninstall" 178 | else 179 | ACTION="Install" 180 | fi 181 | 182 | if [ "$ACTION" == "Install" ]; then 183 | 184 | # Create mod paths 185 | rm -rf $MODPATH 2>/dev/null 186 | mkdir -p $MODPATH 187 | 188 | # Copy files 189 | ui_print "- Copying files" 190 | unzip -o "$ZIP" 'system/*' -d $MODPATH 2>/dev/null 191 | unzip -o "$ZIP" 'wget' -d $MODPATH 2>/dev/null 192 | 193 | # Handle replace folders 194 | for TARGET in $REPLACE; do 195 | mktouch $MODPATH$TARGET/.replace 196 | done 197 | 198 | # Auto Mount 199 | $AUTOMOUNT && touch $MODPATH/auto_mount 200 | 201 | # prop files 202 | $PROPFILE && cp -af $INSTALLER/common/system.prop $MODPATH/system.prop 203 | 204 | # Module info 205 | cp -af $INSTALLER/module.prop $MODPATH/module.prop 206 | if $BOOTMODE; then 207 | # Update info for Magisk Manager 208 | mktouch /magisk/$MODID/update 209 | cp -af $INSTALLER/module.prop /magisk/$MODID/module.prop 210 | fi 211 | 212 | # post-fs-data mode scripts 213 | $POSTFSDATA && cp -af $INSTALLER/common/post-fs-data.sh $MODPATH/post-fs-data.sh 214 | 215 | # service mode scripts 216 | $LATESTARTSERVICE && cp -af $INSTALLER/common/service.sh $MODPATH/service.sh 217 | 218 | # ReUninstall apps 219 | reinstall 220 | 221 | ui_print "- Setting permissions" 222 | set_permissions 223 | 224 | else 225 | 226 | # Uninstall module 227 | ui_print "- ! Current Version of Module Detected ! Uninstalling" 228 | rm -rf $MODPATH 2>/dev/null 229 | rm -rf /magisk/$MODID 230 | 231 | fi 232 | ########################################################################################## 233 | # Finalizing 234 | ########################################################################################## 235 | 236 | $MAGISKBIN/magisk --umountimg $MOUNTPATH $MAGISKLOOP 237 | rmdir $MOUNTPATH 238 | 239 | # Shrink the image if possible 240 | image_size_check $IMG 241 | newSizeM=$((curUsedM / 32 * 32 + 64)) 242 | if [ $curSizeM -gt $newSizeM ]; then 243 | ui_print "- Shrinking $IMG to ${newSizeM}M" 244 | $MAGISKBIN/magisk --resizeimg $IMG $newSizeM 245 | fi 246 | 247 | $BOOTMODE || recovery_cleanup 248 | 249 | if [ $isABDevice == true ]; then 250 | mount -o ro /system 2>/dev/null 251 | mount -o ro /vendor 2>/dev/null 252 | fi 253 | 254 | ui_print "- Done" 255 | exit 0 256 | -------------------------------------------------------------------------------- /META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Terminal App Systemizer 2 | Systemize your App systemlessly! 3 | Using terminal emulator. 4 | Enter this command and choose the app you want to systemize. 5 | 6 | systemize_magisk 7 | 8 | And Reboot to apply changes. -------------------------------------------------------------------------------- /common/aapt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veez21/terminal_app_systemizer/c690738ff0ec0cf58d895ca12ed9ffc8e129b13f/common/aapt -------------------------------------------------------------------------------- /common/file_contexts_image: -------------------------------------------------------------------------------- 1 | /magisk(/.*)? u:object_r:system_file:s0 2 | -------------------------------------------------------------------------------- /common/post-fs-data.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # Please don't hardcode /magisk/modname/... ; instead, please use $MODDIR/... 3 | # This will make your scripts compatible even if Magisk change its mount point in the future 4 | MODDIR=${0%/*} 5 | 6 | # This script will be executed in post-fs-data mode 7 | # More info in the main Magisk thread 8 | -------------------------------------------------------------------------------- /common/service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # Please don't hardcode /magisk/modname/... ; instead, please use $MODDIR/... 3 | # This will make your scripts compatible even if Magisk change its mount point in the future 4 | MODDIR=${0%/*} 5 | 6 | # This script will be executed in late_start service mode 7 | # More info in the main Magisk thread 8 | -------------------------------------------------------------------------------- /common/system.prop: -------------------------------------------------------------------------------- 1 | # This file will be read by resetprop 2 | # Example: Change dpi 3 | # ro.sf.lcd_density=320 4 | -------------------------------------------------------------------------------- /config.sh: -------------------------------------------------------------------------------- 1 | ########################################################################################## 2 | # 3 | # Magisk 4 | # by topjohnwu 5 | # 6 | # This is a template zip for developers 7 | # 8 | ########################################################################################## 9 | ########################################################################################## 10 | # 11 | # Instructions: 12 | # 13 | # 1. Place your files into system folder (delete the placeholder file) 14 | # 2. Fill in your module's info into module.prop 15 | # 3. Configure the settings in this file (common/config.sh) 16 | # 4. For advanced features, add shell commands into the script files under common: 17 | # post-fs-data.sh, service.sh 18 | # 5. For changing props, add your additional/modified props into common/system.prop 19 | # 20 | ########################################################################################## 21 | 22 | ########################################################################################## 23 | # Defines 24 | ########################################################################################## 25 | 26 | # NOTE: This part has to be adjusted to fit your own needs 27 | 28 | # This will be the folder name under /magisk 29 | # This should also be the same as the id in your module.prop to prevent confusion 30 | MODID=terminal_systemizer 31 | 32 | # Set to true if you need to enable Magic Mount 33 | # Most mods would like it to be enabled 34 | AUTOMOUNT=true 35 | 36 | # Set to true if you need to load system.prop 37 | PROPFILE=false 38 | 39 | # Set to true if you need post-fs-data script 40 | POSTFSDATA=false 41 | 42 | # Set to true if you need late_start service script 43 | LATESTARTSERVICE=false 44 | 45 | ########################################################################################## 46 | # Installation Message 47 | ########################################################################################## 48 | 49 | # Set what you want to show when installing your mod 50 | 51 | print_modname() { 52 | ui_print "******************************" 53 | ui_print " Terminal App Systemizer " 54 | ui_print " by veez21 @ xda-developers " 55 | ui_print "******************************" 56 | } 57 | 58 | ########################################################################################## 59 | # Replace list 60 | ########################################################################################## 61 | 62 | # List all directories you want to directly replace in the system 63 | # By default Magisk will merge your files with the original system 64 | # Directories listed here however, will be directly mounted to the correspond directory in the system 65 | 66 | # You don't need to remove the example below, these values will be overwritten by your own list 67 | # This is an example 68 | REPLACE=" 69 | /system/app/Youtube 70 | /system/priv-app/SystemUI 71 | /system/priv-app/Settings 72 | /system/framework 73 | " 74 | 75 | # Construct your own list here, it will overwrite the example 76 | # !DO NOT! remove this if you don't need to replace anything, leave it empty as it is now 77 | REPLACE=" 78 | " 79 | 80 | ########################################################################################## 81 | # Permissions 82 | ########################################################################################## 83 | 84 | # NOTE: This part has to be adjusted to fit your own needs 85 | 86 | set_permissions() { 87 | # Default permissions, don't remove them 88 | set_perm_recursive $MODPATH 0 0 0755 0644 89 | 90 | # Only some special files require specific permissions 91 | # The default permissions should be good enough for most cases 92 | 93 | # Some templates if you have no idea what to do: 94 | 95 | # set_perm_recursive (default: u:object_r:system_file:s0) 96 | # set_perm_recursive $MODPATH/system/lib 0 0 0755 0644 97 | 98 | # set_perm (default: u:object_r:system_file:s0) 99 | # set_perm $MODPATH/system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 100 | # set_perm $MODPATH/system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 101 | # set_perm $MODPATH/system/lib/libart.so 0 0 0644 102 | cp -af $INSTALLER/common/aapt $MODPATH/aapt 103 | set_perm $MODPATH/system/bin/systemize 0 0 0777 104 | set_perm $MODPATH/aapt 0 0 0777 105 | } 106 | 107 | detect_installed() { 108 | no_app=0 109 | no_privapp=0 110 | all_apk_size=0 111 | mkdir -p $TMPDIR/$MODID/system 112 | mkdir -p $TMPDIR/$MODID/system/app 113 | mkdir -p $TMPDIR/$MODID/system/priv-app 114 | if [ -d /magisk/$MODID/system/app ]; then 115 | for i in $(find /magisk/$MODID/system/app -name *.apk -type f); do 116 | if [ "$1" != "size" ]; then 117 | cp -af ${i%/*} $TMPDIR/$MODID/system/app 118 | fi 119 | all_apk_size=$((all_apk_size+$(du $i | awk '{print $1}'))) 120 | done 121 | else 122 | no_app=1 123 | fi 124 | if [ -d /magisk/$MODID/system/priv-app ]; then 125 | for i in $(find /magisk/$MODID/system/priv-app -name *.apk -type f); do 126 | if [ "$1" != "size" ]; then 127 | cp -af ${i%/*} $TMPDIR/$MODID/system/priv-app 128 | fi 129 | all_apk_size=$((all_apk_size+$(du $i | awk '{print $1}'))) 130 | done 131 | else 132 | no_privapp=1 133 | fi 134 | } 135 | 136 | reinstall() { 137 | if [ $no_app == 0 ]; then 138 | for i in $(find $TMPDIR/$MODID/system/app -name *.apk -type f); do 139 | app=${i%/*} 140 | mkdir -p /magisk/$MODID/system/app/${app##*/} 141 | cp -af $app/. /magisk/$MODID/system/app/${app##*/} 142 | done 143 | fi 144 | if [ $no_privapp == 0 ]; then 145 | for i in $(find $TMPDIR/$MODID/system/priv-app -name *.apk -type f); do 146 | app=${i%/*} 147 | mkdir -p /magisk/$MODID/system/priv-app/${app##*/} 148 | cp -af $app/. /magisk/$MODID/system/priv-app/${app##*/} 149 | done 150 | fi 151 | } 152 | -------------------------------------------------------------------------------- /module.prop: -------------------------------------------------------------------------------- 1 | id=terminal_systemizer 2 | name=Terminal Emulator App Systemizer 3 | version=v8.5 4 | versionCode=17 5 | author=veez21 6 | description=Turn apps to System Apps Systemlessly! (Using Terminal Emulator: systemize) 7 | template=1400 8 | -------------------------------------------------------------------------------- /system/bin/systemize: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # Terminal Magisk Mod Template 3 | # by veez21 @ xda-developers 4 | 5 | 6 | # Magisk Module ID ** 7 | # > ENTER MAGISK MODULE ID HERE 8 | ID="terminal_systemizer" 9 | 10 | #=========================== Set Log Files 11 | # > Logs should go in this file 12 | LOG=/magisk/${ID}/terminal.log 13 | # > Verbose output goes here 14 | VERLOG=/magisk/${ID}/verbose.log 15 | 16 | #=========================== Start Logging verbosely 17 | set -x 2>$VERLOG 18 | 19 | #=========================== Set Busybox (Used by Magisk) up 20 | # > Do not touch! 21 | if [ -f /data/magisk/busybox ]; then 22 | alias busybox=/data/magisk/busybox 23 | for i in $(busybox --list); do 24 | if [ $i != 'echo' ]; then 25 | alias $i="/data/magisk/busybox $i" 26 | fi 27 | done 28 | elif [ -f /data/data/com.topjohnwu.magisk/lib/libbusybox.so ]; then 29 | cp /data/data/com.topjohnwu.magisk/lib/libbusybox.so /cache/busybox 30 | chmod 755 /cache/busybox; chown 0.0 /cache/busybox 31 | alias busybox=/cache/busybox 32 | for i in $(busybox --list); do 33 | if [ $i != 'echo' ]; then 34 | alias $i="/cache/busybox $i" 35 | fi 36 | done 37 | else 38 | alias busybox="" 39 | fi 40 | if [ -x /system/xbin/busybox ]; then 41 | true 42 | elif [ -x /system/bin/busybox ]; then 43 | true 44 | elif [ -x /data/data/com.topjohnwu.magisk/busybox/busybox ]; then 45 | export PATH=$PATH:/data/data/com.topjohnwu.magisk/busybox 46 | else 47 | echo "! Busybox not detected.." 48 | echo "Please install one (@osm0sis' busybox recommended)" 49 | false 50 | fi 51 | [ $? -ne 0 ] && exit $? 52 | 53 | #=========================== Default Functions 54 | 55 | # get_file_prop 56 | get_file_prop() { 57 | _prop=$(grep "$1=" $2) 58 | echo ${_prop#*=} 59 | unset _prop 60 | } 61 | 62 | # set_file_prop 63 | set_file_prop() { 64 | sed -i "s/${1}=.*/${1}=${2}/g" $3 65 | } 66 | 67 | # mktouch 68 | mktouch() { 69 | mkdir -p ${1%/*} 70 | if [ -z "$2" ]; then 71 | touch $1 72 | else 73 | echo $2 > $1 74 | fi 75 | chmod 644 $1 76 | } 77 | 78 | # runl 79 | runl() { 80 | echo "[$(date +"%F %T")]: $@" >> $LOG 2>>$LOG 81 | $@ 2>>$LOG 82 | return $? 83 | } 84 | 85 | #=========================== Default Variables 86 | # > Stuff here is used for some other stuff 87 | # > Edit only if necessary! 88 | 89 | # Magisk Mod Directory 90 | MODDIR="/magisk/$ID" 91 | # Version Number 92 | VER=$(get_file_prop version $MODDIR/module.prop) 93 | # Version Code 94 | REL=$(get_file_prop versionCode $MODDIR/module.prop) 95 | # Author 96 | AUTHOR=$(get_file_prop author $MODDIR/module.prop) 97 | # Mod Name/Title 98 | MODTITLE=$(get_file_prop name $MODDIR/module.prop) 99 | 100 | # Colors 101 | G='\e[01;32m' # GREEN 102 | R='\e[01;31m' # RED 103 | Y='\e[01;33m' # YELLOW 104 | B='\e[01;34m' # BLUE 105 | V='\e[01;35m' # VIOLET 106 | Bl='\e[01;30m' # BLACK 107 | C='\e[01;36m' # CYAN 108 | W='\e[01;37m' # WHITE 109 | N='\e[00;37;40m' # How to use (example): echo "${G}example${N}" 110 | 111 | # Divider (based on $MODTITLE, $VER, and $REL characters) 112 | div="${Bl}$(printf '%*s' "$(($(echo $MODTITLE | wc -c)+$(echo $VER | wc -c)+$(echo $REL | wc -c)))" '' | sed 's/ /=/g')${N}" 113 | 114 | #=========================== Main 115 | # > You can start your MOD here. 116 | # > You can add functions, variables & etc. 117 | # > Rather than editing the default vars above. 118 | 119 | 120 | # Terminal App Systemizer 121 | # by veez21 122 | clear 123 | echo "$div" 124 | echo "${W}$MODTITLE $VER${N}${Bl}($REL)${N}" 125 | echo "by ${W}$AUTHOR${N}" 126 | echo "$div" 127 | 128 | use_aapt=0 129 | sysapp=0 130 | privapp=0 131 | perm_xml1=/system/etc/permissions/privapp-permissions-platform.xml 132 | perm_xml=$MODDIR/system/etc/permissions/privapp-permissions-platform.xml 133 | if [ -f $perm_xml1 ]; then patch_xml=true; else patch_xml=false; fi 134 | mkdir -p $MODDIR/system/etc/permissions 2>/dev/null 135 | 136 | # Use aapt if present 137 | if [ -x /system/bin/aapt ] || [ -x /system/xbin/aapt ] || [ -x /sbin/aapt ] || [ -x $MODDIR/aapt ]; then 138 | export PATH=$PATH:$MODDIR 139 | use_aapt=1 140 | fi 141 | 142 | # Detect if /system/app is available 143 | if [ -d /system/app ]; then 144 | sysapp=1 145 | fi 146 | 147 | # Detect if /system/priv-app is available 148 | if [ -d /system/priv-app ]; then 149 | privapp=1 150 | fi 151 | 152 | # /magisk free space 153 | free_space="$(df -m /magisk | tail -n1 | awk '{print $4}')" 154 | total_space="$(df -m /magisk | tail -n1 | awk '{print $2}')" 155 | 156 | is_mounted() { 157 | if [ ! -z "$2" ]; then 158 | cat /proc/mounts | grep $1 | grep $2, >/dev/null 159 | else 160 | cat /proc/mounts | grep $1 >/dev/null 161 | fi 162 | return $? 163 | } 164 | 165 | mount_image() { 166 | if [ ! -d "$2" ]; then 167 | mount -o rw,remount rootfs / 168 | mkdir -p $2 2>/dev/null 169 | ($BOOTMODE) && mount -o ro,remount rootfs / 170 | [ ! -d "$2" ] && return 1 171 | fi 172 | if (! is_mounted $2); then 173 | LOOPDEVICE= 174 | for LOOP in 0 1 2 3 4 5 6 7; do 175 | if (! is_mounted $2); then 176 | LOOPDEVICE=/dev/block/loop$LOOP 177 | if [ ! -f "$LOOPDEVICE" ]; then 178 | mknod $LOOPDEVICE b 7 $LOOP 2>/dev/null 179 | fi 180 | losetup $LOOPDEVICE $1 181 | if [ "$?" -eq "0" ]; then 182 | mount -t ext4 -o loop $LOOPDEVICE $2 183 | if (! is_mounted $2); then 184 | /system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE $2 185 | fi 186 | if (! is_mounted $2); then 187 | /system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE $2 188 | fi 189 | fi 190 | if (is_mounted $2); then 191 | log_print "- Mounting $1 to $2" 192 | break; 193 | fi 194 | fi 195 | done 196 | fi 197 | } 198 | 199 | # List installed apps 200 | list_installed_apps() { 201 | c=1 202 | for i in $(ls /data/data); do 203 | if [[ ! "$(dumpsys package $i | grep system)" ]] && [[ ! "$(dumpsys package $i | grep "targetSdk=0")" ]]; then 204 | app[$c]=${i##*/} 205 | package=${app[$c]} 206 | package[$c]=$package 207 | dir_app[$c]=/data/app/${app[$c]}-*/base.apk 208 | if [ $use_aapt == 1 ]; then 209 | app=$(aapt dump badging ${dir_app[$c]} | grep 'application-label:') 210 | app[$c]=${app#*:} 211 | fi 212 | app[$c]=$(echo ${app[$c]} | tr ' ' '_' | tr -d "'") 213 | c=$((c+1)) 214 | fi 215 | done 216 | } 217 | 218 | # Systemize function 219 | systemize() { 220 | runl echo "Transfering ${apk}($name) to '$1'..." 221 | sleep 0.3 222 | if [ -d /system/app/${name} ] || [ -d /system/priv-app/${name} ] || [ -d $MODDIR/system/app/${name} ] || [ -d $MODDIR/system/priv-app/${name} ]; then 223 | runl echo "App exists!" 224 | runl exit 5 225 | fi 226 | runl mkdir -p ${MODDIR}${1}/${name} 227 | runl cp -f $apkdir ${MODDIR}${1}/${name} 228 | runl chmod -R 755 ${MODDIR}${1}/${name} 229 | runl chmod 644 ${MODDIR}${1}/${name}/${apk} 230 | runl chown 0.0 ${MODDIR}${1}/${name}/${apk} 231 | sleep 0.3 232 | 233 | $patch_xml && { 234 | echo "Granting Permissions" 235 | pp=0 236 | #for i in $(dumpsys package $name | grep "android.permission."); do 237 | for i in $(aapt d permissions $apkdir | awk '{print $2}'); do 238 | pp=$((pp+1)) 239 | if [ $pp -ne 1 ]; then 240 | #app_perm=${i%:*} 241 | #app_perm[$pp]=$app_perm 242 | app_perm=${i#*=} 243 | app_perm[$pp]=$(echo $app_perm | tr -d "'") 244 | fi 245 | done 246 | echo " 247 | 248 | " >> $MODDIR/system/etc/permissions/privapp-permissions-${name}.xml 249 | 250 | 251 | for i in ${app_perm[@]}; do 252 | echo " " >> $MODDIR/system/etc/permissions/privapp-permissions-${name}.xml 253 | done 254 | 255 | echo " 256 | " >> $MODDIR/system/etc/permissions/privapp-permissions-${name}.xml 257 | 258 | chmod 644 $MODDIR/system/etc/permissions/privapp-permissions-${name}.xml 259 | 260 | } 261 | 262 | sleep 0.3 263 | runl echo "Reboot to apply changes" 264 | runl exit 265 | } 266 | 267 | # APK systemizer function 268 | enter_apk_dir() { 269 | echo -n "Enter APK Path:" 270 | runl read apkdir 271 | runl echo "Checking if file exists..." 272 | sleep 0.3 273 | if [ -f "$apkdir" ]; then 274 | runl echo " - OK" 275 | sleep 0.3 276 | apk=${apkdir##*/} 277 | runl echo "Checking if file is an APK..." 278 | sleep 0.3 279 | tmpapk=${apk##*.} 280 | if [ "$tmpapk" == "apk" ]; then 281 | runl echo " - OK" 282 | sleep 0.3 283 | runl echo "Checking package name..." 284 | sleep 0.3 285 | name=${apk%'.apk'*} 286 | if [ $use_aapt == 1 ]; then 287 | name=$(aapt dump badging $apkdir | head -n1 | awk '{print $2}') 288 | name=${name#*=} 289 | fi 290 | name=$(echo $name | tr -d ' ' | tr -d "'") 291 | runl echo " - $name" 292 | sleep 0.3 293 | runl echo "Checking APK size..." 294 | sleep 0.3 295 | if [ $(du -m $apkdir | awk '{print $1}') -gt $free_space ]; then 296 | runl echo " - Insufficient /magisk space! APK size: $(du -m $apkdir | awk '{print $1}')M | /magisk Free: ${free_space}M" 297 | runl echo " - Using magisk_merge.img to merge images..." 298 | merge_img $apkdir 2>>$LOG 299 | else 300 | runl echo " - $(du -m $apkdir | awk '{print $1}')M" 301 | fi 302 | sleep 0.3 303 | if [ $privapp == 1 ] && [ $sysapp == 1 ]; then 304 | echo "Where to install?" 305 | echo -n "< 1 - /system/app | 2 - /system/priv-app > : " 306 | read loc 307 | if [ "$loc" == 1 ]; then 308 | systemize /system/app 309 | elif [ "$loc" == 2 ]; then 310 | systemize /system/priv-app 311 | else 312 | echo "Invalid!" 313 | exit 3 314 | fi 315 | elif [ $sysapp == 1 ] && [ $privapp == 0 ]; then 316 | systemize /system/app 317 | elif [ $privapp == 1 ] && [ $sysapp == 0 ]; then 318 | systemize /system/priv-app 319 | else 320 | runl echo "No installation directory!" 321 | runl exit 4 322 | fi 323 | else 324 | runl echo "$apk is not an APK!" 325 | runl exit 2 326 | fi 327 | else 328 | runl echo "$apkdir doesn't exist!" 329 | runl exit 1 330 | fi 331 | } 332 | 333 | enter_apk_name() { 334 | echo "Enter the App Label of the installed app" 335 | echo -n " > " 336 | runl read apklabel 337 | if [ ! "$apklabel" ]; then 338 | echo "error" 339 | exit 1 340 | fi 341 | echo "Checking if $apklabel is installed" 342 | list_installed_apps 2>$LOG 343 | c=1 344 | for i in ${package[@]}; do 345 | [ "$apklabel" == "$i" ] && { 346 | c=$((c+1)) 347 | break 348 | } || { 349 | c=$((c+1)) 350 | false 351 | } 352 | done 353 | if [ $? -eq 0 ]; then 354 | echo " - OK" 355 | runl echo "Checking APK size..." 356 | sleep 0.3 357 | dir_app=$(echo /data/app/${apklabel}-*/base.apk) 358 | if [ $(du -m $dir_app | awk '{print $1}') -gt $free_space ]; then 359 | runl echo " - Insufficient /magisk space!" 360 | runl echo " - APK size: $(du -m $dir_app | awk '{print $1}')M | /magisk Free: ${free_space}M" 361 | runl echo " - Using magisk_merge.img to merge images..." 362 | merge_img ${dir_app} 2>>$LOG 363 | else 364 | runl echo " - $(du -m $dir_app | awk '{print $1}')M" 365 | fi 366 | if [ -d /system/priv-app ]; then 367 | installdir="priv-app" 368 | else 369 | installdir="app" 370 | fi 371 | echo "Copying APK file of $apklabel" 372 | mkdir -p $MODDIR/system/$installdir/$apklabel 373 | cp -af $dir_app $MODDIR/system/$installdir/$apklabel 374 | [ $? -ne 0 ] && echo "Failed!" && exit 1 375 | else 376 | echo "Failed!" 377 | exit 1 378 | fi 379 | echo " - OK" 380 | chown -R 0.0 $MODDIR/system/${installdir}/$apklabel 381 | chmod 755 $MODDIR/system/${installdir}/$apklabel 382 | chmod 644 $MODDIR/system/${installdir}/$apklabel/base.apk 383 | echo "Done" 384 | echo "Reboot device to apply changes" 385 | exit 386 | } 387 | 388 | revert_apps() { 389 | echo "$div" 390 | echo "Revert" 391 | echo "$div" 392 | echo "" 393 | echo "Loading..." 394 | cc=1 395 | for i in $(find $MODDIR -name "*.apk"); do 396 | rev_dir[$cc]=${i%/*} 397 | rev_label=${i%/*} 398 | rev_label[$cc]=${rev_label##*/} 399 | echo " $cc - ${rev_label[$cc]}" 400 | cc=$((cc+1)) 401 | done 402 | echo "" 403 | echo " 0 - Exit" 404 | echo -n "[CHOICE]: " 405 | read revert 406 | if [ "$revert" -gt ${#rev_label[@]} ] || [ "$revert" -lt 0 ] || [ "$revert" == "" ] || [ -n "$(echo $revert | tr -d '0-9')" ] ; then 407 | echo "Invalid!" 408 | exit 1 409 | elif [ "$revert" == 0 ]; then 410 | exit 411 | else 412 | echo "Reverting ${rev_label[$revert]}..." 413 | rm -rf ${rev_dir[$revert]} 414 | echo "Done! Reboot to apply changes" 415 | exit 416 | fi 417 | } 418 | 419 | # Merge 420 | merge_img() { 421 | f_contexts='/magisk(/.*)? u:object_r:system_file:s0' 422 | apk_size=$(($(du -m $1 | awk '{print $1}')+2)) 423 | merge_img=/data/magisk_merge.img 424 | install_dir=/dev/tmp/${ID} 425 | path=/dev/magisk_merge 426 | tmpmodpath=$path/${ID} 427 | 428 | mkdir -p $install_dir 429 | 430 | SIZE=$((apk_size/32*32+64)) 431 | echo "$f_contexts" > $install_dir/file_contexts_image 432 | make_ext4fs -l ${SIZE}M -a /magisk -S $install_dir/file_contexts_image $merge_img >> $LOG 433 | 434 | mount_image $merge_img $path 435 | if ! is_mounted $path; then 436 | runl echo "magisk_merge.img not mounted!" 437 | runl exit 1 438 | fi 439 | 440 | cp -af $MODDIR/. $tmpmodpath 441 | MODDIR=$tmpmodpath 442 | } 443 | 444 | 445 | mount -o remount,rw /magisk 2>/dev/null 446 | mount -o rw,remount /magisk 2>/dev/null 447 | busybox mount -o remount,rw /magisk 2>/dev/null 448 | busybox mount -o rw,remount /magisk 2>/dev/null 449 | 450 | echo "" 451 | echo " 1 - Systemize Installed Apps (Listed)" 452 | echo " 2 - Systemize Installed Apps (Enter label) " 453 | echo " 3 - Systemize given APK" 454 | if [[ $(find $MODDIR -name "*.apk" 2>/dev/null) ]]; then 455 | echo " 4 - Revert Systemized Apps" 456 | fi 457 | echo " d - ${C}Donate${N}" 458 | echo " 0 - Exit" 459 | echo "" 460 | echo -n "[CHOICE]: " 461 | runl read choice 462 | if [ "$choice" == 1 ]; then 463 | clear 464 | echo "$div" 465 | echo "Installed Apps" 466 | echo "$div" 467 | echo "" 468 | echo "Loading Apps..." 469 | list_installed_apps 2>/dev/null 470 | for i in $(seq 1 $((${#app[@]}-1))); do 471 | echo " ${Bl}$i${N} - ${W}${app[$i]}${N}" | tr '_' ' ' 472 | done 473 | echo "" 474 | echo " 0 - Exit" 475 | echo -n "[CHOICE]: " 476 | runl read installed 477 | if [ "$installed" -gt ${#app[@]} ] || [ "$installed" -lt 0 ] || [ "$installed" == "" ] || [ -n "$(echo $installed | tr -d '0-9')" ] ; then 478 | runl echo "Invalid!" 479 | runl exit 1 480 | elif [ "$installed" == 0 ]; then 481 | runl exit 482 | else 483 | runl echo "Checking APK directory..." 484 | sleep 0.3 485 | if [ -f ${dir_app[$installed]} ]; then 486 | runl echo " - OK" 487 | sleep 0.3 488 | apkdir=${dir_app[$installed]} 489 | apk=${apkdir##*/} 490 | name=${apkdir%/*}; name=${name##*/} 491 | name=$(echo $name | tr -d ' ' | tr -d "'" | tr -d '*' | tr -d '-') 492 | runl echo "Checking package name..." 493 | sleep 0.3 494 | runl echo " - $name" 495 | sleep 0.3 496 | runl echo "Checking APK size..." 497 | sleep 0.3 498 | if [ $(du -m $apkdir | awk '{print $1}') -gt $free_space ]; then 499 | runl echo " - Insufficient /magisk space!" 500 | runl echo " - APK size: $(du -m $apkdir | awk '{print $1}')M | /magisk Free: ${free_space}M" 501 | runl echo " - Using magisk_merge.img to merge images..." 502 | merge_img $apkdir 2>>$LOG 503 | else 504 | runl echo " - $(du -m $apkdir | awk '{print $1}')M" 505 | fi 506 | sleep 0.3 507 | if [ $privapp == 1 ] && [ $sysapp == 1 ]; then 508 | echo "Where to install?" 509 | echo -n "< 1 - /system/app | 2 - /system/priv-app > : " 510 | read loc 511 | if [ "$loc" == 1 ]; then 512 | systemize /system/app 513 | elif [ "$loc" == 2 ]; then 514 | systemize /system/priv-app 515 | else 516 | runl echo "Invalid!" 517 | runl exit 3 518 | fi 519 | elif [ $sysapp == 1 ] && [ $privapp == 0 ]; then 520 | systemize /system/app 521 | elif [ $privapp == 1 ] && [ $sysapp == 0 ]; then 522 | systemize /system/priv-app 523 | else 524 | runl echo "No installation directory!" 525 | runl exit 4 526 | fi 527 | else 528 | runl echo "APK doesn't exist!" 529 | runl exit 6 530 | fi 531 | fi 532 | elif [ "$choice" == 2 ]; then 533 | clear 534 | runl enter_apk_name 535 | runl exit $? 536 | elif [ "$choice" == 3 ]; then 537 | clear 538 | runl enter_apk_dir 539 | runl exit $? 540 | elif [ "$choice" == 4 ]; then 541 | clear 542 | runl revert_apps 543 | runl exit $? 544 | 545 | elif [ "$choice" == "d" ] || [ "$choice" == "D" ]; then 546 | runl am start https://paypal.me/veez21 >/dev/null 547 | elif [ "$choice" == 0 ]; then 548 | runl exit 549 | else runl echo "Invalid!" 550 | runl exit 1 551 | fi 552 | -------------------------------------------------------------------------------- /system/bin/systemize_magisk: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # Terminal Magisk Mod Template 3 | # by veez21 @ xda-developers 4 | 5 | 6 | # Magisk Module ID ** 7 | # > ENTER MAGISK MODULE ID HERE 8 | ID="terminal_systemizer" 9 | 10 | #=========================== Set Log Files 11 | # > Logs should go in this file 12 | LOG=/magisk/${ID}/terminal.log 13 | # > Verbose output goes here 14 | VERLOG=/magisk/${ID}/verbose.log 15 | 16 | #=========================== Start Logging verbosely 17 | set -x 2>$VERLOG 18 | 19 | #=========================== Set Busybox (Used by Magisk) up 20 | # > Do not touch! 21 | if [ -f /data/magisk/busybox ]; then 22 | alias busybox=/data/magisk/busybox 23 | for i in $(busybox --list); do 24 | if [ $i != 'echo' ]; then 25 | alias $i="/data/magisk/busybox $i" 26 | fi 27 | done 28 | elif [ -f /data/data/com.topjohnwu.magisk/lib/libbusybox.so ]; then 29 | cp /data/data/com.topjohnwu.magisk/lib/libbusybox.so /cache/busybox 30 | chmod 755 /cache/busybox; chown 0.0 /cache/busybox 31 | alias busybox=/cache/busybox 32 | for i in $(busybox --list); do 33 | if [ $i != 'echo' ]; then 34 | alias $i="/cache/busybox $i" 35 | fi 36 | done 37 | else 38 | alias busybox="" 39 | fi 40 | if [ -x /system/xbin/busybox ]; then 41 | true 42 | elif [ -x /system/bin/busybox ]; then 43 | true 44 | elif [ -x /data/data/com.topjohnwu.magisk/busybox/busybox ]; then 45 | export PATH=$PATH:/data/data/com.topjohnwu.magisk/busybox 46 | else 47 | echo "! Busybox not detected.." 48 | echo "Please install one (@osm0sis' busybox recommended)" 49 | false 50 | fi 51 | [ $? -ne 0 ] && exit $? 52 | 53 | #=========================== Default Functions 54 | 55 | # get_file_prop 56 | get_file_prop() { 57 | _prop=$(grep "$1=" $2) 58 | echo ${_prop#*=} 59 | unset _prop 60 | } 61 | 62 | # set_file_prop 63 | set_file_prop() { 64 | sed -i "s/${1}=.*/${1}=${2}/g" $3 65 | } 66 | 67 | # mktouch 68 | mktouch() { 69 | mkdir -p ${1%/*} 70 | if [ -z "$2" ]; then 71 | touch $1 72 | else 73 | echo $2 > $1 74 | fi 75 | chmod 644 $1 76 | } 77 | 78 | # runl 79 | runl() { 80 | echo "[$(date +"%F %T")]: $@" >> $LOG 2>>$LOG 81 | $@ 2>>$LOG 82 | return $? 83 | } 84 | 85 | #=========================== Default Variables 86 | # > Stuff here is used for some other stuff 87 | # > Edit only if necessary! 88 | 89 | # Magisk Mod Directory 90 | MODDIR="/magisk/$ID" 91 | # Version Number 92 | VER=$(get_file_prop version $MODDIR/module.prop) 93 | # Version Code 94 | REL=$(get_file_prop versionCode $MODDIR/module.prop) 95 | # Author 96 | AUTHOR=$(get_file_prop author $MODDIR/module.prop) 97 | # Mod Name/Title 98 | MODTITLE=$(get_file_prop name $MODDIR/module.prop) 99 | 100 | # Colors 101 | G='\e[01;32m' # GREEN 102 | R='\e[01;31m' # RED 103 | Y='\e[01;33m' # YELLOW 104 | B='\e[01;34m' # BLUE 105 | V='\e[01;35m' # VIOLET 106 | Bl='\e[01;30m' # BLACK 107 | C='\e[01;36m' # CYAN 108 | W='\e[01;37m' # WHITE 109 | N='\e[00;37;40m' # How to use (example): echo "${G}example${N}" 110 | 111 | # Divider (based on $MODTITLE, $VER, and $REL characters) 112 | div="${Bl}$(printf '%*s' "$(($(echo $MODTITLE | wc -c)+$(echo $VER | wc -c)+$(echo $REL | wc -c)))" '' | sed 's/ /=/g')${N}" 113 | 114 | #=========================== Main 115 | # > You can start your MOD here. 116 | # > You can add functions, variables & etc. 117 | # > Rather than editing the default vars above. 118 | 119 | 120 | # Terminal App Systemizer 121 | # by veez21 122 | clear 123 | echo "$div" 124 | echo "${W}$MODTITLE $VER${N}${Bl}($REL)${N}" 125 | echo "by ${W}$AUTHOR${N}" 126 | echo "$div" 127 | 128 | use_aapt=0 129 | sysapp=0 130 | privapp=0 131 | perm_xml1=/system/etc/permissions/privapp-permissions-platform.xml 132 | perm_xml=$MODDIR/system/etc/permissions/privapp-permissions-platform.xml 133 | if [ -f $perm_xml1 ]; then patch_xml=true; else patch_xml=false; fi 134 | 135 | $patch_xml && { 136 | if [ ! -f $perm_xml ]; then 137 | mkdir -p $MODDIR/system/etc/permissions 2>/dev/null 138 | cp $perm_xml1 $perm_xml 139 | chmod -R 755 $MODDIR/system/etc/permissions 140 | chmod 644 $perm_xml 141 | fi 142 | } 143 | 144 | # Use aapt if present 145 | if [ -x /system/bin/aapt ] || [ -x /system/xbin/aapt ] || [ -x /sbin/aapt ] || [ -x $MODDIR/aapt ]; then 146 | export PATH=$PATH:$MODDIR 147 | use_aapt=1 148 | fi 149 | 150 | # Detect if /system/app is available 151 | if [ -d /system/app ]; then 152 | sysapp=1 153 | fi 154 | 155 | # Detect if /system/priv-app is available 156 | if [ -d /system/priv-app ]; then 157 | privapp=1 158 | fi 159 | 160 | # /magisk free space 161 | free_space="$(df -m /magisk | tail -n1 | awk '{print $4}')" 162 | total_space="$(df -m /magisk | tail -n1 | awk '{print $2}')" 163 | 164 | is_mounted() { 165 | if [ ! -z "$2" ]; then 166 | cat /proc/mounts | grep $1 | grep $2, >/dev/null 167 | else 168 | cat /proc/mounts | grep $1 >/dev/null 169 | fi 170 | return $? 171 | } 172 | 173 | mount_image() { 174 | if [ ! -d "$2" ]; then 175 | mount -o rw,remount rootfs / 176 | mkdir -p $2 2>/dev/null 177 | ($BOOTMODE) && mount -o ro,remount rootfs / 178 | [ ! -d "$2" ] && return 1 179 | fi 180 | if (! is_mounted $2); then 181 | LOOPDEVICE= 182 | for LOOP in 0 1 2 3 4 5 6 7; do 183 | if (! is_mounted $2); then 184 | LOOPDEVICE=/dev/block/loop$LOOP 185 | if [ ! -f "$LOOPDEVICE" ]; then 186 | mknod $LOOPDEVICE b 7 $LOOP 2>/dev/null 187 | fi 188 | losetup $LOOPDEVICE $1 189 | if [ "$?" -eq "0" ]; then 190 | mount -t ext4 -o loop $LOOPDEVICE $2 191 | if (! is_mounted $2); then 192 | /system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE $2 193 | fi 194 | if (! is_mounted $2); then 195 | /system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE $2 196 | fi 197 | fi 198 | if (is_mounted $2); then 199 | log_print "- Mounting $1 to $2" 200 | break; 201 | fi 202 | fi 203 | done 204 | fi 205 | } 206 | 207 | # List installed apps 208 | list_installed_apps() { 209 | c=1 210 | for i in $(ls /data/data); do 211 | if [[ ! "$(dumpsys package $i | grep system)" ]] && [[ ! "$(dumpsys package $i | grep "targetSdk=0")" ]]; then 212 | app[$c]=${i##*/} 213 | package=${app[$c]} 214 | package[$c]=$package 215 | dir_app[$c]=/data/app/${app[$c]}-*/base.apk 216 | if [ $use_aapt == 1 ]; then 217 | app=$(aapt dump badging ${dir_app[$c]} | grep 'application-label:') 218 | app[$c]=${app#*:} 219 | fi 220 | app[$c]=$(echo ${app[$c]} | tr ' ' '_' | tr -d "'") 221 | c=$((c+1)) 222 | fi 223 | done 224 | } 225 | 226 | # Systemize function 227 | systemize() { 228 | runl echo "Transfering ${apk}($name) to '$1'..." 229 | sleep 0.3 230 | if [ -d /system/app/${name} ] || [ -d /system/priv-app/${name} ] || [ -d $MODDIR/system/app/${name} ] || [ -d $MODDIR/system/priv-app/${name} ]; then 231 | runl echo "App exists!" 232 | runl exit 5 233 | fi 234 | runl mkdir -p ${MODDIR}${1}/${name} 235 | runl cp -f $apkdir ${MODDIR}${1}/${name} 236 | runl chmod -R 755 ${MODDIR}${1}/${name} 237 | runl chmod 644 ${MODDIR}${1}/${name}/${apk} 238 | runl chown 0.0 ${MODDIR}${1}/${name}/${apk} 239 | sleep 0.3 240 | $patch_xml && { 241 | echo "Patching $(basename $perm_xml)" 242 | pp=0 243 | #for i in $(dumpsys package $name | grep "android.permission."); do 244 | for i in $(aapt d permissions $apkdir | awk '{print $2}'); do 245 | pp=$((pp+1)) 246 | if [ $pp -ne 1 ]; then 247 | #app_perm=${i%:*} 248 | #app_perm[$pp]=$app_perm 249 | app_perm=${i#*=} 250 | app_perm[$pp]=$(echo $app_perm | tr -d "'") 251 | fi 252 | done 253 | remove_this=$(grep -n "" $perm_xml | tail -n1); remove_this=${remove_this%:*} 254 | sed -i "${remove_this}d" $perm_xml 255 | echo "\n " >> $perm_xml 256 | for i in ${app_perm[@]}; do 257 | echo " " >> $perm_xml 258 | done 259 | echo " <\privapp-permissions>" >> $perm_xml 260 | echo "" >> $perm_xml 261 | } 262 | sleep 0.3 263 | runl echo "Reboot to apply changes" 264 | runl exit 265 | } 266 | 267 | # APK systemizer function 268 | enter_apk_dir() { 269 | echo -n "Enter APK Path:" 270 | runl read apkdir 271 | runl echo "Checking if file exists..." 272 | sleep 0.3 273 | if [ -f "$apkdir" ]; then 274 | runl echo " - OK" 275 | sleep 0.3 276 | apk=${apkdir##*/} 277 | runl echo "Checking if file is an APK..." 278 | sleep 0.3 279 | tmpapk=${apk##*.} 280 | if [ "$tmpapk" == "apk" ]; then 281 | runl echo " - OK" 282 | sleep 0.3 283 | runl echo "Checking package name..." 284 | sleep 0.3 285 | name=${apk%'.apk'*} 286 | if [ $use_aapt == 1 ]; then 287 | name=$(aapt dump badging $apkdir | head -n1 | awk '{print $2}') 288 | name=${name#*=} 289 | fi 290 | name=$(echo $name | tr -d ' ' | tr -d "'") 291 | runl echo " - $name" 292 | sleep 0.3 293 | runl echo "Checking APK size..." 294 | sleep 0.3 295 | if [ $(du -m $apkdir | awk '{print $1}') -gt $free_space ]; then 296 | runl echo " - Insufficient /magisk space! APK size: $(du -m $apkdir | awk '{print $1}')M | /magisk Free: ${free_space}M" 297 | runl echo " - Using magisk_merge.img to merge images..." 298 | merge_img $apkdir 2>>$LOG 299 | else 300 | runl echo " - $(du -m $apkdir | awk '{print $1}')M" 301 | fi 302 | sleep 0.3 303 | if [ $privapp == 1 ] && [ $sysapp == 1 ]; then 304 | echo "Where to install?" 305 | echo -n "< 1 - /system/app | 2 - /system/priv-app > : " 306 | read loc 307 | if [ "$loc" == 1 ]; then 308 | systemize /system/app 309 | elif [ "$loc" == 2 ]; then 310 | systemize /system/priv-app 311 | else 312 | echo "Invalid!" 313 | exit 3 314 | fi 315 | elif [ $sysapp == 1 ] && [ $privapp == 0 ]; then 316 | systemize /system/app 317 | elif [ $privapp == 1 ] && [ $sysapp == 0 ]; then 318 | systemize /system/priv-app 319 | else 320 | runl echo "No installation directory!" 321 | runl exit 4 322 | fi 323 | else 324 | runl echo "$apk is not an APK!" 325 | runl exit 2 326 | fi 327 | else 328 | runl echo "$apkdir doesn't exist!" 329 | runl exit 1 330 | fi 331 | } 332 | 333 | enter_apk_name() { 334 | echo "Enter the App Label of the installed app" 335 | echo -n " > " 336 | runl read apklabel 337 | if [ ! "$apklabel" ]; then 338 | echo "error" 339 | exit 1 340 | fi 341 | echo "Checking if $apklabel is installed" 342 | list_installed_apps 2>$LOG 343 | c=1 344 | for i in ${package[@]}; do 345 | [ "$apklabel" == "$i" ] && { 346 | c=$((c+1)) 347 | break 348 | } || { 349 | c=$((c+1)) 350 | false 351 | } 352 | done 353 | if [ $? -eq 0 ]; then 354 | echo " - OK" 355 | runl echo "Checking APK size..." 356 | sleep 0.3 357 | dir_app=$(echo /data/app/${apklabel}-*/base.apk) 358 | if [ $(du -m $dir_app | awk '{print $1}') -gt $free_space ]; then 359 | runl echo " - Insufficient /magisk space!" 360 | runl echo " - APK size: $(du -m $dir_app | awk '{print $1}')M | /magisk Free: ${free_space}M" 361 | runl echo " - Using magisk_merge.img to merge images..." 362 | merge_img ${dir_app} 2>>$LOG 363 | else 364 | runl echo " - $(du -m $dir_app | awk '{print $1}')M" 365 | fi 366 | if [ -d /system/priv-app ]; then 367 | installdir="priv-app" 368 | else 369 | installdir="app" 370 | fi 371 | echo "Copying APK file of $apklabel" 372 | mkdir -p $MODDIR/system/$installdir/$apklabel 373 | cp -af $dir_app $MODDIR/system/$installdir/$apklabel 374 | [ $? -ne 0 ] && echo "Failed!" && exit 1 375 | else 376 | echo "Failed!" 377 | exit 1 378 | fi 379 | echo " - OK" 380 | chown -R 0.0 $MODDIR/system/${installdir}/$apklabel 381 | chmod 755 $MODDIR/system/${installdir}/$apklabel 382 | chmod 644 $MODDIR/system/${installdir}/$apklabel/base.apk 383 | echo "Done" 384 | echo "Reboot device to apply changes" 385 | exit 386 | } 387 | 388 | # Merge 389 | merge_img() { 390 | f_contexts='/magisk(/.*)? u:object_r:system_file:s0' 391 | apk_size=$(($(du -m $1 | awk '{print $1}')+2)) 392 | merge_img=/data/magisk_merge.img 393 | install_dir=/dev/tmp/${ID} 394 | path=/dev/magisk_merge 395 | tmpmodpath=$path/${ID} 396 | 397 | mkdir -p $install_dir 398 | 399 | SIZE=$((apk_size/32*32+64)) 400 | echo "$f_contexts" > $install_dir/file_contexts_image 401 | make_ext4fs -l ${SIZE}M -a /magisk -S $install_dir/file_contexts_image $merge_img >> $LOG 402 | 403 | mount_image $merge_img $path 404 | if ! is_mounted $path; then 405 | runl echo "magisk_merge.img not mounted!" 406 | runl exit 1 407 | fi 408 | 409 | cp -af $MODDIR/. $tmpmodpath 410 | MODDIR=$tmpmodpath 411 | } 412 | 413 | 414 | mount -o remount,rw /magisk 2>/dev/null 415 | mount -o rw,remount /magisk 2>/dev/null 416 | busybox mount -o remount,rw /magisk 2>/dev/null 417 | busybox mount -o rw,remount /magisk 2>/dev/null 418 | 419 | echo "" 420 | echo " 1 - Systemize Installed Apps (Listed)" 421 | echo " 2 - Systemize Installed Apps (Enter label) " 422 | echo " 3 - Systemize given APK" 423 | echo " 0 - Exit" 424 | echo "" 425 | echo -n "[CHOICE]: " 426 | runl read choice 427 | if [ "$choice" == 1 ]; then 428 | clear 429 | echo "$div" 430 | echo "Installed Apps" 431 | echo "$div" 432 | echo "" 433 | echo "Loading Apps..." 434 | list_installed_apps 2>/dev/null 435 | for i in $(seq 1 $((${#app[@]}-1))); do 436 | echo " $i - ${app[$i]}" | tr '_' ' ' 437 | done 438 | echo "" 439 | echo " 0 - Exit" 440 | echo -n "[CHOICE]: " 441 | runl read installed 442 | if [ "$installed" -gt ${#app[@]} ] || [ "$installed" -lt 0 ] || [ "$installed" == "" ] || [ -n "$(echo $installed | tr -d '0-9')" ] ; then 443 | runl echo "Invalid!" 444 | runl exit 1 445 | elif [ "$installed" == 0 ]; then 446 | runl exit 447 | else 448 | runl echo "Checking APK directory..." 449 | sleep 0.3 450 | if [ -f ${dir_app[$installed]} ]; then 451 | runl echo " - OK" 452 | sleep 0.3 453 | apkdir=${dir_app[$installed]} 454 | apk=${apkdir##*/} 455 | name=${apkdir%/*}; name=${name##*/} 456 | name=$(echo $name | tr -d ' ' | tr -d "'" | tr -d '*' | tr -d '-') 457 | runl echo "Checking package name..." 458 | sleep 0.3 459 | runl echo " - $name" 460 | sleep 0.3 461 | runl echo "Checking APK size..." 462 | sleep 0.3 463 | if [ $(du -m $apkdir | awk '{print $1}') -gt $free_space ]; then 464 | runl echo " - Insufficient /magisk space!" 465 | runl echo " - APK size: $(du -m $apkdir | awk '{print $1}')M | /magisk Free: ${free_space}M" 466 | runl echo " - Using magisk_merge.img to merge images..." 467 | merge_img $apkdir 2>>$LOG 468 | else 469 | runl echo " - $(du -m $apkdir | awk '{print $1}')M" 470 | fi 471 | sleep 0.3 472 | if [ $privapp == 1 ] && [ $sysapp == 1 ]; then 473 | echo "Where to install?" 474 | echo -n "< 1 - /system/app | 2 - /system/priv-app > : " 475 | read loc 476 | if [ "$loc" == 1 ]; then 477 | systemize /system/app 478 | elif [ "$loc" == 2 ]; then 479 | systemize /system/priv-app 480 | else 481 | runl echo "Invalid!" 482 | runl exit 3 483 | fi 484 | elif [ $sysapp == 1 ] && [ $privapp == 0 ]; then 485 | systemize /system/app 486 | elif [ $privapp == 1 ] && [ $sysapp == 0 ]; then 487 | systemize /system/priv-app 488 | else 489 | runl echo "No installation directory!" 490 | runl exit 4 491 | fi 492 | else 493 | runl echo "APK doesn't exist!" 494 | runl exit 6 495 | fi 496 | fi 497 | elif [ "$choice" == 2 ]; then 498 | clear 499 | runl enter_apk_name 500 | runl exit $? 501 | elif [ "$choice" == 3 ]; then 502 | clear 503 | runl enter_apk_dir 504 | runl exit $? 505 | 506 | 507 | elif [ "$choice" == 0 ]; then 508 | runl exit 509 | else runl echo "Invalid!" 510 | runl exit 1 511 | fi 512 | -------------------------------------------------------------------------------- /update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | ########################################################################################## 3 | # 4 | # Magisk Module Template Install Script 5 | # by topjohnwu 6 | # 7 | ########################################################################################## 8 | 9 | # Detect whether in boot mode 10 | ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false 11 | $BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true 12 | 13 | # Default permissions 14 | umask 022 15 | 16 | ########################################################################################## 17 | # Flashable update-binary preparation 18 | ########################################################################################## 19 | 20 | # DETERMINE IF PIXEL (A/B OTA) DEVICE 21 | ABDeviceCheck=$(cat /proc/cmdline | grep slot_suffix | wc -l) 22 | if [ "$ABDeviceCheck" -gt 0 ]; then 23 | isABDevice=true 24 | SYSTEM=/system/system 25 | else 26 | isABDevice=false 27 | SYSTEM=/system 28 | fi 29 | 30 | OUTFD=$2 31 | ZIP=$3 32 | 33 | ui_print() { 34 | if $BOOTMODE; then 35 | echo "$1" 36 | else 37 | echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD 38 | echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD 39 | fi 40 | } 41 | 42 | is_mounted() { 43 | if [ ! -z "$2" ]; then 44 | cat /proc/mounts | grep $1 | grep $2, >/dev/null 45 | else 46 | cat /proc/mounts | grep $1 >/dev/null 47 | fi 48 | return $? 49 | } 50 | 51 | require_new_magisk() { 52 | ui_print "***********************************" 53 | ui_print "! $MAGISKBIN isn't setup properly!" 54 | ui_print "! Please install Magisk v14.0+!" 55 | ui_print "***********************************" 56 | exit 1 57 | } 58 | 59 | # Mount /data and /cache to access MAGISKBIN 60 | mount /data 2>/dev/null 61 | mount /cache 2>/dev/null 62 | 63 | # This path should work in any cases 64 | TMPDIR=/dev/tmp 65 | MOUNTPATH=/magisk 66 | INSTALLER=$TMPDIR/install 67 | if is_mounted /data; then 68 | IMG=/data/magisk.img 69 | MAGISKBIN=/data/magisk 70 | if $BOOTMODE; then 71 | MOUNTPATH=/dev/magisk_merge 72 | IMG=/data/magisk_merge.img 73 | fi 74 | else 75 | IMG=/cache/magisk.img 76 | MAGISKBIN=/cache/data_bin 77 | ui_print "- Data unavailable, using cache workaround" 78 | fi 79 | 80 | # Utility functions must exist 81 | [ -f $MAGISKBIN/util_functions.sh ] || require_new_magisk 82 | # Load utility fuctions 83 | . $MAGISKBIN/util_functions.sh 84 | get_outfd 85 | 86 | rm -rf $TMPDIR 2>/dev/null 87 | mkdir -p $INSTALLER 88 | # Extract common files 89 | unzip -o "$ZIP" module.prop config.sh 'common/*' -d $INSTALLER 2>/dev/null 90 | 91 | ########################################################################################## 92 | # Prepare 93 | ########################################################################################## 94 | 95 | [ ! -f $INSTALLER/config.sh ] && abort "! Unable to extract zip file!" 96 | # Load configurations 97 | . $INSTALLER/config.sh 98 | 99 | # Check the min magisk version 100 | MIN_VER=`grep_prop template $INSTALLER/module.prop` 101 | [ ! -z $MAGISK_VER_CODE -a $MAGISK_VER_CODE -ge $MIN_VER ] || require_new_magisk 102 | MODID=`grep_prop id $INSTALLER/module.prop` 103 | MODPATH=$MOUNTPATH/$MODID 104 | 105 | # Print mod name 106 | print_modname 107 | 108 | # Please leave this message in your flashable zip for credits :) 109 | ui_print "******************************" 110 | ui_print "Powered by Magisk (@topjohnwu)" 111 | ui_print "******************************" 112 | 113 | SPACE=" " 114 | if [ $isABDevice == true ]; then 115 | ui_print " ! A/B OTA device detected!" 116 | WRITE=rw 117 | SPACE=" " 118 | elif [ -f /data/magisk.img ] || [ -f /cache/magisk.img ] || [ -d /magisk ]; then 119 | WRITE=ro 120 | elif [ ! -f /data/magisk.img ] || [ ! -f /cache/magisk.img ] || [ ! -d /magisk ]; then 121 | WRITE=rw 122 | fi 123 | 124 | ui_print "$SPACE Mounting /system($WRITE)..." 125 | mount -o $WRITE /system 2>/dev/null 126 | ui_print "$SPACE Mounting /vendor($WRITE)..." 127 | mount -o $WRITE /vendor 2>/dev/null 128 | 129 | if [ $isABDevice == true ] || [ ! -d $SYSTEM/vendor ]; then 130 | VENDOR=/vendor 131 | else 132 | VENDOR=$SYSTEM/vendor 133 | fi 134 | 135 | if is_mounted /data; then 136 | [ ! -f /data/magisk.img ] && abort "! Magisk is not installed" 137 | else 138 | [ ! -f /cache/magisk.img ] && abort "! Magisk is not installed" 139 | fi 140 | $BOOTMODE && ! is_mounted /magisk && abort "! Magisk is not activated!" 141 | [ ! -f $SYSTEM/build.prop ] && abort "! $SYSTEM could not be mounted!" 142 | 143 | # Detect version and architecture 144 | api_level_arch_detect 145 | 146 | # You can get the Android API version from $API, the CPU architecture from $ARCH 147 | # Useful if you are creating Android version / platform dependent mods 148 | 149 | # We need busybox/binaries to be setup 150 | $BOOTMODE && boot_actions || recovery_actions 151 | 152 | ########################################################################################## 153 | # Install 154 | ########################################################################################## 155 | 156 | request_zip_size_check "$ZIP" 157 | 158 | if [ -f "$IMG" ]; then 159 | ui_print "- Found $IMG" 160 | image_size_check $IMG 161 | if [ "$reqSizeM" -gt "$curFreeM" ]; then 162 | newSizeM=$(((reqSizeM + curUsedM) / 32 * 32 + 64)) 163 | ui_print "- Resizing $IMG to ${newSizeM}M" 164 | $MAGISKBIN/magisk --resizeimg $IMG $newSizeM 165 | fi 166 | else 167 | newSizeM=$((reqSizeM / 32 * 32 + 64)); 168 | ui_print "- Creating $IMG with size ${newSizeM}M" 169 | $MAGISKBIN/magisk --createimg $IMG $newSizeM 170 | fi 171 | 172 | ui_print "- Mounting $IMG to $MOUNTPATH" 173 | MAGISKLOOP=`$MAGISKBIN/magisk --mountimg $IMG $MOUNTPATH` 174 | is_mounted $MOUNTPATH || abort "! $IMG mount failed..." 175 | 176 | if [ "$(cat $MODPATH/module.prop)" == "$(cat $INSTALLER/module.prop)" ]; then 177 | ACTION="Uninstall" 178 | else 179 | ACTION="Install" 180 | fi 181 | 182 | if [ "$ACTION" == "Install" ]; then 183 | 184 | # Create mod paths 185 | rm -rf $MODPATH 2>/dev/null 186 | mkdir -p $MODPATH 187 | 188 | # Copy files 189 | ui_print "- Copying files" 190 | unzip -o "$ZIP" 'system/*' -d $MODPATH 2>/dev/null 191 | unzip -o "$ZIP" 'wget' -d $MODPATH 2>/dev/null 192 | 193 | # Handle replace folders 194 | for TARGET in $REPLACE; do 195 | mktouch $MODPATH$TARGET/.replace 196 | done 197 | 198 | # Auto Mount 199 | $AUTOMOUNT && touch $MODPATH/auto_mount 200 | 201 | # prop files 202 | $PROPFILE && cp -af $INSTALLER/common/system.prop $MODPATH/system.prop 203 | 204 | # Module info 205 | cp -af $INSTALLER/module.prop $MODPATH/module.prop 206 | if $BOOTMODE; then 207 | # Update info for Magisk Manager 208 | mktouch /magisk/$MODID/update 209 | cp -af $INSTALLER/module.prop /magisk/$MODID/module.prop 210 | fi 211 | 212 | # post-fs-data mode scripts 213 | $POSTFSDATA && cp -af $INSTALLER/common/post-fs-data.sh $MODPATH/post-fs-data.sh 214 | 215 | # service mode scripts 216 | $LATESTARTSERVICE && cp -af $INSTALLER/common/service.sh $MODPATH/service.sh 217 | 218 | # ReUninstall apps 219 | reinstall 220 | 221 | ui_print "- Setting permissions" 222 | set_permissions 223 | 224 | else 225 | 226 | # Uninstall module 227 | ui_print "- ! Current Version of Module Detected ! Uninstalling" 228 | rm -rf $MODPATH 2>/dev/null 229 | rm -rf /magisk/$MODID 230 | 231 | fi 232 | ########################################################################################## 233 | # Finalizing 234 | ########################################################################################## 235 | 236 | $MAGISKBIN/magisk --umountimg $MOUNTPATH $MAGISKLOOP 237 | rmdir $MOUNTPATH 238 | 239 | # Shrink the image if possible 240 | image_size_check $IMG 241 | newSizeM=$((curUsedM / 32 * 32 + 64)) 242 | if [ $curSizeM -gt $newSizeM ]; then 243 | ui_print "- Shrinking $IMG to ${newSizeM}M" 244 | $MAGISKBIN/magisk --resizeimg $IMG $newSizeM 245 | fi 246 | 247 | $BOOTMODE || recovery_cleanup 248 | 249 | if [ $isABDevice == true ]; then 250 | mount -o ro /system 2>/dev/null 251 | mount -o ro /vendor 2>/dev/null 252 | fi 253 | 254 | ui_print "- Done" 255 | exit 0 256 | --------------------------------------------------------------------------------