|
| 1 | +########################################################################################## |
| 2 | +# |
| 3 | +# MMT Extended Utility Functions |
| 4 | +# |
| 5 | +########################################################################################## |
| 6 | + |
| 7 | +umount_mirrors() { |
| 8 | + [ -d $ORIGDIR ] || return 0 |
| 9 | + for i in $ORIGDIR/*; do |
| 10 | + umount -l $i 2>/dev/null |
| 11 | + done |
| 12 | + rm -rf $ORIGDIR 2>/dev/null |
| 13 | + mount -o ro,remount $MAGISKTMP |
| 14 | +} |
| 15 | + |
| 16 | +cleanup() { |
| 17 | + $KSU && umount_mirrors |
| 18 | + rm -rf $MODPATH/common $MODPATH/install.zip 2>/dev/null |
| 19 | +} |
| 20 | + |
| 21 | +abort() { |
| 22 | + ui_print "$1" |
| 23 | + rm -rf $MODPATH 2>/dev/null |
| 24 | + cleanup |
| 25 | + rm -rf $TMPDIR 2>/dev/null |
| 26 | + exit 1 |
| 27 | +} |
| 28 | + |
| 29 | +device_check() { |
| 30 | + local opt=`getopt -o dm -- "$@"` type=device |
| 31 | + eval set -- "$opt" |
| 32 | + while true; do |
| 33 | + case "$1" in |
| 34 | + -d) local type=device; shift;; |
| 35 | + -m) local type=manufacturer; shift;; |
| 36 | + --) shift; break;; |
| 37 | + *) abort "Invalid device_check argument $1! Aborting!";; |
| 38 | + esac |
| 39 | + done |
| 40 | + local prop=$(echo "$1" | tr '[:upper:]' '[:lower:]') |
| 41 | + for i in /system /vendor /odm /product; do |
| 42 | + if [ -f $i/build.prop ]; then |
| 43 | + for j in "ro.product.$type" "ro.build.$type" "ro.product.vendor.$type" "ro.vendor.product.$type"; do |
| 44 | + [ "$(sed -n "s/^$j=//p" $i/build.prop 2>/dev/null | head -n 1 | tr '[:upper:]' '[:lower:]')" == "$prop" ] && return 0 |
| 45 | + done |
| 46 | + [ "$type" == "device" ] && [ "$(sed -n "s/^"ro.build.product"=//p" $i/build.prop 2>/dev/null | head -n 1 | tr '[:upper:]' '[:lower:]')" == "$prop" ] && return 0 |
| 47 | + fi |
| 48 | + done |
| 49 | + return 1 |
| 50 | +} |
| 51 | + |
| 52 | +cp_ch() { |
| 53 | + local opt=`getopt -o nr -- "$@"` BAK=true UBAK=true FOL=false |
| 54 | + eval set -- "$opt" |
| 55 | + while true; do |
| 56 | + case "$1" in |
| 57 | + -n) UBAK=false; shift;; |
| 58 | + -r) FOL=true; shift;; |
| 59 | + --) shift; break;; |
| 60 | + *) abort "Invalid cp_ch argument $1! Aborting!";; |
| 61 | + esac |
| 62 | + done |
| 63 | + local SRC="$1" DEST="$2" OFILES="$1" |
| 64 | + $FOL && local OFILES=$(find $SRC -type f 2>/dev/null) |
| 65 | + [ -z $3 ] && PERM=0644 || PERM=$3 |
| 66 | + case "$DEST" in |
| 67 | + $TMPDIR/*|$MODULEROOT/*|$NVBASE/modules/$MODID/*) BAK=false;; |
| 68 | + esac |
| 69 | + for OFILE in ${OFILES}; do |
| 70 | + if $FOL; then |
| 71 | + if [ "$(basename $SRC)" == "$(basename $DEST)" ]; then |
| 72 | + local FILE=$(echo $OFILE | sed "s|$SRC|$DEST|") |
| 73 | + else |
| 74 | + local FILE=$(echo $OFILE | sed "s|$SRC|$DEST/$(basename $SRC)|") |
| 75 | + fi |
| 76 | + else |
| 77 | + [ -d "$DEST" ] && local FILE="$DEST/$(basename $SRC)" || local FILE="$DEST" |
| 78 | + fi |
| 79 | + if $BAK && $UBAK; then |
| 80 | + [ ! "$(grep "$FILE$" $INFO 2>/dev/null)" ] && echo "$FILE" >> $INFO |
| 81 | + [ -f "$FILE" -a ! -f "$FILE~" ] && { mv -f $FILE $FILE~; echo "$FILE~" >> $INFO; } |
| 82 | + elif $BAK; then |
| 83 | + [ ! "$(grep "$FILE$" $INFO 2>/dev/null)" ] && echo "$FILE" >> $INFO |
| 84 | + fi |
| 85 | + install -D -m $PERM "$OFILE" "$FILE" |
| 86 | + done |
| 87 | +} |
| 88 | + |
| 89 | +install_script() { |
| 90 | + case "$1" in |
| 91 | + -l) shift; local INPATH=$NVBASE/service.d;; |
| 92 | + -p) shift; local INPATH=$NVBASE/post-fs-data.d;; |
| 93 | + *) local INPATH=$NVBASE/service.d;; |
| 94 | + esac |
| 95 | + [ "$(grep "#!/system/bin/sh" $1)" ] || sed -i "1i #!/system/bin/sh" $1 |
| 96 | + local i; for i in "MODPATH" "LIBDIR" "MODID" "INFO" "MODDIR"; do |
| 97 | + case $i in |
| 98 | + "MODPATH") sed -i "1a $i=$NVBASE/modules/$MODID" $1;; |
| 99 | + "MODDIR") sed -i "1a $i=\${0%/*}" $1;; |
| 100 | + *) sed -i "1a $i=$(eval echo \$$i)" $1;; |
| 101 | + esac |
| 102 | + done |
| 103 | + case $1 in |
| 104 | + "$MODPATH/post-fs-data.sh"|"$MODPATH/service.sh"|"$MODPATH/uninstall.sh") sed -i "s|^MODPATH=.*|MODPATH=\$MODDIR|" $1;; # MODPATH=MODDIR for these scripts (located in module directory) |
| 105 | + *) cp_ch -n $1 $INPATH/$(basename $1) 0755;; |
| 106 | + esac |
| 107 | +} |
| 108 | + |
| 109 | +prop_process() { |
| 110 | + sed -i -e "/^#/d" -e "/^ *$/d" $1 |
| 111 | + [ -f $MODPATH/system.prop ] || mktouch $MODPATH/system.prop |
| 112 | + while read LINE; do |
| 113 | + echo "$LINE" >> $MODPATH/system.prop |
| 114 | + done < $1 |
| 115 | +} |
| 116 | + |
| 117 | +mount_mirrors() { |
| 118 | + mount -o rw,remount $MAGISKTMP |
| 119 | + mkdir -p $ORIGDIR/system |
| 120 | + if $SYSTEM_ROOT; then |
| 121 | + mkdir -p $ORIGDIR/system_root |
| 122 | + mount -o ro / $ORIGDIR/system_root |
| 123 | + mount -o bind $ORIGDIR/system_root/system $ORIGDIR/system |
| 124 | + else |
| 125 | + mount -o ro /system $ORIGDIR/system |
| 126 | + fi |
| 127 | + for i in vendor $PARTITIONS; do |
| 128 | + [ ! -d /$i -o -d $ORIGDIR/$i ] && continue |
| 129 | + mkdir -p $ORIGDIR/$i |
| 130 | + mount -o ro /$i $ORIGDIR/$i |
| 131 | + done |
| 132 | +} |
| 133 | + |
| 134 | +# Check for min/max api version |
| 135 | +[ -z $MINAPI ] || { [ $API -lt $MINAPI ] && abort "! Your system API of $API is less than the minimum api of $MINAPI! Aborting!"; } |
| 136 | +[ -z $MAXAPI ] || { [ $API -gt $MAXAPI ] && abort "! Your system API of $API is greater than the maximum api of $MAXAPI! Aborting!"; } |
| 137 | + |
| 138 | + |
| 139 | +# Start debug |
| 140 | +[ -z $KSU ] && KSU=false || exec 2>/sdcard/Download/$MODID-debug.log |
| 141 | +set -x |
| 142 | + |
| 143 | +# Set variables |
| 144 | +[ -z $ARCH32 ] && ARCH32="$(echo $ABI32 | cut -c-3)" |
| 145 | +[ $API -lt 26 ] && DYNLIB=false |
| 146 | +[ -z $DYNLIB ] && DYNLIB=false |
| 147 | +[ -z $PARTOVER ] && PARTOVER=false |
| 148 | +INFO=$NVBASE/modules/.$MODID-files |
| 149 | +if $KSU; then |
| 150 | + MAGISKTMP="/mnt" |
| 151 | + ORIGDIR="$MAGISKTMP/mirror" |
| 152 | + mount_mirrors |
| 153 | +elif [ "$(magisk --path 2>/dev/null)" ]; then |
| 154 | + ORIGDIR="$(magisk --path 2>/dev/null)/.magisk/mirror" |
| 155 | +elif [ "$(echo $MAGISKTMP | awk -F/ '{ print $NF}')" == ".magisk" ]; then |
| 156 | + ORIGDIR="$MAGISKTMP/mirror" |
| 157 | +else |
| 158 | + ORIGDIR="$MAGISKTMP/.magisk/mirror" |
| 159 | +fi |
| 160 | +if $DYNLIB; then |
| 161 | + LIBPATCH="\/vendor" |
| 162 | + LIBDIR=/system/vendor |
| 163 | +else |
| 164 | + LIBPATCH="\/system" |
| 165 | + LIBDIR=/system |
| 166 | +fi |
| 167 | +# Detect extra partition compatibility (KernelSU or Magisk Delta) |
| 168 | +EXTRAPART=false |
| 169 | +if $KSU || [ "$(echo $MAGISK_VER | awk -F- '{ print $NF}')" == "delta" ]; then |
| 170 | + EXTRAPART=true |
| 171 | +elif ! $PARTOVER; then |
| 172 | + unset PARTITIONS |
| 173 | +fi |
| 174 | + |
| 175 | +if ! $BOOTMODE; then |
| 176 | + ui_print "- Only uninstall is supported in recovery" |
| 177 | + ui_print " Uninstalling!" |
| 178 | + touch $MODPATH/remove |
| 179 | + [ -s $INFO ] && install_script $MODPATH/uninstall.sh || rm -f $INFO $MODPATH/uninstall.sh |
| 180 | + recovery_cleanup |
| 181 | + cleanup |
| 182 | + rm -rf $NVBASE/modules_update/$MODID $TMPDIR 2>/dev/null |
| 183 | + exit 0 |
| 184 | +fi |
| 185 | + |
| 186 | +# Extract files |
| 187 | +ui_print "- Extracting module files" |
| 188 | +unzip -o "$ZIPFILE" -x 'META-INF/*' 'common/functions.sh' -d $MODPATH >&2 |
| 189 | +[ -f "$MODPATH/common/addon.tar.xz" ] && tar -xf $MODPATH/common/addon.tar.xz -C $MODPATH/common 2>/dev/null |
| 190 | + |
| 191 | +# Run addons |
| 192 | +if [ "$(ls -A $MODPATH/common/addon/*/install.sh 2>/dev/null)" ]; then |
| 193 | + ui_print " "; ui_print "- Running Addons -" |
| 194 | + for i in $MODPATH/common/addon/*/install.sh; do |
| 195 | + ui_print " Running $(echo $i | sed -r "s|$MODPATH/common/addon/(.*)/install.sh|\1|")..." |
| 196 | + . $i |
| 197 | + done |
| 198 | +fi |
| 199 | + |
| 200 | +# Remove files outside of module directory |
| 201 | +ui_print "- Removing old files" |
| 202 | + |
| 203 | +if [ -f $INFO ]; then |
| 204 | + while read LINE; do |
| 205 | + if [ "$(echo -n $LINE | tail -c 1)" == "~" ]; then |
| 206 | + continue |
| 207 | + elif [ -f "$LINE~" ]; then |
| 208 | + mv -f $LINE~ $LINE |
| 209 | + else |
| 210 | + rm -f $LINE |
| 211 | + while true; do |
| 212 | + LINE=$(dirname $LINE) |
| 213 | + [ "$(ls -A $LINE 2>/dev/null)" ] && break 1 || rm -rf $LINE |
| 214 | + done |
| 215 | + fi |
| 216 | + done < $INFO |
| 217 | + rm -f $INFO |
| 218 | +fi |
| 219 | + |
| 220 | +### Install |
| 221 | +ui_print "- Installing" |
| 222 | + |
| 223 | +[ -f "$MODPATH/common/install.sh" ] && . $MODPATH/common/install.sh |
| 224 | + |
| 225 | +ui_print " Installing for $ARCH SDK $API device..." |
| 226 | +# Remove comments from files and place them, add blank line to end if not already present |
| 227 | +for i in $(find $MODPATH -type f -name "*.sh" -o -name "*.prop" -o -name "*.rule"); do |
| 228 | + [ -f $i ] && { sed -i -e "/^#/d" -e "/^ *$/d" $i; [ "$(tail -1 $i)" ] && echo "" >> $i; } || continue |
| 229 | + case $i in |
| 230 | + "$MODPATH/service.sh") install_script -l $i;; |
| 231 | + "$MODPATH/post-fs-data.sh") install_script -p $i;; |
| 232 | + "$MODPATH/uninstall.sh") if [ -s $INFO ] || [ "$(head -n1 $MODPATH/uninstall.sh)" != "# Don't modify anything after this" ]; then |
| 233 | + cp -f $MODPATH/uninstall.sh $MODPATH/$MODID-uninstall.sh # Fallback script in case module manually deleted |
| 234 | + sed -i "1i[ -d \"\$MODPATH\" ] && exit 0" $MODPATH/$MODID-uninstall.sh |
| 235 | + echo 'rm -f $0' >> $MODPATH/$MODID-uninstall.sh |
| 236 | + install_script -l $MODPATH/$MODID-uninstall.sh |
| 237 | + rm -f $MODPATH/$MODID-uninstall.sh |
| 238 | + install_script $MODPATH/uninstall.sh |
| 239 | + else |
| 240 | + rm -f $INFO $MODPATH/uninstall.sh |
| 241 | + fi;; |
| 242 | + esac |
| 243 | +done |
| 244 | + |
| 245 | +$IS64BIT || for i in $(find $MODPATH/system -type d -name "lib64"); do rm -rf $i 2>/dev/null; done |
| 246 | +[ -d "/system/priv-app" ] || mv -f $MODPATH/system/priv-app $MODPATH/system/app 2>/dev/null |
| 247 | +[ -d "/system/xbin" ] || mv -f $MODPATH/system/xbin $MODPATH/system/bin 2>/dev/null |
| 248 | +if $DYNLIB; then |
| 249 | + for FILE in $(find $MODPATH/system/lib* -type f 2>/dev/null | sed "s|$MODPATH/system/||"); do |
| 250 | + [ -s $MODPATH/system/$FILE ] || continue |
| 251 | + case $FILE in |
| 252 | + lib*/modules/*) continue;; |
| 253 | + esac |
| 254 | + mkdir -p $(dirname $MODPATH/system/vendor/$FILE) |
| 255 | + mv -f $MODPATH/system/$FILE $MODPATH/system/vendor/$FILE |
| 256 | + [ "$(ls -A `dirname $MODPATH/system/$FILE`)" ] || rm -rf `dirname $MODPATH/system/$FILE` |
| 257 | + done |
| 258 | + # Delete empty lib folders (busybox find doesn't have this capability) |
| 259 | + toybox find $MODPATH/system/lib* -type d -empty -delete >/dev/null 2>&1 |
| 260 | +fi |
| 261 | + |
| 262 | +# Set permissions |
| 263 | +ui_print " " |
| 264 | +ui_print "- Setting Permissions" |
| 265 | +set_perm_recursive $MODPATH 0 0 0755 0644 |
| 266 | +for i in /system/vendor /vendor /system/vendor/app /vendor/app /system/vendor/etc /vendor/etc /system/odm/etc /system/vendor/odm/etc /vendor/odm/etc /system/vendor/overlay /vendor/overlay; do |
| 267 | + if [ -d "$MODPATH$i" ] && [ ! -L "$MODPATH$i" ]; then |
| 268 | + case $i in |
| 269 | + *"/vendor") set_perm_recursive $MODPATH$i 0 0 0755 0644 u:object_r:vendor_file:s0;; |
| 270 | + *"/app") set_perm_recursive $MODPATH$i 0 0 0755 0644 u:object_r:vendor_app_file:s0;; |
| 271 | + *"/overlay") set_perm_recursive $MODPATH$i 0 0 0755 0644 u:object_r:vendor_overlay_file:s0;; |
| 272 | + *"/etc") set_perm_recursive $MODPATH$i 0 2000 0755 0644 u:object_r:vendor_configs_file:s0;; |
| 273 | + esac |
| 274 | + fi |
| 275 | +done |
| 276 | +for i in $(find $MODPATH/system/vendor $MODPATH/vendor -type f -name *".apk" 2>/dev/null); do |
| 277 | + chcon u:object_r:vendor_app_file:s0 $i |
| 278 | +done |
| 279 | +set_permissions |
| 280 | + |
| 281 | +# Complete install |
| 282 | +cleanup |
0 commit comments