1
0
mirror of https://github.com/EliasKotlyar/Xiaomi-Dafang-Hacks.git synced 2025-09-02 12:43:02 +02:00
Files
xiaomi-dafang-hacks/firmware_mod/autoupdate.sh
Greg Thornton 43d73c3c77 Allow custom firmware repositories (#1651)
* Add repo option to autoupdate.sh

* Fix repo option in autoupdate.sh

* Use local repo when checking for updates

* Use default repo if non given in VERSION file in autoupdates.sh

* Pass custom repo to web ui and update cgi

* Add custom firmware update to web ui

* Fix update messages

* Fix update start arguments

* Fix update input labels

* Add custom upgrade button when on custom firmware
2020-12-22 07:48:59 +01:00

421 lines
13 KiB
Bash
Executable File

#!/bin/sh
##########################################################################
# Github autodownload script
# See usage for help
# Edit the global variables to change the repo and initial folder
# Depends on curl, jq (json parser), openssl (SHA calculation)
# owner name and repo name
REPO="EliasKotlyar/Xiaomi-Dafang-Hacks"
# Branch to use
BRANCH="master"
# Initial remote folder
REMOTEFOLDER="firmware_mod"
# Default destination foler
DESTFOLDER="/system/sdcard/"
DESTOVERRIDE="/tmp/Update"
# The list of exclude, can have multple filter with "*.conf|*.sh"
EXCLUDEFILTER="*.conf|*.user|passwd|shadow"
GITHUBURL="https://api.github.com/repos"
GITHUBURLRAW="https://raw.githubusercontent.com"
CURL="/system/sdcard/bin/curl -k -L"
JQ="/system/sdcard/bin/jq"
SHA="/system/sdcard/bin/openssl dgst -sha256"
BASENAME="/system/sdcard/bin/busybox basename"
FIND="/system/sdcard/bin/busybox find"
VERSION_FILE='/system/sdcard/VERSION'
COMMITS_FILE='/tmp/.lastcommit'
TMPFILE=/tmp/update.tmp
BACKUPEXT=.backup
_PRINTONLY=0
_V=0
_FORCE=0
_FORCEREBOOT=0
_BACKUP=0
_PROGRESS=0
_NBFILES=0
_NBTOTALFILES=0
##########################################################################
usage()
{
echo "Usage: $1 [OPTIONS]"
echo "$1 will update a local folder with the ${REPO} github repo (first copy all the files in ${DESTOVERRIDE}, stop services and reboot"
echo "Usage this script to update the ${REPO} github repo from ${BRANCH} (default) branch"
echo "Options:"
echo "-b (--backup) backup erased file (add extension ${BACKUPEXT} to the local file before ovewrite it) "
echo "-x (--repo) to set the repo"
echo "-r (--branch) to set the branch"
echo "-f (--force) force update"
echo "-d (--dest) set the destination folder (default is ${DESTFOLDER})"
echo "-p (--print) print action only, do nothing"
echo "-s (--steps) add progress in file /tmp/progress"
echo "-v (--verbose) for verbose"
echo "-u (--user) githup login/password (not mandatory, but sometime anonymous account get banned)"
echo "-t (--token) github API token"
echo "-h (--help) for this help"
echo
echo "Note that ${EXCLUDEFILTER} will be excluded"
echo "Examples:"
echo "Update all files if needed >$1 -d /system/sdcard (-f to force update)"
}
##########################################################################
# Function to get user input for yes/no/all
# print the result (yes,no,all)
ask_yes_or_no() {
read R
case $(echo ${R} | tr '[A-Z]' '[a-z]') in
y|yes) echo "yes" ;;
a|all) echo "all" ;;
*) echo "no" ;;
esac
}
##########################################################################
# Log string if verbose is set
log ()
{
if [ ${_V} -eq 1 ]; then
echo "$@"
fi
}
##########################################################################
# Log string on std error
logerror ()
{
echo "$@" 1>&2
}
##########################################################################
# Log string on std error
progress()
{
if [ ${_PROGRESS} -eq 1 ]; then
_NBFILES=$((${_NBFILES} + 1))
echo -n $((${_NBFILES} *100 / ${_NBTOTALFILES} )) > /tmp/progress
# echo "file = ${_NBFILES}, total=${_NBTOTALFILES} = $((${_NBFILES} *100 / ${_NBTOTALFILES} ))"
fi
}
##########################################################################
# If "printonly" action is selected print the action to do (but don't do it
# If not execute it
action()
{
if [ ${_PRINTONLY} -eq 1 ]; then
echo "Action: $@"
else
eval "$@"
fi
return $?
}
##########################################################################
# Check if $1 macth with the excluded filter
ismatch()
{
in=$(${BASENAME} ${1})
for filter in $(echo ${EXCLUDEFILTER} | sed "s/|/ /g")
do
if [ "${in#$filter}" == "" ]; then
echo match
return 0
fi
done
echo notmatch
}
##########################################################################
# Print the files from repo of the folder $1
# Recursive call (for folder)
getfiles()
{
if echo "${1}" | grep -q "API rate limit exceeded"; then
logerror "Github limit exceeded, try with an account (-u option)"
exit 1
else
for row in $(echo "${1}" | ${JQ} '.[]| select(.type=="file") | .download_url' ); do
filetoget=$(echo "${row}" | tr -d '"')
echo ${filetoget}
done
for row in $(echo "${1}" | ${JQ} '.[]| select(.type == "dir") | .path' ); do
flder=$(echo "${row}" | tr -d '"')
next=$(curl -s https://api.github.com/repos/${REPO}/contents/${flder}?ref=${BRANCH})
getfiles "${next}"
done
fi
}
##########################################################################
# Let some time before rebooting
countdownreboot()
{
i=10
while [ ${i} -gt 0 ];
do
echo "$i seconds remaining before reboot (Press control-c to abort)";
i=$((${i} - 1))
sleep 1;
done
action reboot
}
##########################################################################
# Generate VERSION file
generateVersionFile ()
{
echo "{\"date\":\"${REMOTECOMMITDATE}\",\"repo\":\"${REPO}\",\"branch\":\"${BRANCH}\",\"commit\":\"${REMOTECOMMITID}\"}" > $VERSION_FILE
}
##########################################################################
# Curl with optional authentication
curl ()
{
if [ -n "$_TOKEN" ]; then
$CURL -H "Authorization: token $_TOKEN" "$@"
elif [ -n "$_USER" ]; then
$CURL -u "$_USER" "$@"
else
$CURL "$@"
fi
}
##########################################################################
# Script real start
while [ $# -gt 0 ]
do
arg="$1"
case ${arg} in
"")
;;
-v | --verbose)
_V=1
shift
;;
-f | --force)
_FORCE=1
_FORCEREBOOT=1
shift
;;
-d | --dest)
DESTFOLDER="$2/"
shift
shift
;;
-b | --backup)
_BACKUP=1;
shift
;;
-p | --print)
_PRINTONLY=1
shift
;;
-u | --user)
_USER="$2"
shift
shift
;;
-t | --token)
_TOKEN="$2"
shift
shift
;;
-s | --steps)
_PROGRESS=1;
shift
;;
-x | --repo)
REPO=$2;
shift
shift
;;
-r | --branch)
BRANCH=$2
shift
shift
;;
*|-h |\? | --help)
usage $0
exit 1
;;
esac
done
log "Starting AutoUpdate on branch ${BRANCH}"
######################################################""
# Get date and last commit ID from Github
curl -s ${GITHUBURL}/${REPO}/commits/${BRANCH} --output $COMMITS_FILE
REMOTECOMMITDATE=$(${JQ} -r '.commit .author .date' ${COMMITS_FILE})
REMOTECOMMITID=$(${JQ} -r '.sha[0:7]' ${COMMITS_FILE} )
if [ ${_FORCE} = 1 ]; then
log "Forcing update."
fi
if [ ${_PRINTONLY} = 1 ]; then
log "Print actions only, do nothing."
fi
if [ ${_BACKUP} = 1 ]; then
log "Backing up files."
fi
action "rm -rf ${DESTOVERRIDE} 2>/dev/null"
if [ -f "$VERSION_FILE" ]; then
LOCALCOMMITID=$(${JQ} -r .commit ${VERSION_FILE})
LOCALREPO=$(${JQ} -r .repo ${VERSION_FILE})
if [ -z "$LOCALREPO" ]; then LOCALREPO="$REPO"; fi
if [ ${LOCALREPO} = ${REPO} ] && [ ${LOCALCOMMITID} = ${REMOTECOMMITID} ]; then
logerror "You are currently on the latest version"
echo "You are currently on the latest version"
exit 1
elif [ ${LOCALREPO} = ${REPO} ]; then
echo "Need to upgrade from ${LOCALCOMMITID} to ${REMOTECOMMITID}"
log "Getting list of remote files."
FILES=$(curl -s ${GITHUBURL}/${REPO}/compare/${LOCALCOMMITID}...${REMOTECOMMITID} | ${JQ} -r '.files[].raw_url' | grep ${REMOTEFOLDER})
else
echo "Repo has changed. Upgrade to last commit ${REMOTECOMMITID}"
log "Getting list of remote files."
FIRST=$(curl -s ${GITHUBURL}/${REPO}/contents/${REMOTEFOLDER}?ref=${BRANCH})
FILES=$(getfiles "${FIRST}")
fi
else
echo "Version file missing. Upgrade to last commit ${REMOTECOMMITID}"
log "Getting list of remote files."
FIRST=$(curl -s ${GITHUBURL}/${REPO}/contents/${REMOTEFOLDER}?ref=${BRANCH})
FILES=$(getfiles "${FIRST}")
fi
if [ $_PROGRESS = 1 ]; then
_NBTOTALFILES=$(echo $FILES | wc -w)
log Number of file to update $_NBTOTALFILES
echo -n 0 > /tmp/progress
fi
# For all the repository files
for i in ${FILES}
do
progress
# String to remove to get the local path
LOCALFILE=$(echo ${i} | awk -F ${REMOTEFOLDER}/ '{print $2}')
# Remove files that match the filter
res=$(ismatch ${LOCALFILE})
if [ "$res" == "match" ]; then
echo "${LOCALFILE} is excluded due to filter."
continue
fi
# Get the file temporally to calculate SHA
curl -s ${i} -o ${TMPFILE} 2>/dev/null
if [ ! -f ${TMPFILE} ]; then
echo "Can not get remote file $i, exiting."
exit 1
fi
# sometimes zero byte files are received, which overwrite the local files, we ignore those files
# exception: files that are hidden i.e. start with dot. Ex: files like ".gitkeep"
if [[ ! -s ${TMPFILE} ]] && [[ $(basename ${LOCALFILE} | cut -c1-1) != "." ]]; then
echo "Received zero byte file $i, exiting."
exit 1
fi
# Check the file exists in local
if [ -f "${DESTFOLDER}/${LOCALFILE}" ]; then
REMOTESHA=$(${SHA} ${TMPFILE} 2>/dev/null | cut -d "=" -f 2)
# Calculate the remote and local SHA
LOCALSHA=$(${SHA} ${DESTFOLDER}${LOCALFILE} 2>/dev/null | cut -d "=" -f 2)
# log "SHA of $LOCALFILE is ${LOCALSHA} ** remote is ${REMOTESHA}"
if [ "${REMOTESHA}" = "${LOCALSHA}" ] ; then
echo "${LOCALFILE} is up to date."
else
if [ ${_FORCE} = 1 ]; then
echo "${LOCALFILE} updated."
action "mkdir -p $(dirname ${DESTOVERRIDE}/${LOCALFILE}) 2>/dev/null"
if [ ${_BACKUP} = 1 ]; then
action cp ${DESTFOLDER}${LOCALFILE} ${DESTOVERRIDE}/${LOCALFILE}${BACKUPEXT}
fi
action mv ${TMPFILE} ${DESTOVERRIDE}/${LOCALFILE}
else
echo "${LOCALFILE} needs to be updated. Overwrite?"
echo "[Y]es or [N]o or [A]ll?"
rep=$(ask_yes_or_no )
if [ "${rep}" = "no" ]; then
echo "${LOCALFILE} not updated"
rm -f ${TMPFILE} 2>/dev/null
else
action "mkdir -p $(dirname ${DESTOVERRIDE}/${LOCALFILE}) 2>/dev/null"
if [ ${_BACKUP} = 1 ]; then
action cp ${DESTFOLDER}${LOCALFILE} ${DESTOVERRIDE}/${LOCALFILE}${BACKUPEXT}
fi
action mv ${TMPFILE} ${DESTOVERRIDE}/${LOCALFILE}
fi
if [ "${rep}" = "all" ]; then
_FORCE=1
fi
fi
fi
else
if [ ${_FORCE} = 1 ]; then
echo "${LOCALFILE} created."
action "mkdir -p $(dirname ${DESTOVERRIDE}/${LOCALFILE}) 2>/dev/null"
action mv ${TMPFILE} ${DESTOVERRIDE}/${LOCALFILE}
else
echo "${LOCALFILE} doesn't exist, create it?"
echo "[Y]es or [N]o or [A]ll ?"
rep=$(ask_yes_or_no )
if [ "${rep}" = "no" ]; then
echo "${LOCALFILE} not created."
rm -f ${TMPFILE} 2>/dev/null
else
action "mkdir -p $(dirname ${DESTOVERRIDE}/${LOCALFILE}) 2>/dev/null"
action mv ${TMPFILE} ${DESTOVERRIDE}/${LOCALFILE}
fi
if [ "${rep}" = "all" ]; then
_FORCE=1
fi
fi
fi
done
if [ $_PROGRESS = 1 ]; then
echo -n 100 > /tmp/progress
fi
if [ -d ${DESTOVERRIDE} ] && [ $(ls -l ${DESTOVERRIDE}/* | wc -l 2>/dev/null) > 1 ]; then
echo "--------------- Stopping services ---------"
for i in /system/sdcard/controlscripts/*; do
echo stopping $i
$i stop &> /dev/null
done
pkill lighttpd.bin 2> /dev/null
pkill bftpd 2> /dev/null
echo "--------------- Updating files ----------"
action "cp -Rf ${DESTOVERRIDE}/* ${DESTFOLDER} 2>/dev/null"
action "rm -Rf ${DESTOVERRIDE}/* 2>/dev/null"
# Everythings was OK, save the date
generateVersionFile
echo "--------------- Reboot ------------"
if [ ${_FORCEREBOOT} = 1 ]; then
countdownreboot
else
echo "A reboot is needed, do you want to reboot now?"
echo "[Y]es or [N]o"
rep=$(ask_yes_or_no )
if [ "${rep}" = "yes" ]; then
countdownreboot
fi
fi
else
generateVersionFile
echo "No files to update."
fi