#!/bin/sh # # Copyright (c) 2017-2018 Aaron LI # MIT License # # Tool to update a DragonFly BSD system using binary releases or # snapshot builds. # set -e NAME="dfly-update" VERSION="0.?.?" TOOLDIR="${0%/*}" PREFIX="${PREFIX:-${TOOLDIR}}" CONFIGFILE="${PREFIX}/${NAME}.conf" # # Error Codes # EC_OS=5 EC_CONFIGFILE=10 EC_CONFIG=11 # # Default Configurations # # Base URL to Remote DragonFly BSD images URL_BASE="https://mirror-master.dragonflybsd.org" URL_DEVELOPMENT="${URL_BASE}/snapshots/x86_64/images" URL_RELEASE="${URL_BASE}/iso-images" # Default to track the same branch as the installed system UPDATE_BRANCH= # # Helper Functions # error() { echo "ERROR: $@" >&2 } check_os() { local os=$(uname -s) if [ "${os}" != "DragonFly" ]; then error "Not a DragonFly BSD system!" exit ${EC_OS} fi } # Load configurations from file load_config() { local configfile="$1" local tmpcfg=$(mktemp -t ${NAME}) || exit ${EC_TMPFILE} if [ ! -r "${configfile}" ]; then error "Cannot read configuration file: ${configfile}" exit ${EC_CONFIGFILE} fi # Filter out only valid configurations to be secure egrep '^[^ ]*=[^;&]*' ${configfile} > ${tmpcfg} . ${tmpcfg} rm -f ${tmpcfg} } # Get the branch of the installed system # * DEVELOPMENT # * RELEASE get_local_branch() { check_os || exit $? uname -r | awk -F'-' '{ print $2 }' } # Get the version of local installed system get_local_version() { check_os local version=$(uname -v | awk '{ print $2 }') echo "${version}" | awk -F'-' '{ print $1 }' | tr -d 'v' } # Get the latest remote system image # Returns: # "_filename=; _md5=" get_latest_image() { local latest_filename latest_md5 line if [ "${branch}" = "DEVELOPMENT" ]; then url_checksum="${URL_DEVELOPMENT}/CHECKSUM.MD5" else url_checksum="${URL_RELEASE}/md5.txt" fi local branch="$1" local url_checksum=$(get_md5list_url ${branch}) local tmpchecksum=$(mktemp -t ${NAME}) || \ exit ${EC_TMPFILE} echo "Fetch remote systems checksum: ${url_checksum}" >&2 fetch -o ${tmpchecksum} "${url_checksum}" if [ "${branch}" = "DEVELOPMENT" ]; then line=$(fgrep '.img.bz2' ${tmpchecksum} | tail -n 1) else line=$(fgrep '.img.bz2' ${tmpchecksum} | \ fgrep -v 'gui-' | tail -n 1) fi latest_filename=$(echo "${line}" | awk -F'[()]' '{ print $2 }') latest_md5=$(echo "${line}" | awk '{ print $5 }') rm -f ${tmpchecksum} echo "_filename='${latest_filename}'; _md5='${latest_md5}'" } # Extract the version from image filename get_version_filename() { if [ "${branch}" = "DEVELOPMENT" ]; then local branch="$1" local filename="$2" local version version=$(echo "${filename}" | cut -d'-' -f5 | cut -d'.' -f1-5) else version=$(echo "${filename}" | cut -d'-' -f3 | cut -d'_' -f1) version=${version#v} fi echo ${version} } # Compare between two version strings # Parameters: ver1 ver2 # Returns values: # * 0 : ver1 = ver2 # * 1 : ver1 < ver2 # * 2 : ver1 > ver2 compare_version() { local ver1="$1" local ver2="$2" local ver_low=$(echo -e "${ver1}\n${ver2}" | sort -V | head -n 1) if [ "${ver1}" = "${ver2}" ]; then echo 0 elif [ "${ver1}" = "${ver_low}" ]; then echo 1 else echo 2 fi } # # Sub-command functions # cmd_version() { cat <<_EOF_ v${VERSION} Aaron LI https://github.com/liweitianux/dfly-update _EOF_ } cmd_usage() { cat <<_EOF_ dfly-update - DragonFly BSD update tool using binary release/snapshots Usage: help Show this help. version Show version information of this tool. status Show local installed system version and remote available version. _EOF_ echo cmd_version } cmd_status() { local branch version branch_remote version_remote has_update branch=$(get_local_branch) version=$(get_local_version) if [ -z "${UPDATE_BRANCH}" ]; then branch_remote=${branch} else branch_remote=${UPDATE_BRANCH} fi eval "$(get_latest_image ${branch_remote})" || exit $? version_remote=$(get_version_filename ${branch_remote} ${_filename}) cat <<_EOF_ Local installed system: branch: ${branch} version: ${version} Remote available system: branch: ${branch_remote} version: ${version_remote} _EOF_ has_update=$(compare_version ${version} ${version_remote}) if [ ${has_update} -eq 0 ]; then echo "^_^ Your DragonFly is up-to-date ^_^" elif [ ${has_update} -eq 1 ]; then echo "!!! Your DragonFly needs update !!!" else echo "??? Your DragonFly is newer than remote ???" fi } cmd_extension_or_status() { case "$1" in "") cmd_status ;; *) echo "TODO..." ;; esac } # # Main # # Load configurations [ -r "${CONFIGFILE}" ] && load_config ${CONFIGFILE} COMMAND="$1" case "${COMMAND}" in help|--help|-h) shift cmd_usage ;; version|--version|-V) shift cmd_version ;; status) shift cmd_status "$@" ;; *) cmd_extension_or_status "$@" ;; esac exit 0