You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

576 lines
17 KiB

#!/sbin/sh
# Minimal MicroG installer
# By FriendlyNeighborhoodShane
# Based on work by osm0sis @ xda-developers (Thanks!)
#
# Copyright 2018-2020 FriendlyNeighborhoodShane
# Distributed under the terms of the GNU GPL v3
exec 3>&1;
exec 1>&2;
outfd="/proc/self/fd/$2";
zipfile="$3";
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
ui_print() {
echo "$1" >&3;
};
else
ui_print() {
echo "ui_print $1" >> "$outfd";
echo "ui_print" >> "$outfd";
};
fi;
log() { echo "$1"; }
$bootmode || mount -o bind /dev/urandom /dev/random;
select_word() {
select_term="$1";
while read -r select_line; do
select_current=0;
select_found="";
for select_each in $select_line; do
select_current="$(( select_current + 1 ))";
[ "$select_current" = "$select_term" ] && { select_found="yes"; break; }
done;
[ "$select_found" = "yes" ] && echo "$select_each";
done;
}
file_getprop() {
grep "^$2" "$1" | head -n1 | select_word 1 | cut -d= -f2;
}
abort() {
ui_print " ";
ui_print "!!! FATAL ERROR: $1";
ui_print " ";
ui_print "Stopping installation and Uninstalling...";
uninstall_pack;
[ -d "$filedir" ] && rm -rf "$filedir";
[ -d "$bbdir" ] && rm -rf "$bbdir";
$bootmode || {
if [ "$sysroot" ]; then umount "/$sysroot"; else umount "/system"; fi;
}
sync;
ui_print " ";
ui_print "Installation failed!";
ui_print " ";
exit 1;
}
ui_print " ";
ui_print "-- Minimal MicroG Installer --";
ui_print "-- The Essentials only MicroG pack --";
modname="MinMicroG";
log " ";
log "Zip File is $zipfile";
log "Bootmode is $bootmode";
$bootmode || {
[ -e "/system" ] && mount -o ro /system;
[ -e "/system_root" ] && mount -o ro /system_root;
[ -e "/mnt/system" ] && mount -o ro /mnt/system;
mount /data;
}
[ -e "/system/system/build.prop" ] && sysroot="system";
[ -e "/system_root/system/build.prop" ] && sysroot="system_root";
[ -e "/mnt/system/system/build.prop" ] && sysroot="mnt/system";
[ -f "/$sysroot/system/build.prop" ] || abort "Could not find a ROM in /$sysroot";
bbdir="/tmp/busybox";
$bootmode || {
for bb in /data/adb/magisk/busybox; do
[ -f "$bb" ] && magiskbb="$bb";
done;
[ "$magiskbb" ] && {
ui_print " ";
ui_print "Setting up busybox...";
mkdir -p "$bbdir";
"$magiskbb" --install -s "$bbdir/";
export PATH="$bbdir:$PATH";
log "Shell path set to $PATH";
}
}
for bin in chcon chmod chown cp cut df du echo find grep head mkdir mount ps rm sed tail touch umount unzip; do
command -v "$bin" >/dev/null || abort "No $bin available";
done;
$bootmode && filedir="/dev/tmp/$modname" || filedir="/tmp/$modname";
tmplibdir="$filedir/tmplibdir";
$bootmode && forcesys=no;
case "$(basename "$zipfile")" in
*system*|*System*|*SYSTEM*)
forcesys=yes;
ui_print " ";
ui_print "WARNING: Forcing a system action!";
;;
esac;
case "$(basename "$zipfile")" in
*uninstall*|*Uninstall*|*UNINSTALL*)
action=uninstallation;
;;
*)
action=installation;
;;
esac;
abi="$(file_getprop /$sysroot/system/build.prop ro.product.cpu.abi)";
case "$abi" in
arm64*)
arch=arm64;
libarches="arm64-v8a armeabi-v7a armeabi";
;;
arm*)
arch=arm;
libarches="armeabi-v7a armeabi";
;;
x86_64*)
arch=x86_64;
libarches="x86_64 x86 armeabi-v7a armeabi";
;;
x86*)
arch=x86;
libarches="x86 armeabi-v7a armeabi";
;;
mips64*)
arch=mips64;
libarches="mips64 mips";
;;
mips*)
arch=mips;
libarches="mips";
;;
*)
abort "Could not recognise architecture: $abi";
;;
esac;
sdk="$(file_getprop /$sysroot/system/build.prop ro.build.version.sdk)";
[ "$sdk" ] || abort "Could not find SDK";
[ "$sdk" -gt 0 ] || abort "Could not recognise SDK: $sdk";
sizecheck() {
for realsizeobject in $1; do
sizeobject="$realsizeobject";
break;
done;
[ -e "$sizeobject" ] || { echo 0; return 0; }
objectsize="$(du -s "$sizeobject" | select_word 1)";
libsize=0;
case "$sizeobject" in
*.apk)
apkunzip="$(unzip -l "$sizeobject" "lib/*/lib*.so")";
if echo "$apkunzip" | grep -q "lib/.*/lib.*.so"; then
for archlib in $libarches; do
if echo "$apkunzip" | grep -q "lib/$archlib/lib.*.so"; then
libsizeb=0;
for entry in $(unzip -l "$sizeobject" | grep "lib/$archlib/lib.*.so" | select_word 1); do
libsizeb="$(( libsizeb + entry ))";
done;
libsize="$(( libsizeb / 1024 + 1 ))";
break;
fi;
done;
fi;
;;
esac;
echo "$(( objectsize + libsize ))";
}
remove() {
removalobject="$1";
backupobject="$2";
if [ "$sdk" -lt 21 ]; then
[ "$(basename "$(dirname "$removalobject")").apk" = "$(basename "$removalobject")" ] && {
removalobject="$(dirname "$(dirname "$removalobject")")/$(basename "$removalobject")";
backupobject="$(dirname "$(dirname "$backupobject")")/$(basename "$backupobject")";
}
fi;
[ "$(basename "$(dirname "$removalobject")").apk" = "$(basename "$removalobject")" ] && {
removalobject="$(dirname "$removalobject")";
backupobject="$(dirname "$backupobject")";
}
[ -e "$removalobject" ] || return 0;
mkdir -p "$(dirname "$backupobject")";
cp -rf "$removalobject" "$backupobject";
if [ -e "$backupobject" ]; then
log "BACKUPER: Object backed up ($removalobject)";
else
log "ERROR: Could not backup ($removalobject)";
fi;
rm -rf "$removalobject" || { log "ERROR: Could not remove ($removalobject)"; return 1; }
if [ -e "$removalobject" ]; then
log "ERROR: Could not remove ($removalobject)";
return 1;
else
log "REMOVER: Object removed ($removalobject)";
fi;
}
debloat() {
debloatobject="$1";
debloatingobject="$2";
if [ "$sdk" -lt 21 ]; then
[ "$(basename "$(dirname "$debloatobject")").apk" = "$(basename "$debloatobject")" ] && {
debloatobject="$(dirname "$(dirname "$debloatobject")")/$(basename "$debloatobject")";
debloatingobject="$(dirname "$(dirname "$debloatingobject")")/$(basename "$debloatingobject")";
}
fi;
[ "$(basename "$(dirname "$debloatobject")").apk" = "$(basename "$debloatobject")" ] && debloatobject="$(dirname "$debloatobject")";
[ -e "$debloatobject" ] || return 0;
mkdir -p "$(dirname "$debloatingobject")";
if [ "$(basename "$(dirname "$debloatingobject")").apk" = "$(basename "$debloatingobject")" ]; then
if touch "$(dirname "$debloatingobject")/.replace"; then
log "DEBLOATER: Object directory debloated ($debloatobject)";
else
log "ERROR: Could not create replace file for object $debloatobject";
return 1;
fi;
elif [ -d "$debloatobject" ]; then
mkdir -p "$debloatingobject";
if touch "$debloatingobject/.replace"; then
log "DEBLOATER: directory debloated ($debloatobject)";
else
log "ERROR: Could not create replace file for directory $debloatobject";
return 1;
fi;
else
if echo "# This is a dummy for debloating" > "$debloatingobject"; then
log "DEBLOATER: Object dummy debloated ($debloatobject)";
else
log "ERROR: Could not create dummy file for $debloatobject";
return 1;
fi;
fi;
}
uninstall() {
uninstallobject="$1";
if [ "$sdk" -lt 21 ]; then
[ "$(basename "$(dirname "$uninstallobject")").apk" = "$(basename "$uninstallobject")" ] && uninstallobject="$(dirname "$(dirname "$uninstallobject")")/$(basename "$uninstallobject")";
fi;
[ "$(basename "$(dirname "$uninstallobject")").apk" = "$(basename "$uninstallobject")" ] && uninstallobject="$(dirname "$uninstallobject")";
[ -e "$uninstallobject" ] || return 0;
rm -rf "$uninstallobject" || {
log "ERROR: Object not uninstalled ($uninstallobject)";
return 1;
}
if [ -e "$uninstallobject" ]; then
log "ERROR: Object not uninstalled ($uninstallobject)";
return 1;
else
log "UNINSTALLER: Object uninstalled ($uninstallobject)";
fi;
}
install_dest() {
for realobject in $1; do
object="$realobject";
break;
done;
destobject="$2";
[ -e "$object" ] || { log "ERROR: Object not found ($object)"; return 1; }
if [ "$sdk" -lt 21 ]; then
[ "$(basename "$(dirname "$destobject")").apk" = "$(basename "$destobject")" ] && destobject="$(dirname "$(dirname "$destobject")")/$(basename "$destobject")";
fi;
mkdir -p "$(dirname "$destobject")";
cp -rf "$object" "$destobject" || abort "Could not install $destobject";
if [ -e "$destobject" ]; then
log "INSTALLER: Object installed ($object to $destobject)";
else
abort "Could not install $destobject";
fi;
case "$destobject" in
*.apk)
install_lib "$destobject";
;;
esac;
}
install_lib() {
libobject="$1";
mkdir -p "$tmplibdir";
unzipout="$(unzip -l "$libobject" "lib/*/lib*.so")";
echo "$unzipout" | grep -q "lib/.*/lib.*.so" || return 0;
for archlib in $libarches; do
if echo "$unzipout" | grep -q "lib/$archlib/lib.*.so"; then
case "$archlib" in
*arm64*)
log "INSTALLER: Installing arm64 libs ($libobject)";
libdir=lib64;
libarch=arm64;
;;
*arm*)
log "INSTALLER: Installing arm libs ($libobject)";
libdir=lib;
libarch=arm;
;;
*x86_64*)
log "INSTALLER: Installing x86_64 libs ($libobject)";
libdir=lib64;
libarch=x86_64;
;;
*x86*)
log "INSTALLER: Installing x86 libs ($libobject)";
libdir=lib;
libarch=x86;
;;
*mips64*)
log "INSTALLER: Installing mips64 libs ($libobject)";
libdir=lib64;
libarch=mips64;
;;
*mips*)
log "INSTALLER: Installing mips libs ($libobject)";
libdir=lib;
libarch=mips;
;;
esac;
if [ "$sdk" -lt 21 ]; then
libdest="$(dirname "$(dirname "$libobject")")/$libdir";
else
libdest="$(dirname "$libobject")/lib/$libarch";
fi;
unzip -oq "$libobject" "lib/$archlib/lib*.so" -d "$tmplibdir";
mkdir -p "$libdest";
for lib in "$tmplibdir/lib/$archlib"/lib*.so; do
cp -rf "$lib" "$libdest/$(basename "$lib")" || abort "Could not Install $lib for $libobject";
if [ -f "$libdest/$(basename "$lib")" ]; then
log "INSTALLER: Installed library ($lib to $libdest)";
else
abort "Could not Install $lib for $libobject";
fi;
done;
break;
fi;
done;
rm -rf "$tmplibdir";
}
uninstall_pack() {
if [ "$magisk" = "yes" ]; then
rm -rf "$root" || { log " "; log "Could not delete Magisk root ($root)"; }
elif [ "$magisk" = "no" ]; then
for thing in $stuff_uninstall; do
[ "$thing" ] && uninstall "$root/$thing";
done;
fi;
}
perm() {
uid="$1";
gid="$2";
dmod="$3";
fmod="$4";
permobject="$5";
[ -e "$permobject" ] || return 0;
chown -R "$uid:$gid" "$permobject" || chown -R "$uid.$gid" "$permobject";
find "$permobject" -type d -exec chmod "$dmod" {} +;
find "$permobject" -type f -exec chmod "$fmod" {} +;
}
rm -rf "$filedir";
mkdir -p "$filedir";
unzip -o "$zipfile" "defconf" -d "$filedir/";
[ -f "$filedir/defconf" ] || abort "Could not find a default config";
. "$filedir/defconf" || abort "Could not execute default config";
moddir="/data/media/0/$modname";
backupdir="$moddir/Backup";
ui_print " ";
ui_print "Package: $variant";
ui_print "Version: $ver";
ui_print "Release date: $date";
ui_print " ";
ui_print "Using architecture: $arch";
ui_print "Using SDK level: $sdk";
ui_print "Sysroot is on /$sysroot";
if [ "$sdk" -lt "$minsdk" ]; then
ui_print " ";
ui_print "WARNING: Using an old Android";
ui_print "Full compatibility not guaranteed";
fi;
ui_print " ";
ui_print "Mounting...";
if [ -e "/data/adb/magisk" ] && [ "$forcesys" != "yes" ]; then
$bootmode && modulesdir="/data/adb/modules_update" || modulesdir="/data/adb/modules";
root="$modulesdir/$modname";
magisk=yes;
log "Using $modulesdir";
[ -d "$modulesdir" ] || {
mkdir -p "$modulesdir";
perm 0 0 0755 0644 "$modulesdir";
}
else
if [ "$sysroot" ]; then
mount -o rw,remount /$sysroot;
mount -o rw,remount /$sysroot /$sysroot;
else
mount -o rw,remount /system;
mount -o rw,remount /system /system;
fi;
root="/$sysroot";
magisk=no;
log "Mounted /$sysroot/system RW";
fi;
if [ "$action" = "installation" ]; then
ui_print " ";
ui_print "Extracting files...";
mkdir -p "$filedir";
unzip -o "$zipfile" -d "$filedir" || abort "Could not unzip $zipfile";
pre_install_actions;
ui_print " ";
ui_print "Cleaning up...";
log "Removing duplicates";
uninstall_pack;
log "Debloating";
if [ "$magisk" = "yes" ]; then
for thing in $stuff_debloat $stuff_uninstall; do
[ "$thing" ] && debloat "/$sysroot/$thing" "$root/$thing";
done;
elif [ "$magisk" = "no" ]; then
for thing in $stuff_debloat; do
[ "$thing" ] && remove "/$sysroot/$thing" "$backupdir/$thing";
done;
fi;
[ -d "$backupdir" ] && {
perm 1023 1023 775 664 "$backupdir";
chcon -hR 'u:object_r:media_rw_data_file:s0' "$backupdir";
}
ui_print " ";
ui_print "Doing size checks...";
packsize=0;
for thing in defconf $stuff; do
[ "$thing" ] && packsize="$(( packsize + $(sizecheck "$filedir/$thing") ))";
done;
for thing in $stuff_arch; do
[ "$thing" ] && packsize="$(( packsize + $(sizecheck "$filedir/$(dirname "$thing")/*-$arch-*/$(basename "$thing")") ))";
done;
for thing in $stuff_sdk; do
[ "$thing" ] && packsize="$(( packsize + $(sizecheck "$filedir/$(dirname "$thing")/*-$sdk-*/$(basename "$thing")") ))";
done;
for thing in $stuff_arch_sdk; do
[ "$thing" ] && packsize="$(( packsize + $(sizecheck "$filedir/$(dirname "$thing")/*-$arch-*-$sdk-*/$(basename "$thing")") ))";
done;
packsizem="$(( packsize / 1024 + 1 ))";
log "Pack size is $packsizem";
if [ "$magisk" = "yes" ]; then
datfreem="$(( $(df -Pk "/data" | tail -n 1 | select_word 4) / 1024 ))";
log "Free data space is $datfreem";
[ "$datfreem" -lt "$packsizem" ] && abort "Not enough free space in your data!";
elif [ "$magisk" = "no" ]; then
sysfreem="$(( $(df -Pk "/$sysroot/system" | tail -n 1 | select_word 4) / 1024 ))";
log "Free system space is $sysfreem";
[ "$sysfreem" -lt "$packsizem" ] && abort "Not enough free space in your system!";
fi;
ui_print " ";
ui_print "Installing $modname to $root...";
mkdir -p "$root";
log " ";
log "Installing generic stuff";
for thing in $stuff; do
[ "$thing" ] && install_dest "$filedir/$thing" "$root/$thing";
done;
log " ";
log "Installing Arch dependant stuff for $arch";
for thing in $stuff_arch; do
[ "$thing" ] && install_dest "$filedir/$(dirname "$thing")/*-$arch-*/$(basename "$thing")" "$root/$thing";
done;
log " ";
log "Installing SDK dependant stuff for SDK $sdk";
for thing in $stuff_sdk; do
[ "$thing" ] && install_dest "$filedir/$(dirname "$thing")/*-$sdk-*/$(basename "$thing")" "$root/$thing";
done;
log " ";
log "Installing Arch and SDK dependant stuff for $arch and SDK $sdk";
for thing in $stuff_arch_sdk; do
[ "$thing" ] && install_dest "$filedir/$(dirname "$thing")/*-$arch-*-$sdk-*/$(basename "$thing")" "$root/$thing";
done;
log " ";
log "Executing other actions";
if [ "$magisk" = "yes" ]; then
[ "$modprop" ] && {
echo "$modprop" > "$root/module.prop" || abort "Could not create module.prop in $root";
}
touch "$root/auto_mount" || abort "Could not create auto_mount in $root";
if $bootmode && [ "$modulesdir" = "/data/adb/modules_update" ]; then
modmnt="/data/adb/modules";
mkdir -p "$modmnt/$modname";
touch "$modmnt/$modname/update" || abort "Could not create update in $modmnt/$modname";
[ "$modprop" ] && {
echo "$modprop" > "$modmnt/$modname/module.prop" || abort "Could not create module.prop in $modmnt/$modname";
}
fi;
fi;
ui_print " ";
ui_print "Setting permissions...";
if [ "$magisk" = "yes" ]; then
find "$root" -maxdepth 1 -exec chmod 0755 {} +;
fi;
for thing in $stuff_perm; do
case "$thing" in
*/bin*|*/xbin*|*/lib*)
perm 0 2000 0755 0777 "$root/$thing";
;;
*)
perm 0 0 0755 0644 "$root/$thing";
;;
esac;
chcon -hR 'u:object_r:system_file:s0' "$root/$thing";
done;
post_install_actions;
fi;
if [ "$action" = "uninstallation" ]; then
pre_uninstall_actions;
ui_print " ";
ui_print "Uninstalling $modname from $root...";
uninstall_pack;
post_uninstall_actions;
fi;
ui_print " ";
ui_print "Unmounting...";
$bootmode || {
if [ "$sysroot" ]; then umount "/$sysroot"; else umount /system; fi;
}
rm -rf "$filedir";
[ -d "$bbdir" ] && rm -rf "$bbdir";
sync;
ui_print " ";
ui_print "Done!";
ui_print " ";
exit 0;