#!/bin/sh
. /etc/os-release
. /lib/functions/uci-defaults.sh
API=$(uci -q get ota.config.api_url)
WRLOCK=/var/lock/ota_background.lock
# armsr/armv8
[ "$OPENWRT_BOARD" = "armsr/armv8" ] && alias board_name="echo armsr,armv8"
# x86_64
[ $(uname -m) = "x86_64" ] && alias board_name="echo x86_64"
action=${1}
shift
sha256() {
sha256sum $1 | cut -d' ' -f1
}
download() {
read_json
if [ -f /tmp/firmware.img ]; then
echo "Checking existed firmware.img..." >> /tmp/firmware.img.progress
if [ "`sha256 /tmp/firmware.img`" = "$FW_SHA256SUM" ]; then
return 0;
else
echo "Check failed, redownload" >> /tmp/firmware.img.progress
rm -f /tmp/firmware.img
fi
fi
touch /tmp/firmware.img.progress
fw_download_tool "$FW_URL" -o /tmp/firmware.img.part -k -L -4 > /tmp/firmware.img.progress 2>&1 &
echo "$! $PPID" > /var/run/ota/download.pid
while true; do
progress=$(grep -c "100.00%" /tmp/firmware.img.progress)
if [ "$progress" -ge "1" ]; then
echo "Checking new firmware.img.part..." > /tmp/firmware.img.progress
break
fi
sleep 1
done
if [ "`sha256 /tmp/firmware.img.part`" = "$FW_SHA256SUM" ]; then
mv /tmp/firmware.img.part /tmp/firmware.img && echo $FW_SHA256SUM > /tmp/firmware.img.sha256sum
rm -f /tmp/firmware.img.progress
return 0
else
echo "Checksum failed!" >>/tmp/firmware.img.progress
sleep 1
rm -rf /tmp/firmware.img.part
return 1
fi
}
lock_download() {
local lock="$WRLOCK"
exec 200>$lock
flock -n 200 || return
download
flock -u 200
}
# 0: found newer fw, 1: already newest fw, *: err
do_check() {
url_check=$(curl -I -o /dev/null -s -w %{http_code} "$API")
[ $url_check -ne 200 ] && exit 255
curl -s "$API" > /var/run/ota/fw.json
read_json
NEW_VERSION=$(basename $FW_URL | awk -F- '{if (NF >= 3 && $3 ~ /^rc/) {print $2 "-" $3} else {print $2}}')
if [ "$BUILD_DATE" -lt "$FW_BUILD_DATE" ]; then
echo "
Model: $(board_name)
Current Version: $PRETTY_NAME
Build Date: $(date "+%Y-%m-%d %H:%M:%S" -d "@$BUILD_DATE")
"
echo "New Version: OpenWrt $NEW_VERSION
Build Date: $(date "+%Y-%m-%d %H:%M:%S" -d "@$FW_BUILD_DATE")
"
return 0
elif [ "$BUILD_DATE" -ge "$FW_BUILD_DATE" ]; then
return 1
else
return 255
fi
}
# async download
do_download(){
[ ! -f "/var/run/ota/fw.json" ] && { echo "do check first" >&2 ; return 254; }
lock_download &
return 0
}
# 0: done, 1: downloading, 2: failed, *: err
do_progress() {
read_json
[ -f /tmp/firmware.img.sha256sum ] && [ "`cat /tmp/firmware.img.sha256sum`" = "$FW_SHA256SUM" ] && return 0
[ -f /tmp/firmware.img.progress ] || { echo "download not in progress" >&2 ; return 254; }
[ -f /tmp/firmware.img.part ] && { cat /tmp/firmware.img.progress | tr '\r' '\n' | tail -n1; return 1; }
tail -1 /tmp/firmware.img.progress | grep -Fq 'Canceled!' && { echo "Canceled"; return 2; }
tail -1 /tmp/firmware.img.progress | grep -Fq 'Checksum failed!' && { echo "Checksum failed!"; return 254; }
grep -v '\r' /tmp/firmware.img.progress >&2
return 1
}
do_cancel() {
if [ -f /var/run/ota/download.pid ]; then
local pid=`cat /var/run/ota/download.pid`
if [ -n "$pid" ]; then
kill -TERM $pid;
while kill -9 $pid >/dev/null 2>&1; do
if ! sleep 1; then
break
fi
done
rm -rf /tmp/firmware.img* /var/lock/ota_background.lock /var/lock/ota_api.lock /var/run/ota/download.pid
echo "" >> /tmp/firmware.img.progress
echo "Canceled!" >> /tmp/firmware.img.progress
fi
fi
return 0
}
read_json(){
FW_BUILD_DATE=$(jsonfilter -i /var/run/ota/fw.json -e "@['$(board_name)'][0]['build_date']")
FW_SHA256SUM=$(jsonfilter -i /var/run/ota/fw.json -e "@['$(board_name)'][0]['sha256sum']")
FW_URL=$(jsonfilter -i /var/run/ota/fw.json -e "@['$(board_name)'][0]['url']")
}
ota_init(){
mkdir -p /var/run/ota >/dev/null 2>&1 || true
}
usage() {
echo "usage: ota sub-command"
echo "where sub-command is one of:"
echo " check Check firmware upgrade"
echo " download Download latest firmware"
echo " progress Download progress"
echo " cancel Cancel download"
}
ota_init || exit 255
case $action in
"check")
do_check
;;
"download")
do_download
;;
"progress")
do_progress
;;
"cancel")
do_cancel
;;
*)
usage
;;
esac