Let's make panini .. XD
#!/system/bin/sh
# Panini by shakalaca@23pin
########## environment variables ##########
MODE=$1
# block device and mount point for panini, configure before using
CONTAINER_DEV=/dev/block/bootdevice/by-name/APD
# special case for ZenFone x86
if [ -L /dev/block/by-name/APD ]; then
CONTAINER_DEV=/dev/block/by-name/APD
fi
CONTAINER_MNT=/APD
LOG_FILE=/cache/panini.log
UNBLOCK_FILE=/cache/panini.post-fs
ROOT_MNT_SYSTEM=$CONTAINER_MNT/system_mnt
ROOT_BIND_SYSTEM=$CONTAINER_MNT/system_bind
ROOT_PANINI=$CONTAINER_MNT/panini
########## routines ##########
getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$"$VARNAME");
for FILE in /data/panini/config /cache/panini.conf; 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
}
log_print() {
echo "$1" >> $LOG_FILE
}
get_mount_dev() {
_mount=`cat /proc/mounts | grep "$1"`
echo ${_mount% /*}
}
get_selinux_context() {
F_INFO=(`ls -Z $1`)
echo ${F_INFO[3]}
}
bind_mount() {
log_print "Mount $1 to $2"
mount -o bind $1 $2
}
touch_perm() {
log_print "Touching $1"
touch $1
chmod 644 $1
}
mkdir_perm() {
log_print "Creating tree $1"
mkdir -p $1
chmod 755 $1
if [ ! -z "$2" ]; then
chcon $2 $1
fi
}
is_mounted() {
cat /proc/mounts | grep $1 >/dev/null
return $?
}
is_os_upgraded() {
OS_VERSION=`cat /system/build.prop|grep ro.build.fingerprint`
PANINI_VERSION=`cat /data/panini/version 2>/dev/null`
if [ "$OS_VERSION" != "$PANINI_VERSION" ]; then
cat /system/build.prop|grep ro.build.fingerprint > /data/panini/version
echo "true"
else
echo "false"
fi
}
is_dir_changed() {
LS_INFO=(`ls -l ${ROOT_PANINI%/*} | grep " ${ROOT_PANINI##*/}$"`)
CURRENT_MODIFY="${LS_INFO[3]} ${LS_INFO[4]}"
PANINI_MODIFY=`cat /data/panini/modify 2>/dev/null`
if [ "$CURRENT_MODIFY" != "$PANINI_MODIFY" ]; then
echo $CURRENT_MODIFY > /data/panini/modify
echo "true"
else
echo "false"
fi
}
process() {
for f in `ls $2`; do
local SOURCE=$2/$f
local TARGET=$ROOT_BIND_SYSTEM${2#$1}/$f
local PANINI=$ROOT_PANINI${2#$1}/$f
# symbolic link
if [ -L $SOURCE ]; then
cp -an $SOURCE $TARGET
# directory
elif [ -d $SOURCE ]; then
if [ -d $PANINI ] || [ "$f" == "bin" ] || [ "$f" == "xbin" ]; then
# check if removed by request
if [ ! -f $PANINI/.remove ]; then
mkdir_perm $TARGET
process $1 $SOURCE
fi
else
mkdir_perm $TARGET
fi
# file
else
if [[ $2 == *bin ]] || [[ $2 == *xbin ]]; then
cp -an $SOURCE $TARGET
local F_SECONTEXT=$(get_selinux_context $SOURCE)
if [ "$F_SECONTEXT" != "u:object_r:system_file:s0" ]; then
chcon $F_SECONTEXT $TARGET
fi
else
touch_perm $TARGET
fi
fi
done
}
process_after_bind_tree() {
EXEC_FILE=/data/panini/after_bind_tree.sh
if [ -f $EXEC_FILE ]; then
chmod +x $EXEC_FILE
eval ". $EXEC_FILE"
fi
}
exit_unblock() {
touch_perm $UNBLOCK_FILE
exit 0
}
########## main ##########
if [ ! -d /data/panini ]; then
mkdir_perm /data/panini
fi
getvar CONTAINER_DEV
getvar CONTAINER_MNT
getvat ROOT_MNT_SYSTEM
getvar ROOT_BIND_SYSTEM
getvar ROOT_PANINI
if [ ! $(is_mounted $CONTAINER_MNT) ]; then
mount -r -w -t ext4 -o noatime $CONTAINER_DEV $CONTAINER_MNT
fi
if [ ! $(is_mounted $ROOT_MNT_SYSTEM) ]; then
mkdir_perm $ROOT_MNT_SYSTEM u:object_r:system_file:s0
mount -r -t ext4 -o noatime $(get_mount_dev " /system ") $ROOT_MNT_SYSTEM
fi
if [ ! -d $ROOT_PANINI ]; then
mkdir_perm $ROOT_PANINI u:object_r:system_file:s0
fi
if [ -f /data/panini/disabled ] || [ -f /cache/panini.disabled ]; then
exit_unblock
fi
if [ "$MODE" == "stage1" ]; then
mv $LOG_FILE ${LOG_FILE}_last
OS_DIRTY=$(is_os_upgraded)
TREE_DIRTY=$(is_dir_changed)
if [ ! -f /data/panini/not-dirty ] && [ ! -f /cache/panini.not-dirty ] && ([ $OS_DIRTY == "true" ] || [ $TREE_DIRTY == "true" ]); then
rm -rf $ROOT_BIND_SYSTEM
mkdir_perm $ROOT_BIND_SYSTEM u:object_r:system_file:s0
process $ROOT_PANINI $ROOT_PANINI
process /system /system
process_after_bind_tree
fi
elif [ "$MODE" == "stage2" ]; then
bind_mount $ROOT_BIND_SYSTEM /system
export LD_LIBRARY_PATH=$ROOT_MNT_SYSTEM/lib:$ROOT_MNT_SYSTEM/vendor/lib
if [ -d $ROOT_MNT_SYSTEM/lib64 ]; then
export LD_LIBRARY_PATH=$ROOT_MNT_SYSTEM/lib64:$ROOT_MNT_SYSTEM/vendor/lib64
fi
for bind_f in `find $ROOT_BIND_SYSTEM -type f -o -type d`; do
# do not bind 'bin' & 'xbin' since they were copied
if [[ $bind_f == $ROOT_BIND_SYSTEM/bin* ]] || [ $bind_f == $ROOT_BIND_SYSTEM/xbin* ]; then
continue
fi
TARGET=/system${bind_f#$ROOT_BIND_SYSTEM}
PANINI=$ROOT_PANINI${bind_f#$ROOT_BIND_SYSTEM}
ORIGIN=$ROOT_MNT_SYSTEM${bind_f#$ROOT_BIND_SYSTEM}
if [ -d $PANINI ]; then
log_print "Skip binding $TARGET"
elif [ -f $PANINI ]; then
bind_mount $PANINI $TARGET
else
bind_mount $ORIGIN $TARGET
fi
done
fi
exit_unblock
on post-fs
export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin:/bin
rm /cache/panini.post-fs
# stage 1
start make_panini
wait /cache/panini.post-fs 50
rm /cache/panini.post-fs
# stage 2
start enjoy_panini
wait /cache/panini.post-fs 50
rm /cache/panini.post-fs
service make_panini /sbin/panini.sh stage1
user root
seclabel u:r:init:s0
oneshot
service enjoy_panini /sbin/panini.sh stage2
user root
seclabel u:r:init:s0
oneshot
#!/system/bin/sh
SYSTEMLIB=/system/lib
if [ -d /system/lib64 ]; then
SYSTEMLIB=/system/lib64
fi
# extract files
LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-extract $1 init.supersu.rc /sutmp/init.supersu.rc
# patch init.supersu.rc
cat /data/init.supersu.rc.patch >> /sutmp/init.supersu.rc
# push back files
LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-add $1 $1 750 init.supersu.rc /sutmp/init.supersu.rc
LD_LIBRARY_PATH=$SYSTEMLIB /su/bin/sukernel --cpio-add $1 $1 750 sbin/panini.sh /data/panini.sh
exit 0
CONTAINER_DEV=/dev/block/bootdevice/by-name/APD
CONTAINER_MNT=/APD
ROOT_PANINI=$CONTAINER_MNT/panini
#!/system/bin/sh
# hack for ZenFone 2 (x86)
LIB_FILES="
lib/libc++.so
lib/libc.so
lib/libcutils.so
lib/liblog.so
lib/libm.so
lib/libpcre.so
lib/libselinux.so
"
if [ -d $ROOT_PANINI/lib ]; then
for lib_file in $LIB_FILES; do
cp -a $ROOT_MNT_SYSTEM/$lib_file $ROOT_BIND_SYSTEM/$lib_file
done
fi
* reboot to TWRP
* adb push custom_ramdisk_patch.sh /data/
* adb push init.supersu.rc.patch /data/
* adb push panini.sh /data/
* adb shell mkdir /data/panini (optional)
* adb push config /data/panini (optional)
* adb push after_bind_tree.sh /data/panini (optional)
* adb sideload SuperSU.zip
* reboot
* put files under /APD/panini (tree structure is the same with /system)
* set right permissions (755 for directory and executable file, 644 for non-executable file)
* set right selinux context (for ex: u:object_r:dex2oat_exec:s0 for /APD/panini/bin/dex2oat..)
* for disable: touch /cache/panini.disabled
* for not updating bind tree (faster boot): touch /cache/panini.not-dirty