Skip to content

Commit

Permalink
Magisk Module Template
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed Feb 19, 2017
1 parent f8c14b4 commit 6fd89d8
Show file tree
Hide file tree
Showing 11 changed files with 486 additions and 1 deletion.
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Declare files that will always have LF line endings on checkout.
META-INF/** text eol=lf
common/** text eol=lf
module.prop text eol=lf
changelog.txt text eol=lf

# Denote all files that are truly binary and should not be modified.
system/** binary
321 changes: 321 additions & 0 deletions META-INF/com/google/android/update-binary
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
#!/sbin/sh

##########################################################################################
# Functions
##########################################################################################

ui_print() {
if ($BOOTMODE); then
echo "$1"
else
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
fi
}

grep_prop() {
REGEX="s/^$1=//p"
shift
FILES=$@
if [ -z "$FILES" ]; then
FILES='/system/build.prop'
fi
cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1
}

is_mounted() {
if [ ! -z "$2" ]; then
cat /proc/mounts | grep $1 | grep $2, >/dev/null
else
cat /proc/mounts | grep $1 >/dev/null
fi
return $?
}

mount_image() {
if [ ! -d "$2" ]; then
mkdir -p $2 2>/dev/null
chmod 755 $2
[ ! -d "$2" ] && return 1
fi
if (! is_mounted $2); then
LOOPDEVICE=
for LOOP in 0 1 2 3 4 5 6 7; do
if (! is_mounted $2); then
LOOPDEVICE=/dev/block/loop$LOOP
if [ ! -f "$LOOPDEVICE" ]; then
mknod $LOOPDEVICE b 7 $LOOP
fi
losetup $LOOPDEVICE $1
if [ "$?" -eq "0" ]; then
mount -t ext4 -o loop $LOOPDEVICE $2
if (! is_mounted $2); then
/system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE $2
fi
if (! is_mounted $2); then
/system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE $2
fi
fi
if (is_mounted $2); then
ui_print "- Mounting $1 to $2"
break;
fi
fi
done
fi
}

set_perm() {
chown $2:$3 $1 || exit 1
chmod $4 $1 || exit 1
if [ "$5" ]; then
chcon $5 $1 2>/dev/null
else
chcon 'u:object_r:system_file:s0' $1 2>/dev/null
fi
}

set_perm_recursive() {
find $1 -type d 2>/dev/null | while read dir; do
set_perm $dir $2 $3 $4 $6
done
find $1 -type f 2>/dev/null | while read file; do
set_perm $file $2 $3 $5 $6
done
}

mktouch() {
mkdir -p ${1%/*}
if [ -z "$2" ]; then
touch $1
else
echo $2 > $1
fi
chmod 644 $1
}

payload_size_check() {
reqSizeM=0;
for entry in $(unzip -l "$@" 2>/dev/null | tail -n +4 | awk '{ print $1 }'); do
test $entry != "--------" && reqSizeM=$((reqSizeM + entry)) || break;
done;
test $reqSizeM -lt 1048576 && reqSizeM=1 || reqSizeM=$((reqSizeM / 1048576));
}

target_size_check() {
e2fsck -p -f $1
curBlocks=`e2fsck -n $1 2>/dev/null | cut -d, -f3 | cut -d\ -f2`;
curUsedM=$((`echo "$curBlocks" | cut -d/ -f1` * 4 / 1024));
curSizeM=$((`echo "$curBlocks" | cut -d/ -f2` * 4 / 1024));
curFreeM=$((curSizeM - curUsedM));
}

##########################################################################################
# Flashable update-binary preparation
##########################################################################################

OUTFD=$2
ZIP=$3

readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=0

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=$FD
break
fi
fi
done
fi

if [ -z "$BOOTMODE" ]; then
BOOTMODE=false
fi

if ($BOOTMODE) && (! is_mounted /magisk); then
ui_print "! Magisk is not activated!... abort"
exit 1
fi

# Fix SuperSU.....
($BOOTMODE) && /data/magisk/sepolicy-inject -s fsck --live

TMPDIR=/tmp
MOUNTPATH=/magisk
IMGNAME=magisk.img

if ($BOOTMODE); then
TMPDIR=/dev/tmp
MOUNTPATH=/dev/magisk_merge
IMGNAME=magisk_merge.img
fi

mkdir -p $TMPDIR 2>/dev/null
cd $TMPDIR
unzip -o "$ZIP" config.sh

if [ ! -f "config.sh" ]; then
ui_print "! Failed: Unable to extract zip file!"
exit 1
fi

source config.sh

INSTALLER=$TMPDIR/$MODID
MODPATH=$MOUNTPATH/$MODID

mkdir -p $INSTALLER
cd $INSTALLER
unzip -o "$ZIP" "common/*" module.prop

##########################################################################################
# Main
##########################################################################################

# Print mod name
print_modname

# Please leave this message in your flashable zip for credits :)
ui_print "******************************"
ui_print "Powered by Magisk (@topjohnwu)"
ui_print "******************************"

ui_print "- Mounting /system(ro), /vendor(ro), /data, /cache"
mount -o ro /system 2>/dev/null
mount -o ro /vendor 2>/dev/null
mount /data 2>/dev/null
mount /cache 2>/dev/null

if [ ! -f '/system/build.prop' ]; then
ui_print "! Failed: /system could not be mounted!"
exit 1
fi

API=$(grep_prop ro.build.version.sdk)
ABI=$(grep_prop ro.product.cpu.abi | cut -c-3)
ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3)
ABILONG=$(grep_prop ro.product.cpu.abi)

ARCH=arm
IS64BIT=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;

# You can get the Android API version from $API, the CPU architecture from $ARCH
# Useful if you are creating Android version / platform dependent mods

IMG=
if (is_mounted /data); then
IMG=/data/$IMGNAME
if [ ! -f "/data/magisk.img" ]; then
ui_print "! Magisk is not installed!"
ui_print "! Magisk is required for this mod!"
exit 1
fi
else
IMG=/cache/magisk.img
ui_print " "
ui_print "***********************************"
ui_print "* !! Data unavailible !! *"
ui_print "* Magisk detection is impossible *"
ui_print "* Installation will still proceed *"
ui_print "* But please make sure you have *"
ui_print "* Magisk installed!! *"
ui_print "***********************************"
ui_print " "
fi

payload_size_check "$ZIP" "*"

if [ -f "$IMG" ]; then
ui_print "- $IMG detected!"
target_size_check $IMG
if [ "$reqSizeM" -gt "$curFreeM" ]; then
SIZE=$((((reqSizeM + curUsedM) / 32 + 2) * 32))
ui_print "- Resizing $IMG to ${SIZE}M..."
resize2fs $IMG ${SIZE}M
fi
else
SIZE=$(((reqSizeM / 32 + 2) * 32));
ui_print "- Creating $IMG with size ${SIZE}M"
make_ext4fs -l ${SIZE}M -a /magisk -S $INSTALLER/common/file_contexts_image $IMG
fi

mount_image $IMG $MOUNTPATH
if (! is_mounted $MOUNTPATH); then
ui_print "! $IMG mount failed... abort"
exit 1
fi

# Create mod paths
rm -rf $MODPATH 2>/dev/null
mkdir -p $MODPATH

# Copy files
ui_print "- Copying files"
unzip -o "$ZIP" "system/*" -d $MODPATH

# Handle replace folders
for TARGET in $REPLACE; do
mktouch $MODPATH$TARGET/.replace
done

# Auto Mount
if ($AUTOMOUNT); then
mktouch $MODPATH/auto_mount
fi

# prop files
if ($PROPFILE); then
cp -af $INSTALLER/common/system.prop $MODPATH/system.prop
fi

# Module info
cp -af $INSTALLER/module.prop $MODPATH/module.prop
if ($BOOTMODE); then
# Update info for Magisk Manager
mktouch /magisk/$MODID/update
cp -af $INSTALLER/module.prop /magisk/$MODID/module.prop
fi

# post-fs-data mode scripts
if ($POSTFSDATA); then
cp -af $INSTALLER/common/post-fs-data.sh $MODPATH/post-fs-data.sh
fi

# service mode scripts
if ($LATESTARTSERVICE); then
cp -af $INSTALLER/common/service.sh $MODPATH/service.sh
fi

ui_print "- Setting permissions"
set_permissions

ui_print "- Unmounting partitions"

umount $MOUNTPATH
losetup -d $LOOPDEVICE
rmdir $MOUNTPATH

# Shrink the image if possible
target_size_check $IMG
NEWDATASIZE=$(((curUsedM / 32 + 2) * 32))
if [ "$curSizeM" -gt "$NEWDATASIZE" ]; then
ui_print "- Shrinking $IMG to ${NEWDATASIZE}M..."
resize2fs $IMG ${NEWDATASIZE}M
fi

if (! $BOOTMODE); then
umount /system
umount /vendor 2>/dev/null
fi

ui_print "- Done"
exit 0
1 change: 1 addition & 0 deletions META-INF/com/google/android/updater-script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#MAGISK
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# Magisk Module Template
## !! Please update this README.md file for online Repo submission !!
You can edit your `README.md` within Github's online editor, it also has an preview button!
Check the [Markdown Cheat Sheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) for markdown syntaxes, it's super easy!

## How to Create a Magisk Module
1. Clone / download this repo
2. Open `config.sh`, follow the instructions written at the beginning of the file. You should at least change `config.sh` and `module.prop`
3. Zip your files, the zipped file is a flashable zip for both Magisk Manager and custom recoveries
4. Please check **Notes** for precautions

## How to Request a New Repo
1. Fork [this repo](https://github.com/topjohnwu/magisk-module-template)
2. Create your own Magisk Module as stated above
3. Push your changes to Github
4. Change the description of the Github repo to **the id of your module. This is important! Never change it to anything else!**
5. Open an issue in [topjohnwu/Magisk_Repo_Central](https://github.com/topjohnwu/Magisk_Repo_Central/issues/new)
Please include your repo link so I can check and clone it
6. Your repo should be cloned into [Magisk-Modules-Repo](https://github.com/Magisk-Modules-Repo), and you should receive an email to become the collaborator of that repo so you can edit it in the future.

## Notes
1. (Windows aware!!) This git repo is configured to force Unix endlines on all necessary files. The line endings on these files should remain the Unix format. Please use advanced text editors like Sublime, Atom, Notepad++ etc. to edit the text files
2. In `module.prop`, `version` is any string you like, so any fancy version name (e.g. ultra-beta-v0.0.0.1) is allowed. However, `versionCode` **MUST** be an integer. The value is used for version comparison.
2. Make sure your module ID **doesn't contain any spaces**.
3. (For repo developers) Magisk Manager monitors all repo's `master` branch. So any changes to the branch `master` will be reflected to all users immediately. If you are working on an update for a module, please work on another branch, make sure it works, and then merge the changes back to `master`.

## Best Practice for Updating a Repo
1. Open a new branch, and start update your files on the new branch
2. Test if everything works fine
3. Bump up the `versionCode` in `module.prop`, or Magisk Manager won't know that your module is updated!
4. Merge the changes back to master, all users shall now receive the update in Magisk Manager
1 change: 1 addition & 0 deletions common/file_contexts_image
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/magisk(/.*)? u:object_r:system_file:s0
7 changes: 7 additions & 0 deletions common/post-fs-data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/system/bin/sh
# Please don't hardcode /magisk/modname/... ; instead, please use $MODDIR/...
# This will make your scripts compatible even if Magisk change its mount point in the future
MODDIR=${0%/*}

# This script will be executed in post-fs-data mode
# More info in the main Magisk thread
7 changes: 7 additions & 0 deletions common/service.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/system/bin/sh
# Please don't hardcode /magisk/modname/... ; instead, please use $MODDIR/...
# This will make your scripts compatible even if Magisk change its mount point in the future
MODDIR=${0%/*}

# This script will be executed in late_start service mode
# More info in the main Magisk thread
3 changes: 3 additions & 0 deletions common/system.prop
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This file will be read by resetprop
# Example: Change dpi
# ro.sf.lcd_density=320
Loading

0 comments on commit 6fd89d8

Please sign in to comment.