#!/sbin/sh
#
# SuperSU installer ZIP
# Copyright (c) 2012-2015 - Chainfire
#
# ----- GENERIC INFO ------
#
# The following su binary versions are included in the full package. Each
# should be installed only if the system has the same or newer API level
# as listed. The script may fall back to a different binary on older API
# levels. supolicy are all ndk/pie/19+ for 32 bit, ndk/pie/20+ for 64 bit.
#
# binary        ARCH/path   build type      API
#
# arm-v5te      arm         ndk non-pie     7+
# x86           x86         ndk non-pie     7+
#
# x86           x86         ndk pie         17+   (su.pie, naming exception)
# arm-v7a       armv7       ndk pie         17+
# mips          mips        ndk pie         17+
#
# arm64-v8a     arm64       ndk pie         20+
# mips64        mips64      ndk pie         20+
# x86_64        x64         ndk pie         20+
#
# Non-static binaries are supported to be PIE (Position Independent
# Executable) from API level 16, and required from API level 20 (which will
# refuse to execute non-static non-PIE).
#
# The script performs several actions in various ways, sometimes
# multiple times, due to different recoveries and firmwares behaving
# differently, and it thus being required for the correct result.
#
# Overridable variables (shell):
#   BIN - Location of architecture specific files (native folder)
#   COM - Location of common files (APK folder)
#   NOOVERRIDE - Do not read variables from /system/.supersu or
#                /data/.supersu
#
# Overridable variables (shell, /system/.supersu, /data/.supersu):
#   SYSTEMLESS - Do a system-less install? (true/false, 6.0+ only)
#   PATCHBOOTIMAGE - Automatically patch boot image? (true/false,
#                    SYSTEMLESS only)
#   BOOTIMAGE - Boot image location (PATCHBOOTIMAGE only)
#   STOCKBOOTIMAGE - Stock boot image location (PATCHBOOTIMAGE only)
#   BINDSYSTEMXBIN - Poor man's overlay on /system/xbin (true/false,
#                    SYSTEMLESS only)
#   FSTABSYSTEMRW - Set /system, /vendor and /oem to read/write in
#                   fstab. On some devices, this fixes /system not
#                   being remountable read/write from Android.
# Shell overrides all, /data/.supersu overrides /system/.supersu
#
# Note that if SELinux is set to enforcing, the daemonsu binary expects
# to be run at startup (usually from install-recovery.sh, 99SuperSUDaemon,
# or app_process) from u:r:init:s0 or u:r:kernel:s0 contexts. Depending
# on the current policies, it can also deal with u:r:init_shell:s0 and
# u:r:toolbox:s0 contexts. Any other context will lead to issues eventually.
#
# ----- "SYSTEM" INSTALL -----
#
# "System" install puts all the files needed in /system and does not need
# any boot image modifications. Default install method pre-Android-6.0.
#
# To install SuperSU properly, aside from cleaning old versions and
# other superuser-type apps from the system, the following files need to
# be installed:
#
# API   source                        target                              chmod   chcon                       required
#
# 7-19  common/Superuser.apk          /system/app/Superuser.apk           0644    u:object_r:system_file:s0   gui
# 20+   common/Superuser.apk          /system/app/SuperSU/SuperSU.apk     0644    u:object_r:system_file:s0   gui
#
# 17+   common/install-recovery.sh    /system/etc/install-recovery.sh     0755    *1                          required
# 17+                                 /system/bin/install-recovery.sh     (symlink to /system/etc/...)        required
# *1: same as /system/bin/toolbox: u:object_r:system_file:s0 if API < 20, u:object_r:toolbox_exec:s0 if API >= 20
#
# 7+    ARCH/su *2                    /system/xbin/su                     *3      u:object_r:system_file:s0   required
# 7+                                  /system/bin/.ext/.su                *3      u:object_r:system_file:s0   gui
# 17+                                 /system/xbin/daemonsu               0755    u:object_r:system_file:s0   required
# 17-21                               /system/xbin/sugote                 0755    u:object_r:zygote_exec:s0   required
# *2: su.pie for 17+ x86(_32) only
# *3: 06755 if API < 18, 0755 if API >= 18
#
# 19+   ARCH/supolicy                 /system/xbin/supolicy               0755    u:object_r:system_file:s0   required
# 19+   ARCH/libsupol.so              /system/lib(64)/libsupol.so         0644    u:object_r:system_file:s0   required
#
# 17-21 /system/bin/sh or mksh *4     /system/xbin/sugote-mksh            0755    u:object_r:system_file:s0   required
# *4: which one (or both) are available depends on API
#
# 21+   /system/bin/app_process32 *5  /system/bin/app_process32_original  0755    u:object_r:zygote_exec:s0   required
# 21+   /system/bin/app_process64 *5  /system/bin/app_process64_original  0755    u:object_r:zygote_exec:s0   required
# 21+   /system/bin/app_processXX *5  /system/bin/app_process_init        0755    u:object_r:system_file:s0   required
# 21+                                 /system/bin/app_process             (symlink to /system/xbin/daemonsu)  required
# 21+                             *5  /system/bin/app_process32           (symlink to /system/xbin/daemonsu)  required
# 21+                             *5  /system/bin/app_process64           (symlink to /system/xbin/daemonsu)  required
# *5: Only do this for the relevant bits. On a 64 bits system, leave the 32 bits files alone, or dynamic linker errors
#     will prevent the system from fully working in subtle ways. The bits of the su binary must also match!
#
# 17+   common/99SuperSUDaemon *6     /system/etc/init.d/99SuperSUDaemon  0755    u:object_r:system_file:s0   optional
# *6: only place this file if /system/etc/init.d is present
#
# 17+   'echo 1 >' or 'touch' *7      /system/etc/.installed_su_daemon    0644    u:object_r:system_file:s0   optional
# *7: the file just needs to exist or some recoveries will nag you. Even with it there, it may still happen.
#
# It may seem some files are installed multiple times needlessly, but
# it only seems that way. Installing files differently or symlinking
# instead of copying (unless specified) will lead to issues eventually.
#
# After installation, run '/system/xbin/su --install', which may need to
# perform some additional installation steps. Ideally, at one point,
# a lot of this script will be moved there.
#
# The included chattr(.pie) binaries are used to remove ext2's immutable
# flag on some files. This flag is no longer set by SuperSU's OTA
# survival since API level 18, so there is no need for the 64 bit versions.
# Note that chattr does not need to be installed to the system, it's just
# used by this script, and not supported by the busybox used in older
# recoveries.
#
# ----- "SYSTEM-LESS" INSTALL -----
#
# "System-less" install requires a modified boot image (the script can patch
# many boot images on-the-fly), but does not touch /system at all. Instead
# it keeps all the needed files in an image (/data/su.img) which is mounted
# to /su. Default install method on all Android-6.0+, and Samsung-5.1+.
#
# An ext4 image is created as /data/su.img, or /cache/su.img if /data could
# not be mounted. Similarly, the APK is placed as either /data/SuperSU.apk
# or /cache/SuperSU.apk. This is so we are not dependent on /data decryption
# working in recovery, which in the past has proved an issue on brand-new
# Android versions and devices.
#
# /sbin/launch_daemonsu.sh, which is added a service to init.rc, will mount
# the image at /su, and launch daemonsu from /su/bin/daemonsu. But before it
# does that, it will try to merge /data/su.img and /cache/su.img (leading),
# if both are present. It will also try to install the SuperSU APK.
#
# Files are expected at the following places (/su being the mountpoint of
# the ext4 image):
#
# API   source                        target                              chmod   chcon                       required
#
# 22+   common/Superuser.apk          /[data|cache]/SuperSU.apk           0644    u:object_r:system_file:s0   gui
#
# 22+   ARCH/su *1                    /su/bin/su                          0755    u:object_r:system_file:s0   required
# 22+                                 /su/bin/daemonsu                    0755    u:object_r:system_file:s0   required
# *1: su.pie for 17+ x86(_32) only
#
# 22+   ARCH/supolicy                 /su/bin/supolicy_wrapped            0755    u:object_r:system_file:s0   required
# 22+   /su/bin/su (symlink) *2       /su/lib/supolicy                    0755    u:object_r:system_file:s0   required
# 22+   ARCH/libsupol.so              /su/lib/libsupol.so                 0644    u:object_r:system_file:s0   required
# *2: when called this way, su sets the correct LD_LIBRARY_PATH and calls supolicy_wrapped
#
# 22+   ARCH/sukernel                 /su/bin/sukernel                    0755    u:object_r:system_file:s0   required
#
# These files are automatically created on launch by daemonsu as needed:
# 22+   /system/bin/sh                /su/bin/sush                        0755    u:object_r:system_file:s0   required
# 22+   /system/bin/app_process[64]   /su/bin/app_process                 0755    u:object_r:system_file:s0   required
#
# These files are injected into the boot image ramdisk:
# 22+   common/launch_daemonsu.sh     /sbin/launch_daemonsu.sh            0700    u:object_r:rootfs:s0        required
#
# The automated boot image patcher included makes the following modifications
# to the ramdisk:
#
# - Uses the supolicy tool to patch the sepolicy file
# - Injects /sbin/launch_daemon.sh
# - Removes /verity_key
# - Patches /*fstab*
# --- Removes support_scfs and verify flags
# --- Changes forceencrypt into encryptable
# - Patches /init.rc
# --- Adds mkdir /su
# --- Adds a sukernel.mount property trigger that mounts /data/su.img to /su
# --- Adds the daemonsu service that launches /sbin/launch_daemon.sh
# --- Adds a SuperSU:PATCH marker with the version of the sukernel tool
# --- Adds a SuperSU:STOCK marker listed the SHA1 of the original boot image
# - Patches /init.environ.rc
# --- Adds PATH variable if it does not exist
# --- Prepends /su/bin to the PATH variable
# - Patches /file_contexts
# --- Adds a default context for file existing in the /su mount
#
# In case this documentation becomes outdated, please note that the sukernel
# tool is very chatty, and its output tells you exactly what it is doing
# and how. In TWRP, you can view this output by catting /tmp/recovery.log
# after flashing the ZIP.
#
# The boot image patcher creates a backup of the boot image it patches, for
# future restoration. It cannot re-patch a patched boot image, it will restore
# the previous boot image first. /[data|cache]/stock_boot_*.gz
#
# The boot image patcher currently only supports GZIP compressed ramdisks, and
# boot images in the standard Android boot image format.
#
# Just before flashing, the boot image patcher will call
# /data/custom_boot_image_patch.sh with the name of the patched boot image
# as parameter. A device-specific patcher can further patch the boot image
# if needed. It must replace the input file and return a 0 exit code.

getvar() {
  local VARNAME=$1
  local VALUE=$(eval echo \$"$VARNAME");
  for FILE in /data/.supersu /system/.supersu; do
    if [ -z "$VALUE" ]; then
      LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
      if [ ! -z "$LINE" ]; then
        VALUE=${LINE#*=}
      fi
    fi
  done
  eval $VARNAME=\$VALUE
}

if [ -z "$NOOVERRIDE" ]; then
  # read override variables
  getvar SYSTEMLESS
  getvar PATCHBOOTIMAGE
  getvar BOOTIMAGE
  getvar STOCKBOOTIMAGE
  getvar BINDSYSTEMXBIN
  getvar FSTABSYSTEMRW
fi

if [ -z "$SYSTEMLESS" ]; then
  # will still only happen on supported Android versions
  SYSTEMLESS=true
fi
if [ -z "$PATCHBOOTIMAGE" ]; then
  # only if we end up doing a system-less install
  PATCHBOOTIMAGE=true
fi
if [ -z "$BINDSYSTEMXBIN" ]; then
  # causes launch_daemonsu to bind over /system/xbin
  BINDSYSTEMXBIN=true
fi
if [ -z "$FSTABSYSTEMRW" ]; then
  # system-less only, changes ro to rw in fstab
  FSTABSYSTEMRW=false
fi

OUTFD=$2
ZIP=$3

SYSTEMLIB=/system/lib

ui_print() {
  echo -n -e "ui_print $1\n" > /proc/self/fd/$OUTFD
  echo -n -e "ui_print\n" > /proc/self/fd/$OUTFD
}

ch_con() {
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toybox chcon -h u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toybox chcon -h u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toolbox chcon -h u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toolbox chcon -h u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  chcon -h u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toybox chcon u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toybox chcon u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toolbox chcon u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toolbox chcon u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
  chcon u:object_r:system_file:s0 $1 1>/dev/null 2>/dev/null
}

ch_con_ext() {
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toybox chcon $2 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toybox chcon $2 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toolbox chcon $2 $1 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toolbox chcon $2 $1 1>/dev/null 2>/dev/null
  chcon $2 $1 1>/dev/null 2>/dev/null
}

ln_con() {
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toybox ln -s $1 $2 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toybox ln -s $1 $2 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/toolbox ln -s $1 $2 1>/dev/null 2>/dev/null
  LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/toolbox ln -s $1 $2 1>/dev/null 2>/dev/null
  ln -s $1 $2 1>/dev/null 2>/dev/null
  ch_con $2 1>/dev/null 2>/dev/null
}

set_perm() {
  chown $1.$2 $4
  chown $1:$2 $4
  chmod $3 $4
  ch_con $4
  ch_con_ext $4 $5
}

cp_perm() {
  rm $5
  if [ -f "$4" ]; then
    cat $4 > $5
    set_perm $1 $2 $3 $5 $6
  fi
}

toolbox_mount() {
  RW=rw
  if [ ! -z "$2" ]; then
    RW=$2
  fi

  DEV=
  POINT=
  FS=
  for i in `cat /etc/fstab | grep "$1"`; do
    if [ -z "$DEV" ]; then
      DEV=$i
    elif [ -z "$POINT" ]; then
      POINT=$i
    elif [ -z "$FS" ]; then
      FS=$i
      break
    fi
  done
  mount -t $FS -o $RW $DEV $POINT
  mount -t $FS -o $RW,remount $DEV $POINT

  DEV=
  POINT=
  FS=
  for i in `cat /etc/recovery.fstab | grep "$1"`; do
    if [ -z "$POINT" ]; then
      POINT=$i
    elif [ -z "$FS" ]; then
      FS=$i
    elif [ -z "$DEV" ]; then
      DEV=$i
      break
    fi
  done
  if [ "$FS" = "emmc" ]; then
    mount -t ext4 -o $RW $DEV $POINT
    mount -t ext4 -o $RW,remount $DEV $POINT
    mount -t f2fs -o $RW $DEV $POINT
    mount -t f2fs -o $RW,remount $DEV $POINT
  else
    mount -t $FS -o $RW $DEV $POINT
    mount -t $FS -o $RW,remount $DEV $POINT
  fi
}

ui_print " "
ui_print "*****************"
ui_print "SuperSU installer"
ui_print "*****************"

ui_print "- Mounting /system, /data and rootfs"

mount -o ro /system
toolbox_mount /system ro
mount /data
toolbox_mount /data
mount -o rw,remount /
mount -o rw,remount / /

if [ -z "$BIN" ]; then
  # TWRP went full retard
  if [ ! -f "/sbin/unzip" ]; then
    ui_print "- BAD RECOVERY DETECTED, NO UNZIP, ABORTING"
    exit 1
  fi
fi

API=$(cat /system/build.prop | grep "ro.build.version.sdk=" | dd bs=1 skip=21 count=2)

RWSYSTEM=true
if [ "$API" -eq "$API" ]; then
  if [ "$API" -ge "23" ]; then
    # 6.0+
    if ($SYSTEMLESS); then
      RWSYSTEM=false
    fi
  elif [ "$API" -ge "22" ]; then
    # 5.1/Samsung
    if ($SYSTEMLESS); then
      SAMSUNG=$(cat /system/build.prop | grep "ro.build.fingerprint=" | grep -i "samsung")
      if [ $? -eq 0 ]; then
        RWSYSTEM=false
      fi
    fi
  fi
fi

if ($RWSYSTEM); then
  cat /system/bin/toybox > /system/toybox
  chmod 0755 /system/toybox
  ch_con /system/toybox

  cat /system/bin/toolbox > /system/toolbox
  chmod 0755 /system/toolbox
  ch_con /system/toolbox

  mount -o rw,remount /system
  mount -o rw,remount /system /system
  toolbox_mount /system
fi

ABI=$(cat /system/build.prop /default.prop | grep -m 1 "ro.product.cpu.abi=" | dd bs=1 skip=19 count=3)
ABILONG=$(cat /system/build.prop /default.prop | grep -m 1 "ro.product.cpu.abi=" | dd bs=1 skip=19)
ABI2=$(cat /system/build.prop /default.prop | grep -m 1 "ro.product.cpu.abi2=" | dd bs=1 skip=20 count=3)
SUMOD=06755
SUGOTE=false
SUPOLICY=false
INSTALL_RECOVERY_CONTEXT=u:object_r:system_file:s0
MKSH=/system/bin/mksh
PIE=
SU=su
ARCH=arm
APKFOLDER=false
APKNAME=/system/app/Superuser.apk
APPPROCESS=false
APPPROCESS64=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$API" -eq "$API" ]; then
  if [ "$API" -ge "17" ]; then
    SUGOTE=true
    PIE=.pie
    if [ "$ARCH" = "x86" ]; then SU=su.pie; fi;
    if [ "$ABILONG" = "armeabi-v7a" ]; then ARCH=armv7; fi;
    if [ "$ABI" = "mip" ]; then ARCH=mips; fi;
    if [ "$ABILONG" = "mips" ]; then ARCH=mips; fi;
  fi
  if [ "$API" -ge "18" ]; then
    SUMOD=0755
  fi
  if [ "$API" -ge "20" ]; then
    if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; SYSTEMLIB=/system/lib64; APPPROCESS64=true; fi;
    if [ "$ABILONG" = "mips64" ]; then ARCH=mips64; SYSTEMLIB=/system/lib64; APPPROCESS64=true; fi;
    if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; SYSTEMLIB=/system/lib64; APPPROCESS64=true; fi;
    APKFOLDER=true
    APKNAME=/system/app/SuperSU/SuperSU.apk
  fi
  if [ "$API" -ge "19" ]; then
    SUPOLICY=true
    if [ "$(LD_LIBRARY_PATH=$SYSTEMLIB /system/toolbox ls -lZ /system/bin/toolbox | grep toolbox_exec > /dev/null; echo $?)" -eq "0" ]; then
      INSTALL_RECOVERY_CONTEXT=u:object_r:toolbox_exec:s0
    fi
  fi
  if [ "$API" -ge "21" ]; then
    APPPROCESS=true
  fi
  if [ "$API" -ge "22" ]; then
    SUGOTE=false
  fi
fi
if [ ! -f $MKSH ]; then
  MKSH=/system/bin/sh
fi

#ui_print "DBG [$API] [$ABI] [$ABI2] [$ABILONG] [$ARCH] [$MKSH]"

if [ -z "$BIN" ]; then
  ui_print "- Extracting files"

  cd /tmp
  mkdir supersu
  cd supersu

  unzip -o "$ZIP"
  
  BIN=/tmp/supersu/$ARCH
  COM=/tmp/supersu/common
fi

wipe_system_files_if_present() {
  GO=false
  SYSTEMFILES="
    /system/xbin/daemonsu
    /system/xbin/sugote
    /system/xbin/sugote-mksh
    /system/xbin/supolicy
    /system/xbin/ku.sud
    /system/xbin/.ku
    /system/xbin/.su
    /system/lib/libsupol.so
    /system/lib64/libsupol.so
    /system/bin/.ext/.su
    /system/etc/init.d/99SuperSUDaemon
    /system/etc/.installed_su_daemon
    /system/app/Superuser.apk
    /system/app/Superuser.odex
    /system/app/Superuser
    /system/app/SuperUser.apk
    /system/app/SuperUser.odex
    /system/app/SuperUser
    /system/app/superuser.apk
    /system/app/superuser.odex
    /system/app/superuser
    /system/app/Supersu.apk
    /system/app/Supersu.odex
    /system/app/Supersu
    /system/app/SuperSU.apk
    /system/app/SuperSU.odex
    /system/app/SuperSU
    /system/app/supersu.apk
    /system/app/supersu.odex
    /system/app/supersu
    /system/app/VenomSuperUser.apk
    /system/app/VenomSuperUser.odex
    /system/app/VenomSuperUser
  "
  for FILE in $SYSTEMFILES; do
    if [ -d "$FILE" ]; then GO=true; fi
    if [ -f "$FILE" ]; then GO=true; fi
  done
  if ($GO); then
    if (! $RWSYSTEM); then
      ui_print "- Remounting system r/w :("
      mount -o rw,remount /system
      mount -o rw,remount /system /system
      toolbox_mount /system
    fi
    for FILE in $SYSTEMFILES; do
      if [ -d "$FILE" ]; then rm -rf $FILE; fi
      if [ -f "$FILE" ]; then rm -f $FILE; fi
    done
  fi
}

wipe_data_competitors_and_cache() {
  rm -f /data/dalvik-cache/*com.noshufou.android.su*
  rm -f /data/dalvik-cache/*/*com.noshufou.android.su*
  rm -f /data/dalvik-cache/*com.koushikdutta.superuser*
  rm -f /data/dalvik-cache/*/*com.koushikdutta.superuser*
  rm -f /data/dalvik-cache/*com.mgyun.shua.su*
  rm -f /data/dalvik-cache/*/*com.mgyun.shua.su*
  rm -f /data/dalvik-cache/*com.m0narx.su*
  rm -f /data/dalvik-cache/*/*com.m0narx.su*
  rm -f /data/dalvik-cache/*com.kingroot.kinguser*
  rm -f /data/dalvik-cache/*/*com.kingroot.kinguser*
  rm -f /data/dalvik-cache/*com.kingroot.master*
  rm -f /data/dalvik-cache/*/*com.kingroot.master*
  rm -f /data/dalvik-cache/*Superuser.apk*
  rm -f /data/dalvik-cache/*/*Superuser.apk*
  rm -f /data/dalvik-cache/*SuperUser.apk*
  rm -f /data/dalvik-cache/*/*SuperUser.apk*
  rm -f /data/dalvik-cache/*superuser.apk*
  rm -f /data/dalvik-cache/*/*superuser.apk*
  rm -f /data/dalvik-cache/*VenomSuperUser.apk*
  rm -f /data/dalvik-cache/*/*VenomSuperUser.apk*
  rm -f /data/dalvik-cache/*eu.chainfire.supersu*
  rm -f /data/dalvik-cache/*/*eu.chainfire.supersu*
  rm -f /data/dalvik-cache/*Supersu.apk*
  rm -f /data/dalvik-cache/*/*Supersu.apk*
  rm -f /data/dalvik-cache/*SuperSU.apk*
  rm -f /data/dalvik-cache/*/*SuperSU.apk*
  rm -f /data/dalvik-cache/*supersu.apk*
  rm -f /data/dalvik-cache/*/*supersu.apk*
  rm -f /data/dalvik-cache/*.oat
  rm -rf /data/app/com.noshufou.android.su*
  rm -rf /data/app/com.koushikdutta.superuser*
  rm -rf /data/app/com.mgyun.shua.su*
  rm -rf /data/app/com.m0narx.su*
  rm -rf /data/app/com.kingroot.kinguser*
  rm -rf /data/app/com.kingroot.master*
}

# check_zero "progress_message" "success message" "failure message" "command"
check_zero() {
  if ($CONTINUE); then
    if [ ! -z "$1" ]; then ui_print "$1"; fi
    eval "$4"
    if [ $? -eq 0 ]; then
      if [ ! -z "$2" ]; then ui_print "$2"; fi
    else
      if [ ! -z "$3" ]; then ui_print "$3"; fi
      CONTINUE=false
    fi
  fi
}

# check_zero_def "progress message" "command"
check_zero_def() {
  check_zero "$1" "" "--- Failure, aborting" "$2"
}

if ($RWSYSTEM); then
  ui_print "- Disabling OTA survival"
  chmod 0755 $BIN/chattr$PIE
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/bin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/bin/.ext/.su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/sbin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /vendor/sbin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /vendor/bin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /vendor/xbin/su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/daemonsu
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/sugote
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/sugote_mksh
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/supolicy
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/ku.sud
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/.ku
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/xbin/.su
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/lib/libsupol.so
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/lib64/libsupol.so
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/etc/install-recovery.sh
  LD_LIBRARY_PATH=$SYSTEMLIB $BIN/chattr$PIE -ia /system/bin/install-recovery.sh

  ui_print "- Removing old files"

  if [ -f "/system/bin/install-recovery.sh" ]; then
    if [ ! -f "/system/bin/install-recovery_original.sh" ]; then
      mv /system/bin/install-recovery.sh /system/bin/install-recovery_original.sh
      ch_con /system/bin/install-recovery_original.sh
    fi
  fi
  if [ -f "/system/etc/install-recovery.sh" ]; then
    if [ ! -f "/system/etc/install-recovery_original.sh" ]; then
      mv /system/etc/install-recovery.sh /system/etc/install-recovery_original.sh
      ch_con /system/etc/install-recovery_original.sh
    fi
  fi

  # only wipe these files in /system install, so not part of the wipe_ functions

  rm -f /system/bin/install-recovery.sh
  rm -f /system/etc/install-recovery.sh

  rm -f /system/bin/su
  rm -f /system/xbin/su
  rm -f /system/sbin/su
  rm -f /vendor/sbin/su
  rm -f /vendor/bin/su
  rm -f /vendor/xbin/su

  rm -rf /data/app/eu.chainfire.supersu-*
  rm -rf /data/app/eu.chainfire.supersu.apk

  wipe_system_files_if_present
  wipe_data_competitors_and_cache

  rm /data/su.img
  rm /cache/su.img

  ui_print "- Creating space"
  if ($APKFOLDER); then
    if [ -f "/system/app/Maps/Maps.apk" ]; then
      cp /system/app/Maps/Maps.apk /Maps.apk
      rm /system/app/Maps/Maps.apk
    fi
    if [ -f "/system/app/GMS_Maps/GMS_Maps.apk" ]; then
      cp /system/app/GMS_Maps/GMS_Maps.apk /GMS_Maps.apk
      rm /system/app/GMS_Maps/GMS_Maps.apk
    fi
    if [ -f "/system/app/YouTube/YouTube.apk" ]; then
      cp /system/app/YouTube/YouTube.apk /YouTube.apk
      rm /system/app/YouTube/YouTube.apk
    fi
  else
    if [ -f "/system/app/Maps.apk" ]; then
      cp /system/app/Maps.apk /Maps.apk
      rm /system/app/Maps.apk
    fi
    if [ -f "/system/app/GMS_Maps.apk" ]; then
      cp /system/app/GMS_Maps.apk /GMS_Maps.apk
      rm /system/app/GMS_Maps.apk
    fi
    if [ -f "/system/app/YouTube.apk" ]; then
      cp /system/app/YouTube.apk /YouTube.apk
      rm /system/app/YouTube.apk
    fi
  fi

  ui_print "- Placing files"

  mkdir /system/bin/.ext
  set_perm 0 0 0777 /system/bin/.ext
  cp_perm 0 0 $SUMOD $BIN/$SU /system/bin/.ext/.su
  cp_perm 0 0 $SUMOD $BIN/$SU /system/xbin/su
  cp_perm 0 0 0755 $BIN/$SU /system/xbin/daemonsu
  if ($SUGOTE); then
    cp_perm 0 0 0755 $BIN/$SU /system/xbin/sugote u:object_r:zygote_exec:s0
    cp_perm 0 0 0755 $MKSH /system/xbin/sugote-mksh
  fi
  if ($SUPOLICY); then
    cp_perm 0 0 0755 $BIN/supolicy /system/xbin/supolicy
    cp_perm 0 0 0644 $BIN/libsupol.so $SYSTEMLIB/libsupol.so
  fi
  if ($APKFOLDER); then
    mkdir /system/app/SuperSU
    set_perm 0 0 0755 /system/app/SuperSU
  fi
  cp_perm 0 0 0644 $COM/Superuser.apk $APKNAME
  cp_perm 0 0 0755 $COM/install-recovery.sh /system/etc/install-recovery.sh
  ln_con /system/etc/install-recovery.sh /system/bin/install-recovery.sh
  if ($APPPROCESS); then
    rm /system/bin/app_process
    ln_con /system/xbin/daemonsu /system/bin/app_process
    if ($APPPROCESS64); then
      if [ ! -f "/system/bin/app_process64_original" ]; then
        mv /system/bin/app_process64 /system/bin/app_process64_original
      else
        rm /system/bin/app_process64
      fi
      ln_con /system/xbin/daemonsu /system/bin/app_process64
      if [ ! -f "/system/bin/app_process_init" ]; then
        cp_perm 0 2000 0755 /system/bin/app_process64_original /system/bin/app_process_init
      fi
    else
      if [ ! -f "/system/bin/app_process32_original" ]; then
        mv /system/bin/app_process32 /system/bin/app_process32_original
      else
        rm /system/bin/app_process32
      fi
      ln_con /system/xbin/daemonsu /system/bin/app_process32
      if [ ! -f "/system/bin/app_process_init" ]; then
        cp_perm 0 2000 0755 /system/bin/app_process32_original /system/bin/app_process_init
      fi
    fi
  fi
  cp_perm 0 0 0744 $COM/99SuperSUDaemon /system/etc/init.d/99SuperSUDaemon
  echo 1 > /system/etc/.installed_su_daemon
  set_perm 0 0 0644 /system/etc/.installed_su_daemon

  ui_print "- Restoring files"
  if ($APKFOLDER); then
    if [ -f "/Maps.apk" ]; then
      cp_perm 0 0 0644 /Maps.apk /system/app/Maps/Maps.apk
      rm /Maps.apk
    fi
    if [ -f "/GMS_Maps.apk" ]; then
      cp_perm 0 0 0644 /GMS_Maps.apk /system/app/GMS_Maps/GMS_Maps.apk
      rm /GMS_Maps.apk
    fi
    if [ -f "/YouTube.apk" ]; then
      cp_perm 0 0 0644 /YouTube.apk /system/app/YouTube/YouTube.apk
      rm /YouTube.apk
    fi
  else
    if [ -f "/Maps.apk" ]; then
      cp_perm 0 0 0644 /Maps.apk /system/app/Maps.apk
      rm /Maps.apk
    fi
    if [ -f "/GMS_Maps.apk" ]; then
      cp_perm 0 0 0644 /GMS_Maps.apk /system/app/GMS_Maps.apk
      rm /GMS_Maps.apk
    fi
    if [ -f "/YouTube.apk" ]; then
      cp_perm 0 0 0644 /YouTube.apk /system/app/YouTube.apk
      rm /YouTube.apk
    fi
  fi

  ui_print "- Post-installation script"
  rm /system/toybox
  rm /system/toolbox
  LD_LIBRARY_PATH=$SYSTEMLIB /system/xbin/su --install
else
  ui_print "- System-less mode, boot image support required"

  SUIMG=/data/su.img
  HAVEDATA=true
  DATAMOUNT=$(cat /proc/mounts | grep /data)
  if [ $? -ne 0 ]; then
    SUIMG=/cache/su.img
    HAVEDATA=false
  fi

  ui_print "- Creating image"

  SUIMGSIZE=32M
  if [ ! -f "$SUIMG" ]; then
    make_ext4fs -l $SUIMGSIZE -a /su -S $COM/file_contexts_image $SUIMG
  fi
  if [ ! -f "$SUIMG" ]; then
    LD_LIBRARY_PATH=$SYSTEMLIB /system/bin/make_ext4fs -l $SUIMGSIZE -a /su -S $COM/file_contexts_image $SUIMG
  fi

  ui_print "- Mounting image"

  mkdir /su
  losetup /dev/block/loop0 $SUIMG
  mount -t ext4 -o loop /dev/block/loop0 /su

  ui_print "- Creating paths"

  mkdir /su/bin
  set_perm 0 0 0755 /su/bin
  mkdir /su/lib
  set_perm 0 0 0755 /su/lib
  mkdir /su/etc
  set_perm 0 0 0755 /su/etc
  mkdir /su/su.d
  set_perm 0 0 0700 /su/su.d

  ui_print "- Removing old files"

  wipe_system_files_if_present
  wipe_data_competitors_and_cache

  rm -rf /su/bin/app_process
  rm -rf /su/bin/sush
  rm -rf /su/bin/daemonsu
  rm -rf /su/bin/daemonsu_*
  rm -rf /su/bin/su
  rm -rf /su/bin/su_*
  rm -rf /su/bin/supolicy
  rm -rf /su/bin/supolicy_*
  rm -rf /su/lib/libsupol.so
  rm -rf /su/lib/libsupol_*
  rm -rf /su/bin/sukernel

  ui_print "- Placing files"

  # Copy binaries and utilities
  cp_perm 0 0 0755 $BIN/$SU /su/bin/su
  cp_perm 0 0 0755 $BIN/$SU /su/bin/daemonsu
  ln_con /su/bin/su /su/bin/supolicy
  cp_perm 0 0 0755 $BIN/supolicy /su/bin/supolicy_wrapped
  cp_perm 0 0 0644 $BIN/libsupol.so /su/lib/libsupol.so
  cp_perm 0 0 0755 $BIN/sukernel /su/bin/sukernel

  # Copy APK, installation is done by /sbin/launch_daemonsu.sh
  if ($HAVEDATA); then
    cp_perm 1000 1000 0600 $COM/Superuser.apk /data/SuperSU.apk

    # Wipe /data/security to prevent SELinux policy override
    # Important to keep the folder itself
    rm -rf /data/security/*
  else
    cp_perm 1000 1000 0600 $COM/Superuser.apk /cache/SuperSU.apk
  fi

  if ($BINDSYSTEMXBIN); then
    mkdir /su/xbin_bind
    set_perm 0 0 0755 /su/xbin_bind
  else
    rm -rf /su/xbin_bind
  fi

  if ($PATCHBOOTIMAGE); then
    ui_print " "
    ui_print "******************"
    ui_print "Boot image patcher"
    ui_print "******************"

    ui_print "- Finding boot image"
    # expand the detection if we find more, instead of reading from fstab, because unroot
    # from the SuperSU APK doesn't have the fstab to read from
    if [ -z "$BOOTIMAGE" ]; then
      for PARTITION in kernel KERNEL boot BOOT lnx LNX; do
        BOOTIMAGE=$(readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION)
        if [ ! -z "$BOOTIMAGE" ]; then break; fi
      done
    fi

    CONTINUE=true
    if [ -z "$BOOTIMAGE" ]; then
      ui_print "--- Boot image: not found, aborting"
      CONTINUE=false
    else
      ui_print "--- Boot image: $BOOTIMAGE"
    fi

    if [ -z "$STOCKBOOTIMAGE" ]; then
      STOCKBOOTIMAGE=$BOOTIMAGE
    fi

    rm -rf /sutmp
    mkdir /sutmp

    check_zero_def "- Extracting ramdisk" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --bootimg-extract-ramdisk $BOOTIMAGE /sutmp/ramdisk.packed"
    check_zero_def "- Decompressing ramdisk" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --ungzip /sutmp/ramdisk.packed /sutmp/ramdisk"

    if ($CONTINUE); then
      ui_print "- Checking patch status"
      LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --patch-test /sutmp/ramdisk
      if [ $? -ne 0 ]; then
        ui_print "--- Already patched, attempting to find stock backup"

        if ($CONTINUE); then
          LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --restore /sutmp/ramdisk /sutmp/stock_boot.img
          if [ $? -ne 0 ]; then
            ui_print "--- Restore failed, aborting"
            CONTINUE=false
          else
            ui_print "--- Backup restored"
            STOCKBOOTIMAGE=/sutmp/stock_boot.img
          fi
        fi

        check_zero_def "- Extracting ramdisk" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --bootimg-extract-ramdisk /sutmp/stock_boot.img /sutmp/ramdisk.packed"
        check_zero_def "- Decompressing ramdisk" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --ungzip /sutmp/ramdisk.packed /sutmp/ramdisk"
        check_zero "- Checking patch status" "" "--- Already patched, aborting" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --patch-test /sutmp/ramdisk"
      else
        ui_print "- Creating backup"
        rm /data/stock_boot_*.img
        rm /data/stock_boot_*.img.gz
        rm /cache/stock_boot_*.img
        rm /cache/stock_boot_*.img.gz
        LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --backup $BOOTIMAGE
        if [ $? -ne 0 ]; then
          ui_print "--- Backup failed"
        fi
      fi
    fi

    if ($CONTINUE); then
      ui_print "- Patching sepolicy"

      check_zero_def "" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-extract /sutmp/ramdisk sepolicy /sutmp/sepolicy"

      if ($CONTINUE); then
        LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/supolicy --file /sutmp/sepolicy /sutmp/sepolicy_patched
        if [ ! -f "/sutmp/sepolicy_patched" ]; then
          ui_print "--- Failure, aborting"
          CONTINUE=false
        fi
      fi

      check_zero_def "" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-add /sutmp/ramdisk /sutmp/ramdisk 644 sepolicy /sutmp/sepolicy_patched"
    fi

    check_zero_def "- Patching daemon launcher" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-add /sutmp/ramdisk /sutmp/ramdisk 700 sbin/launch_daemonsu.sh $COM/launch_daemonsu.sh"

    if ($FSTABSYSTEMRW); then
      check_zero_def "- Patching init.*.rc, fstabs(r/w), file_contexts, dm-verity" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --patch-rw /sutmp/ramdisk /sutmp/ramdisk $STOCKBOOTIMAGE"
    else
      check_zero_def "- Patching init.*.rc, fstabs, file_contexts, dm-verity" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --patch /sutmp/ramdisk /sutmp/ramdisk $STOCKBOOTIMAGE"
    fi

    check_zero_def "- Compressing ramdisk" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --gzip /sutmp/ramdisk /sutmp/ramdisk.packed"
    check_zero_def "- Creating boot image" "LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --bootimg-replace-ramdisk $STOCKBOOTIMAGE /sutmp/ramdisk.packed /sutmp/boot.img"

    if ($CONTINUE); then
      if [ -f "/data/custom_boot_image_patch.sh" ]; then
        ui_print "- Calling user script"
        USER=$(sh /data/custom_boot_image_patch.sh /sutmp/boot.img)
        if [ $? -ne 0 ]; then
          ui_print "--- Failure, aborting"
          CONTINUE=false
        fi
      fi
    fi

    if ($CONTINUE); then
      DEV=$(echo $BOOTIMAGE | grep /dev/block/)
      if [ $? -eq 0 ]; then
        ui_print "- Flashing boot image"
        dd if=/dev/zero of=$BOOTIMAGE bs=4096
      else
        ui_print "- Saving boot image"
      fi
      dd if=/sutmp/boot.img of=$BOOTIMAGE bs=4096
    fi

    rm -rf /sutmp
  fi

  umount /su

  ui_print " "
  ui_print "*************************"
  ui_print "    IMPORTANT NOTICE     "
  ui_print "*************************"
  ui_print "If TWRP offers to install"
  ui_print "SuperSU, do *NOT* let it!"
  ui_print "*************************"
  ui_print " "
  sleep 5
fi

ui_print "- Unmounting /system"
umount /system

ui_print "- Done !"
exit 0
