1
mirror of https://github.com/topjohnwu/Magisk synced 2024-11-13 20:54:12 +01:00

Magic Mount Total Re-factor Part 2

1. It seems that many part of the system is upset about symlinks, revert to bind mounts
2. New system and vendor mirror implementation found, no need to copy anything
3. Thanks to the new mirror implementation, adding new items to /system and /vendor is now possible
4. Re-written some coding style
This commit is contained in:
topjohnwu 2016-12-08 00:50:52 -08:00
parent c07e9ac29d
commit 1e3586621b
2 changed files with 138 additions and 237 deletions

2
.gitignore vendored
View File

@ -11,7 +11,7 @@ uninstaller/arm/*
uninstaller/arm64/*
uninstaller/x86/*
uninstaller/x64/*
zipsigntools/zipadjust
ziptools/zipadjust
# Generated scripts
zip_static/common/magic_mask.sh

View File

@ -47,8 +47,8 @@ unblock() {
run_scripts() {
BASE=$MOUNTPOINT
for MOD in $BASE/* ; do
if [ ! -f "$MOD/disable" ]; then
if [ -f "$MOD/$1.sh" ]; then
if [ ! -f $MOD/disable ]; then
if [ -f $MOD/$1.sh ]; then
chmod 755 $MOD/$1.sh
chcon "u:object_r:system_file:s0" "$MOD/$1.sh"
log_print "$1: $MOD/$1.sh"
@ -60,8 +60,8 @@ run_scripts() {
loopsetup() {
LOOPDEVICE=
for DEV in $(ls /dev/block/loop*); do
if [ `losetup $DEV $1 >/dev/null 2>&1; echo $?` -eq 0 ]; then
for DEV in `ls /dev/block/loop*`; do
if losetup $DEV $1; then
LOOPDEVICE=$DEV
break
fi
@ -77,44 +77,39 @@ target_size_check() {
}
travel() {
cd "$TRAVEL_ROOT/$1"
if [ -f ".replace" ]; then
rm -rf "$MOUNTINFO/$1"
mktouch "$MOUNTINFO/$1" "$TRAVEL_ROOT"
cd $TRAVEL_ROOT/$1
if [ -f .replace ]; then
rm -rf $MOUNTINFO/$1
mktouch $MOUNTINFO/$1 $TRAVEL_ROOT
else
for ITEM in * ; do
if [ ! -e "/$1/$ITEM" ]; then
if [ ! -e /$1/$ITEM ]; then
# New item found
if [ "$1" = "system" ]; then
# We cannot add new items to /system root, delete it
rm -rf "$ITEM"
else
# If we are in a higher level, delete the lower levels
rm -rf "$MOUNTINFO/dummy/$1"
# Mount the dummy parent
mktouch "$MOUNTINFO/dummy/$1"
# If we are in a higher level, delete the lower levels
rm -rf $MOUNTINFO/dummy/$1
# Mount the dummy parent
mktouch $MOUNTINFO/dummy/$1
if [ -d "$ITEM" ]; then
# Create new dummy directory and mount it
mkdir -p "$DUMMDIR/$1/$ITEM"
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
elif [ -L "$ITEM" ]; then
# Symlinks are small, copy them
mkdir -p "$DUMMDIR/$1" 2>/dev/null
cp -afc "$ITEM" "$DUMMDIR/$1/$ITEM"
else
# Create new dummy file and mount it
mktouch "$DUMMDIR/$1/$ITEM"
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
fi
if [ -d $ITEM ]; then
# Create new dummy directory and mount it
mkdir -p $DUMMDIR/$1/$ITEM
mktouch $MOUNTINFO/$1/$ITEM $TRAVEL_ROOT
elif [ -L $ITEM ]; then
# Symlinks are small, copy them
mkdir -p $DUMMDIR/$1 2>/dev/null
cp -afc $ITEM $DUMMDIR/$1/$ITEM
else
# Create new dummy file and mount it
mktouch $DUMMDIR/$1/$ITEM
mktouch $MOUNTINFO/$1/$ITEM $TRAVEL_ROOT
fi
else
if [ -d "$ITEM" ]; then
if [ -d $ITEM ]; then
# It's an directory, travel deeper
(travel "$1/$ITEM")
elif [ ! -L "$ITEM" ]; then
(travel $1/$ITEM)
elif [ ! -L $ITEM ]; then
# Mount this file
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
mktouch $MOUNTINFO/$1/$ITEM $TRAVEL_ROOT
fi
fi
done
@ -122,55 +117,33 @@ travel() {
}
clone_dummy() {
for ITEM in $1/* ; do
if [ ! -e "$TRAVEL_ROOT$ITEM" ]; then
if [ ! -d "$MOUNTINFO$ITEM" ]; then
if [ -L "$ITEM" ]; then
# Copy original symlink
cp -afc "$ITEM" "$TRAVEL_ROOT$ITEM"
else
# Link to mirror item
ln -s "$MIRRDIR$ITEM" "$TRAVEL_ROOT$ITEM"
fi
for ITEM in $MIRRDIR$1/* ; do
REAL=${ITEM#$MIRRDIR}
if [ ! -e $MOUNTINFO$REAL ]; then
if [ -L $ITEM ]; then
# Copy original symlink
cp -afc $ITEM $DUMMDIR$REAL
else
# Need to clone a skeleton
(clone_dummy "$ITEM")
if [ -d $ITEM ]; then
mkdir -p $DUMMDIR$REAL
else
mktouch $DUMMDIR$REAL
fi
# Mount the mirror
mktouch $MOUNTINFO/mirror$REAL
fi
elif [ -d "$TRAVEL_ROOT$ITEM" ]; then
# Need to clone a skeleton
(clone_dummy "$ITEM")
elif [ -d $MOUNTINFO$REAL ]; then
# Need to clone deeper
mkdir -p $DUMMDIR$REAL
(clone_dummy $REAL)
fi
done
}
make_copy_image() {
TARGETSIZE=$2
if [ -z $TARGETSIZE ]; then
TARGETSIZE=`du -s $1 | awk '{print $1}'`
TARGETSIZE=$((($TARGETSIZE / 10240 + 2) * 10240))
fi
TARGETIMG=/data/magisk/${1//\//_}.img
make_ext4fs -l ${TARGETSIZE}K -a $1 $TARGETIMG
loopsetup $TARGETIMG
mkdir -p $MIRRDIR/copy$1
mount -t ext4 -o rw,noatime $LOOPDEVICE $MIRRDIR/copy$1
return $?
}
mount_copy_image() {
TARGETIMG=/data/magisk/${1//\//_}.img
umount $MIRRDIR/copy$1
rm -rf $MIRRDIR/copy
losetup -d $LOOPDEVICE 2>/dev/null
loopsetup $TARGETIMG
mount -t ext4 -o rw,noatime $LOOPDEVICE $1
return $?
}
bind_mount() {
if [ -e "$1" -a -e "$2" ]; then
if [ -e $1 -a -e $2 ]; then
mount -o bind $1 $2
if [ "$?" -eq "0" ]; then
if [ $? -eq 0 ]; then
log_print "Mount: $1"
else
log_print "Mount Fail: $1"
@ -179,9 +152,9 @@ bind_mount() {
}
merge_image() {
if [ -f "$1" ]; then
if [ -f $1 ]; then
log_print "$1 found"
if [ -f "$IMG" ]; then
if [ -f $IMG ]; then
log_print "$IMG found, attempt to merge"
# Handle large images
@ -207,36 +180,29 @@ merge_image() {
LOOPMERGE=$LOOPDEVICE
log_print "$LOOPMERGE $1"
if [ ! -z "$LOOPDATA" ]; then
if [ ! -z "$LOOPMERGE" ]; then
# if loop devices have been setup, mount images
OK=true
if [ ! -z $LOOPDATA -a ! -z $LOOPMERGE ]; then
# if loop devices have been setup, mount images
OK=false
mount -t ext4 -o rw,noatime $LOOPDATA /cache/data_img && \
mount -t ext4 -o rw,noatime $LOOPMERGE /cache/merge_img && \
OK=true
if [ `mount -t ext4 -o rw,noatime $LOOPDATA /cache/data_img >/dev/null 2>&1; echo $?` -ne 0 ]; then
OK=false
fi
if [ `mount -t ext4 -o rw,noatime $LOOPMERGE /cache/merge_img >/dev/null 2>&1; echo $?` -ne 0 ]; then
OK=false
fi
if $OK; then
# Merge (will reserve selinux contexts)
cd /cache/merge_img
for MOD in *; do
if [ "$MOD" != "lost+found" ]; then
log_print "Merging: $MOD"
rm -rf /cache/data_img/$MOD
fi
done
cp -afc . /cache/data_img
log_print "Merge complete"
cd /
fi
umount /cache/data_img
umount /cache/merge_img
if $OK; then
# Merge (will reserve selinux contexts)
cd /cache/merge_img
for MOD in *; do
if [ "$MOD" != "lost+found" ]; then
log_print "Merging: $MOD"
rm -rf /cache/data_img/$MOD
fi
done
cp -afc . /cache/data_img
log_print "Merge complete"
cd /
fi
umount /cache/data_img
umount /cache/merge_img
fi
losetup -d $LOOPDATA
@ -263,16 +229,16 @@ case $1 in
log_print "** Magisk post-fs mode running..."
# Cleanup previous version stuffs...
# Cleanup legacy stuffs...
rm -rf /cache/magisk /cache/magisk_merge /cache/magiskhide.log
if [ -d "/cache/magisk_mount" ]; then
if [ -d /cache/magisk_mount ]; then
log_print "* Mounting cache files"
find /cache/magisk_mount -type f 2>/dev/null | while read ITEM ; do
chmod 644 "$ITEM"
chcon "u:object_r:system_file:s0" "$ITEM"
TARGET="${ITEM#/cache/magisk_mount}"
bind_mount "$ITEM" "$TARGET"
chmod 644 $ITEM
chcon "u:object_r:system_file:s0" $ITEM
TARGET=${ITEM#/cache/magisk_mount}
bind_mount $ITEM $TARGET
done
fi
@ -280,15 +246,9 @@ case $1 in
;;
post-fs-data )
if [ `mount | grep " /data " >/dev/null 2>&1; echo $?` -ne 0 ]; then
# /data not mounted yet, we will be called again later
unblock
fi
if [ `mount | grep " /data " | grep "tmpfs" >/dev/null 2>&1; echo $?` -eq 0 ]; then
# /data not mounted yet, we will be called again later
unblock
fi
# /data not mounted yet
! mount | grep " /data " && unblock
mount | grep " /data " | grep "tmpfs" && unblock
# Don't run twice
if [ "`getprop magisk.restart_pfsd`" != "1" ]; then
@ -326,32 +286,29 @@ case $1 in
# Mount magisk.img
[ ! -d $MOUNTPOINT ] && mkdir -p $MOUNTPOINT
if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then
if ! mount | grep $MOUNTPOINT; then
loopsetup $IMG
if [ ! -z "$LOOPDEVICE" ]; then
mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
[ ! -z $LOOPDEVICE ] && mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
if [ $? -ne 0 ]; then
log_print "magisk.img mount failed, nothing to do :("
unblock
fi
fi
if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then
log_print "magisk.img mount failed, nothing to do :("
unblock
fi
# Remove empty directories, legacy paths, symlinks, old temporary images
find $MOUNTPOINT -type d -depth ! -path "*core*" -exec rmdir {} \; 2>/dev/null
rm -rf $COREDIR/bin $COREDIR/dummy $COREDIR/mirror /data/magisk/*.img
# Remove modules that is labeled to be removed
for MOD in $MOUNTPOINT/* ; do
if [ -f "$MOD/remove" ] || [ "$MOD" = "zzsupersu" ]; then
if [ -f $MOD/remove ] || [ $MOD = zzsupersu ]; then
log_print "Remove module: $MOD"
rm -rf $MOD
fi
done
# Unmount, shrink, remount
if [ `umount $MOUNTPOINT >/dev/null 2>&1; echo $?` -eq 0 ]; then
if umount $MOUNTPOINT; then
losetup -d $LOOPDEVICE
target_size_check $IMG
NEWDATASIZE=$(((curUsedM / 32 + 2) * 32))
@ -360,10 +317,8 @@ case $1 in
resize2fs $IMG ${NEWDATASIZE}M
fi
loopsetup $IMG
if [ ! -z "$LOOPDEVICE" ]; then
mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
fi
if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then
[ ! -z $LOOPDEVICE ] && mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
if [ $? -ne 0 ]; then
log_print "magisk.img mount failed, nothing to do :("
unblock
fi
@ -376,7 +331,7 @@ case $1 in
# Travel through all mods
for MOD in $MOUNTPOINT/* ; do
if [ -f "$MOD/auto_mount" -a -d "$MOD/system" -a ! -f "$MOD/disable" ]; then
if [ -f $MOD/auto_mount -a -d $MOD/system -a ! -f $MOD/disable ]; then
TRAVEL_ROOT=$MOD
(travel system)
fi
@ -386,130 +341,80 @@ case $1 in
find $TMPDIR -exec chcon -h "u:object_r:system_file:s0" {} \;
# linker(64), t*box required for bin
if [ -f "$MOUNTINFO/dummy/system/bin" ]; then
if [ -f $MOUNTINFO/dummy/system/bin ]; then
cp -afc /system/bin/linker* /system/bin/t*box $DUMMDIR/system/bin/
fi
BACKUPLIBS=false
DISABLEHIDE=false
# Libraries are full of issues, copy a full clone to data
# lib
if [ -f "$MOUNTINFO/dummy/system/lib" ]; then
BACKUPLIBS=true
make_copy_image /system/lib
cp -afc /system/lib/. $MIRRDIR/copy/system/lib
cp -afc $DUMMDIR/system/lib/. $MIRRDIR/copy/system/lib
mount_copy_image /system/lib
rm -f $MOUNTINFO/dummy/system/lib
fi
# lib64
if [ -f "$MOUNTINFO/dummy/system/lib64" ]; then
BACKUPLIBS=true
make_copy_image /system/lib64
cp -afc /system/lib64/. $MIRRDIR/copy/system/lib64
cp -afc $DUMMDIR/system/lib64/. $MIRRDIR/copy/system/lib64
mount_copy_image /system/lib64
rm -f $MOUNTINFO/dummy/system/lib64
fi
# Whole vendor
if [ -f "$MOUNTINFO/dummy/system/vendor" ]; then
BACKUPLIBS=true
LIBSIZE=`du -s /vendor/lib | awk '{print $1}'`
if [ -d /vendor/lib64 ]; then
LIB64SIZE=`du -s /vendor/lib64 | awk '{print $1}'`
VENDORLIBSIZE=$(((($LIBSIZE + $LIB64SIZE) / 10240 + 2) * 10240))
else
VENDORLIBSIZE=$((($LIBSIZE / 10240 + 2) * 10240))
fi
make_copy_image /vendor $VENDORLIBSIZE
# Copy lib/lib64
mkdir -p $MIRRDIR/copy/vendor/lib
cp -afc /vendor/lib/. $MIRRDIR/copy/vendor/lib
cp -afc $DUMMDIR/system/vendor/lib/. $MIRRDIR/copy/vendor/lib 2>/dev/null
if [ -d /vendor/lib64 ]; then
mkdir -p $MIRRDIR/copy/vendor/lib64
cp -afc /vendor/lib64/. $MIRRDIR/copy/vendor/lib64
cp -afc $DUMMDIR/system/vendor/lib64/. $MIRRDIR/copy/vendor/lib64 2>/dev/null
fi
cp -afc $DUMMDIR/system/vendor/. $MIRRDIR/copy/vendor
TRAVEL_ROOT=$MIRRDIR/copy
(clone_dummy /vendor)
# Create vendor mirror
if [ `mount | grep -c "on /vendor type"` -ne 0 ]; then
VENDORBLOCK=`mount | grep "on /vendor type" | awk '{print $1}'`
mkdir -p $MIRRDIR/vendor
mount -o ro $VENDORBLOCK $MIRRDIR/vendor
else
ln -s $MIRRDIR/system/vendor $MIRRDIR/vendor
fi
mount_copy_image /vendor
rm -f $MOUNTINFO/dummy/system/vendor
fi
# vendor lib
if [ -f "$MOUNTINFO/dummy/system/vendor/lib" ]; then
BACKUPLIBS=true
make_copy_image /system/vendor/lib
cp -afc /system/vendor/lib/. $MIRRDIR/copy/system/vendor/lib
cp -afc $DUMMDIR/system/vendor/lib/. $MIRRDIR/copy/system/vendor/lib
mount_copy_image /system/vendor/lib
rm -f $MOUNTINFO/dummy/system/vendor/lib
fi
# vendor lib64
if [ -f "$MOUNTINFO/dummy/system/vendor/lib64" ]; then
BACKUPLIBS=true
make_copy_image /system/vendor/lib64
cp -afc /system/vendor/lib64/. $MIRRDIR/copy/system/vendor/lib64
cp -afc $DUMMDIR/system/vendor/lib64/. $MIRRDIR/copy/system/vendor/lib64
mount_copy_image /system/vendor/lib64
rm -f $MOUNTINFO/dummy/system/vendor/lib64
fi
for i in /system /system/lib /system/lib64 /system/vendor /system/vendor/lib /system/vendor/lib64; do
[ -f $MOUNTINFO/dummy$1 ] && DISABLEHIDE=true && break
done
# Crash prevention!!
$BACKUPLIBS && rm -f $COREDIR/magiskhide/enable 2>/dev/null
$DISABLEHIDE && rm -f $COREDIR/magiskhide/enable 2>/dev/null
# Remove crap folder
rm -rf $MOUNTPOINT/lost+found
# Start doing tasks
# Stage 1
TRAVEL_ROOT=$DUMMDIR
log_print "* Bind mount dummy system"
find $MOUNTINFO/dummy -type f 2>/dev/null | while read ITEM ; do
TARGET=${ITEM#$MOUNTINFO/dummy}
ORIG="$DUMMDIR$TARGET"
(clone_dummy "$TARGET")
bind_mount "$ORIG" "$TARGET"
done
log_print "* Stage 1: Mount system and vendor mirrors"
SYSTEMBLOCK=`mount | grep " /system " | awk '{print $1}'`
mkdir -p $MIRRDIR/system
mount -o ro $SYSTEMBLOCK $MIRRDIR/system
if [ `mount | grep -c " /vendor "` -ne 0 ]; then
VENDORBLOCK=`mount | grep " /vendor " | awk '{print $1}'`
mkdir -p $MIRRDIR/vendor
mount -o ro $VENDORBLOCK $MIRRDIR/vendor
else
ln -s $MIRRDIR/system/vendor $MIRRDIR/vendor
fi
# Since mirrors always exist, we load libraries from mirrors
LD_LIBRARY_PATH=$MIRRDIR/system/lib:$MIRRDIR/vendor/lib
[ -d /system/lib64 ] LD_LIBRARY_PATH=$MIRRDIR/system/lib64:$MIRRDIR/vendor/lib64
# Stage 2
log_print "* Bind mount module items"
log_print "* Stage 2: Mount dummy skeletons"
# Move dummy /system/vendor to /vendor for consistency
mv -f $MOUNTINFO/dummy/system/vendor $MOUNTINFO/dummy/vendor 2>/dev/null
mv -f $DUMMDIR/system/vendor $DUMMDIR/vendor 2>/dev/null
find $MOUNTINFO/dummy -type f 2>/dev/null | while read ITEM ; do
TARGET=${ITEM#$MOUNTINFO/dummy}
ORIG=$DUMMDIR$TARGET
(clone_dummy $TARGET)
bind_mount $ORIG $TARGET
done
# Stage 3
log_print "* Stage 3: Mount module items"
find $MOUNTINFO/system -type f 2>/dev/null | while read ITEM ; do
TARGET=${ITEM#$MOUNTINFO}
ORIG=`cat $ITEM`$TARGET
bind_mount $ORIG $TARGET
rm -f $DUMMDIR${TARGET%/*}/.dummy 2>/dev/null
done
# Run scripts
# Stage 4
log_print "* Stage 4: Execute module scripts"
run_scripts post-fs-data
# Stage 5
log_print "* Stage 5: Mount mirrored items back to dummy"
find $MOUNTINFO/mirror -type f 2>/dev/null | while read ITEM ; do
TARGET=${ITEM#$MOUNTINFO/mirror}
ORIG=$MIRRDIR$TARGET
bind_mount $ORIG $TARGET
done
# Bind hosts for Adblock apps
if [ -f "$COREDIR/hosts" ]; then
if [ -f $COREDIR/hosts ]; then
log_print "* Enabling systemless hosts file support"
bind_mount $COREDIR/hosts /system/etc/hosts
fi
# Expose busybox
if [ -f "$COREDIR/busybox/enable" ]; then
if [ -f $COREDIR/busybox/enable ]; then
log_print "* Enabling BusyBox"
cp -afc /data/busybox/. $COREDIR/busybox
cp -afc /system/xbin/. $COREDIR/busybox
@ -518,10 +423,6 @@ case $1 in
bind_mount $COREDIR/busybox /system/xbin
fi
# Stage 3
log_print "* Bind mount system mirror"
bind_mount /system $MIRRDIR/system
# Restart post-fs-data if necessary (multirom)
$MULTIROM && setprop magisk.restart_pfsd 1
@ -536,7 +437,7 @@ case $1 in
run_scripts service
# Magisk Hide
if [ -f "$COREDIR/magiskhide/enable" ]; then
if [ -f $COREDIR/magiskhide/enable ]; then
log_print "* Removing tampered read-only system props"
VERIFYBOOT=`getprop ro.boot.verifiedbootstate`