## [Magisk] [nethunter] [This is sourced, not a standalone script]
## Kali NetHunter installation script for Magisk
##
## REF: https://topjohnwu.github.io/Magisk/guides.html
##      https://github.com/topjohnwu/Magisk/blob/master/scripts/update_binary.sh
##      https://github.com/topjohnwu/Magisk/blob/master/scripts/util_functions.sh
##
## Troubleshoot: Save log via Magisk && $ adb shell 'cat /sdcard/Download/magisk_install_log_*.log; rm /sdcard/Download/magisk_install_log_*.log'

do_flash() {
  export TARGET=$(getprop ro.product.device)
  ui_print "* Target device: $TARGET"
  ui_print "* Found Kali kernel to be installed: $KERNEL"
  ## Kernel only installer in Magisk
  mkdir -p "$TMP/boot-patcher"
  unzip -qq "$KERNEL" -d "$TMP/boot-patcher"
  ## #1 - Down side the output isn't formatted
  #sh $TMP/tools/magic-flash.sh $KERNEL 2>&1 || abort "! magic-flash.sh failed"

  ## #2 - Down side not sure if it exits cleanly
  ## Replace ui_print, indent output (to signal its a script) and remove empty lines
  sh $TMP/tools/magic-flash.sh $KERNEL | awk 'gsub(/ui_print /," ") && !/^ $/'

  ## #3 - Down side the output isn't in real time
  #OUT=$( sh $TMP/tools/magic-flash.sh $KERNEL 2>&1 )
  #ret=$?
  #if [ "$ret" -eq 0 ]; then
  #  ## Replace ui_print, indent output (to signal its a script) and remove empty lines
  #  echo "${OUT}" | awk 'gsub(/ui_print /," ") && !/^ $/'
  #else
  #  echo "${OUT}"   # Will be much more verbose
  #  abort "! magic-flash.sh failed: $ret"
  #fi

  ## #4 - Can't do this bash trick, as using sh (shell)
  ## Replace ui_print, indent output (to signal its a script) and remove empty lines
  #sh $TMP/tools/magic-flash.sh $KERNEL 2>&1 | awk 'gsub(/ui_print /," ") && !/^ $/'   # Spawn a new session (aka using sh), don't do it in the current session
  #ret=${PIPESTATUS[0]}   # We want magic-flash.sh exit code, not awk!
  #[ "$ret" -eq 0 ] || abort "! magic-flash.sh failed: $ret"

  ## If script wasn't sourced, would it still be an issue?
}

flash_kernel() {
  [ -e "$ZIPFILE" ] && {
    ## Create kernel-nethunter.zip
    ui_print "* Preparing kernel zip"
    KERNEL=kernel-nethunter.zip
    cp META-INF/com/google/android/update-binary-nethunter META-INF/com/google/android/update-binary
    $TMP/tools/zip -qq -r $KERNEL *
    ## If failed to create a kernel-*.zip
    [ "$KERNEL" ] || {
      ui_print "* Kernel zip preparation failed.. Skipping"
      return
    }
    do_flash || abort "! flash_kernel failed"
  }
}

push_modules() {
   [ ! -d "$TMP/modules" ] && {
      ui_print "  - No modules to push, skipping"
      return
   }
   NHMODULES_DIR=`ls "$TMP/modules"`   
   ui_print "  - Copying modules"
   mkdir -p "$MODPATH/system/lib"
   cp -r "$TMP/modules/$NHMODULES_DIR/lib/modules" "$MODPATH/system/lib"   
   if [ -d "$MODPATH/system/lib/modules" ]; then
     ui_print "  - Modules copied successfully to /system/lib/modules."
   else
     ui_print "- Failed to copy modules to /system/lib/modules."
   fi
}

#------------------------------------------------------------------------------

#<REF: ./scripts/util_functions.sh>
#########################
# Install module
#########################
rm -rf $TMPDIR
mkdir -p $TMPDIR
chcon u:object_r:system_file:s0 $TMPDIR
cd $TMPDIR

setup_flashable
mount_partitions || true
api_level_arch_detect

## Setup BusyBox and binaries
boot_actions

## Extract prop file
unzip -qq -o "$ZIPFILE" module.prop -d $TMPDIR >&2 || print "! Failed to extract"
[ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!"

MODDIRNAME=modules_update
MODULEROOT=/data/adb/$MODDIRNAME
MODID=$(grep_prop id $TMPDIR/module.prop)
MODNAME=$(grep_prop name $TMPDIR/module.prop)
MODAUTH=$(grep_prop author $TMPDIR/module.prop)
MODPATH=$MODULEROOT/$MODID

## Create mod paths
rm -rf $MODPATH
mkdir -p $MODPATH || abort "! Unable to: mkdir -p $MODPATH"
#</REF: ./scripts/util_functions.sh>

## Define several variables
[ -z "$TMPDIR" ] && TMPDIR=/dev/tmp
[ -n "$ZIP" ] && { ZIPFILE="$ZIP"; unset ZIP; }
[ -z "$ZIPFILE" ] && ZIPFILE="$3"
DIR=$(dirname "$ZIPFILE")
TMP=$TMPDIR/$MODID

## Magisk manager/booted flashing support
OUTFD=/proc/self/fd/0
[ -e /data/adb/magisk ] && ADB=adb
if [ -e /data/$ADB/magisk ]; then
  [ -e /magisk/.core/busybox ] && MAGISKBB=/magisk/.core/busybox
  [ -e /sbin/.core/busybox ] && MAGISKBB=/sbin/.core/busybox
  [ -e /sbin/.magisk/busybox ] && MAGISKBB=/sbin/.magisk/busybox
  [ -e /dev/*/.magisk/busybox ] && MAGISKBB=$(echo /dev/*/.magisk/busybox)
  [ -e /data/$ADB/ksu/bin/busybox ] && MAGISKBB=/data/$ADB/ksu/bin/busybox
  [ -e /data/$ADB/ap/bin/busybox ] && MAGISKBB=/data/$ADB/ap/bin/busybox
  [ "$MAGISKBB" ] && export PATH="$MAGISKBB:$PATH"
  [ "$MAGISKBB" ] \
    && debug "MAGISKBB: $MAGISKBB" \
    || debug "Inside of Magisk without BusyBox"
elif [ ! -f "$MAGISKBB" ]; then
  debug "Not inside of Magisk?"
fi

## Define modules target dirs
if [ -e /data/adb/modules ]; then
  MNT=/data/adb/modules_update
  MAGISK=/$MODID/system
fi

## Set target paths
[ ! -z $MODPTH ] || MODPATH=$MNT/$MODID
TARGET=$MNT$MAGISK
ETC=$TARGET/etc
BIN=$TARGET/bin

if [ -d /system/xbin ]; then
  XBIN=$TARGET/xbin
else
  XBIN=$TARGET/bin
fi

UMASK=$(umask)
umask 022

#------------------------------------------------------------------------------

## Ensure zip installer shell is in a working scratch directory
mkdir -p $TMPDIR
cd $TMPDIR

## Source custom installer functions and configuration
#unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 || print "! Failed to extract"
#MODID=$(file_getprop module.prop id) # Alt: MODID=$(grep_prop id $TMPDIR/module.prop)

## Extract the ZIP
ui_print "* Unpacking ZIP"
mkdir -p $TMPDIR/$MODID
cd $TMPDIR/$MODID
## Unpack the ZIP (everything but "kalifs-*")
unzip -qq "$ZIPFILE" -x "kalifs-*" || print "! Failed to extract"
#ui_print "* ZIP unpacked"

#------------------------------------------------------------------------------

## Setup environment before installations
##   Mount System as r/w just incase we need it
ui_print "* Setting environment"
DYNAMIC=false
SAR=false
if [ -d /dev/block/mapper ]; then
  for block in system; do
    for slot in "" _a _b; do
      blockdev --setrw /dev/block/mapper/$block$slot 2>/dev/null
    done
  done
  DYNAMIC=true
fi
mount -o rw,remount -t auto /system || mount /system || true
[ $? != 0 ] && mount -o rw,remount -t auto / && SAR=true

#------------------------------------------------------------------------------

## Install wireless firmwares
[ -d $TMP/system/etc/firmware ] && {
  ui_print "* Copying Wi-Fi firmwares to /system/etc/firmware"
  mkdir -p $ETC
  cp -r "$TMP/system/etc/firmware" "$ETC/"
  set_perm_recursive "$ETC/firmware" 0 0 0755 0644
}

#------------------------------------------------------------------------------

## Install modules
ui_print "* Pushing modules"
push_modules || ui_print "[!] Failed to push modules"

#------------------------------------------------------------------------------

## Install kernel
ui_print "* Flashing kernel"
flash_kernel || ui_print "[!] Failed to flash kernel"

#------------------------------------------------------------------------------

## Random important Magisk stuff (Don't remove)
ui_print "* Important Magisk items"
cp -fp $TMP/module.prop $MNT/$MODID/
touch $MNT/$MODID/auto_mount
[ -e /data/adb/modules ] && IMGMNT=/data/adb/modules
mkdir -p "$IMGMNT/$MODID"
touch "$IMGMNT/$MODID/update"
cp -fp $TMP/module.prop "$IMGMNT/$MODID/"

#------------------------------------------------------------------------------

ui_print "* Restoring environment"
cd /

## Restore environment after installations
if [ -d /dev/block/mapper ]; then
  for block in system; do
    for slot in "" _a _b; do
      blockdev --setro /dev/block/mapper/$block$slot 2>/dev/null
    done
  done
fi
[ "$SAR" ] && mount -o ro,remount / || mount -o ro,remount /system

## Handle replace folders
for TARGET in $REPLACE; do
  ui_print "* Replace target: $TARGET"
  mktouch $MODPATH$TARGET/.replace
done

#------------------------------------------------------------------------------

## Clean up
ui_print "* Cleaning up"
[ -n "$DEBUG" ] || rm -rf $TMPDIR
umask $UMASK

## Done

#------------------------------------------------------------------------------

#<REF: ./scripts/util_functions.sh>
## Update info for Magisk
print "* Setting Magisk metadata"
mktouch /data/adb/modules/$MODID/update
rm -rf /data/adb/modules/$MODID/remove 2>/dev/null
rm -rf /data/adb/modules/$MODID/disable 2>/dev/null
cp -af $MODPATH/module.prop /data/adb/modules/$MODID/module.prop

## Copy over custom sepolicy rules
if [ -f $MODPATH/sepolicy.rule ]; then
  print "* Installing custom sepolicy rules"
  copy_preinit_files
fi

## Remove stuff that doesn't belong to modules and clean up any empty directories
rm -rf $MODPATH/update-magisk \
       $MODPATH/system/placeholder \
       $MODPATH/customize.sh \
       $MODPATH/README.md \
       $MODPATH/.git*
#rmdir -p $MODPATH 2>/dev/null

cd /
[ -n "$DEBUG" ] || rm -rf $TMPDIR
#</REF: ./scripts/util_functions.sh>
