#!/sbin/sh
# Busybox Installer Script: Recovery Flashable Zip
# osm0sis @ xda-developers

OUTFD=/proc/self/fd/$2;
ZIPFILE="$3";

# embedded mode support
readlink /proc/$$/fd/$2 2>/dev/null | grep /tmp >/dev/null;
if [ "$?" -eq "0" ]; then
  # rerouted to log file, so suppress recovery ui commands
  OUTFD=/proc/self/fd/0;
  # try to find the actual fd (pipe with parent updater likely started as 'update-binary 3 fd zipfile')
  for FD in `ls /proc/$$/fd`; do
    readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null;
    if [ "$?" -eq "0" ]; then
      ps | grep " 3 $FD " | grep -v grep >/dev/null;
      if [ "$?" -eq "0" ]; then
        OUTFD=/proc/self/fd/$FD;
        break;
      fi;
    fi;
  done;
fi;

# Magisk boot mode support
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false;
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true;
if $BOOTMODE; then
  OUTFD=/proc/self/fd/0;
  dev=/dev;
  if [ ! -f /data/magisk_merge.img ]; then
    /system/bin/make_ext4fs -l 64M /data/magisk_merge.img >/dev/null;
  fi;
fi;

ui_print() { $BOOTMODE && echo "$1" || echo -e "ui_print $1\nui_print" >> $OUTFD; }
show_progress() { echo "progress $1 $2" >> $OUTFD; }
set_progress() { echo "set_progress $1" >> $OUTFD; }
file_getprop() { grep "^$2" "$1" | head -n1 | cut -d= -f2; }
abort() {
  ui_print " ";
  ui_print "Your system has not been changed.";
  ui_print " ";
  ui_print "Script will now exit...";
  ui_print " ";
  umount $mnt;
  umount /system;
  umount /data;
  umount /cache;
  exit 1;
}

ui_print " ";
ui_print "Busybox Installer Script";
ui_print "by osm0sis @ xda-developers";
modname=busybox-ndk;
show_progress 1.34 0;

ui_print " ";
ui_print "Mounting...";
mount -o ro /system;
mount /data;
mount /cache;
set_progress 0.2;

case $(basename "$ZIPFILE") in
  *uninstall*|*Uninstall*) action=uninstallation;;
  *) action=installation;;
esac;

case $(basename "$ZIPFILE") in
  *system*) ui_print " "; ui_print "Warning: Forcing a system $action!";;
esac;

if [ "$action" == "installation" ]; then
  ui_print " ";
  ui_print "Extracting files...";
  mkdir -p $dev/tmp/$modname;
  cd $dev/tmp/$modname;
  unzip -o "$ZIPFILE";
  set_progress 0.3;

  ui_print " ";
  ui_print "Installing...";
  abi=`getprop ro.product.cpu.abi`;
  case $abi in
    arm*|x86*|mips*) ;;
    *) abi=`file_getprop /default.prop ro.product.cpu.abi`;;
  esac;
  test -f /system/system/build.prop && root=/system;
  case $abi in
    arm*|x86*|mips*) ;;
    *) abi=`file_getprop $root/system/build.prop ro.product.cpu.abi`;;
  esac;
  case $abi in
    arm64*) arch=arm64;;
    arm*) arch=arm;;
    x86_64*) arch=x86_64;;
    x86*) arch=x86;;
    mips64*) arch=mips64;;
    mips*) arch=mips;;
    *) ui_print "Unknown architecture: $abi"; abort;;
  esac;
  ui_print "Using architecture: $arch";
else
  ui_print " ";
  ui_print "Uninstalling...";
fi;

# allow forcing a system installation regardless of su.img/magisk.img detection
case $(basename "$ZIPFILE") in
  *system*) ;;
  *) suimg=$(ls /data/su.img || ls /cache/su.img || ls /data/magisk_merge.img || ls /data/magisk.img || ls /cache/magisk.img) 2>/dev/null; mnt=$dev/$(basename $suimg .img);;
esac;
if [ "$suimg" ]; then
  umount $mnt;
  test ! -e $mnt && mkdir $mnt;
  mount -t ext4 -o rw,noatime $suimg $mnt;
  for i in 0 1 2 3 4 5 6 7; do
    case `mount` in
      *" $mnt "*) break;;
    esac;
    loop=/dev/block/loop$i;
    if [ ! -f "$loop" -o ! -b "$loop" ]; then
      mknod $loop b 7 $i;
    fi;
    losetup $loop $suimg && mount -t ext4 -o loop $loop $mnt;
  done;
  case $mnt in
    */magisk*) magisk=/$modname/system;;
  esac;
  test -d $mnt$magisk/xbin -o "$magisk" && target=$mnt$magisk/xbin || target=$mnt/bin;
else
  mount -o rw,remount /system;
  mount /system;
  target=$root/system/xbin;
fi;
ui_print "Using path: $target";
if [ "$action" == "uninstallation" ]; then
  if [ ! -f "$target/busybox" ]; then
    ui_print " ";
    ui_print "No busybox installation found!";
    abort;
  fi;
else
  mkdir -p $target;
  cp -f busybox-$arch $target/busybox;
  chown 0:0 "$target/busybox";
  chmod 755 "$target/busybox";
  if [ "$magisk" ]; then
    cp -f module.prop $mnt/$modname/;
    touch $mnt/$modname/auto_mount;
    if $BOOTMODE; then
      mkdir -p /magisk/$modname;
      touch /magisk/$modname/update;
      cp -f module.prop /magisk/$modname/;
    fi;
  fi;
  set_progress 0.8;

  ui_print " ";
  ui_print "Cleaning...";
fi;
cleanup="$target";
if [ "$target" == "$mnt$magisk/xbin" -a -f "$mnt$magisk/bin/busybox" ]; then
  $target/busybox rm -f $mnt$magisk/bin/busybox;
  cleanup="$mnt$magisk/bin $target";
fi;
for dir in $cleanup; do
  cd $dir;
  for i in $(ls -al `find -type l` | $target/busybox awk '{ print $(NF-2) ":" $NF }'); do
    case $(echo $i | $target/busybox cut -d: -f2) in
      *busybox) list="$list $dir/$(echo $i | $target/busybox cut -d: -f1)";;
    esac;
  done;
done;
test "$action" == "uninstallation" && list="$list busybox";
$target/busybox rm -f $list;

if [ "$action" == "installation" ]; then
  ui_print " ";
  ui_print "Creating symlinks...";
  for applet in `$target/busybox --list`; do
    if [ "$target" == "$mnt$magisk/bin" ]; then
      sysbin="$(ls /system/bin)";
      case $sysbin in
        *$applet*) ;;
        *) $target/busybox ln -sf busybox $applet;;
      esac;
    else
      $target/busybox ln -sf busybox $applet;
    fi;
  done;
else
  test "$magisk" rm -rf /magisk/$modname;
fi;
set_progress 1.0;

ui_print " ";
ui_print "Unmounting...";
cd /;
umount $mnt;
umount /system;
umount /data;
umount /cache;
set_progress 1.2;

rm -rf /tmp/$modname /dev/tmp;
ui_print " ";
ui_print "Done!";
set_progress 1.34;
exit 0;

