#!/bin/ksh
#
########################################################################
#
# snaps - Check if you can upgrade your OpenBSD OS base to
# last -current snapshot
#
# Copyright (c) 2017-2020, Fred Galusik <f AT galusik.fr>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
set -ue
###
### VARS
###
VERSION=2.0
# choose your MIRROR
true "${MIRROR:=$(grep -v "^#" /etc/installurl)}"
# curl is mandatory
if [ ! "$(which curl 2>/dev/null)" ]; then
echo "WARNING: 'curl' is requested to run this program. Aborting..."
exit 1
fi
CURL=$(whereis curl)
#
ARCH=$(uname -m)
SHA=SHA256
BASE=/snapshots/${ARCH}/
BASEF=/snapshots/${ARCH}/${SHA}
PKGSF=/snapshots/packages/${ARCH}/${SHA}
GET='/usr/bin/ftp -n -m -C'
LOGF=/var/log/snaps.log
###
###
###
usage() {
echo "${0##*/} ${VERSION}"
echo "Usage: ${0##*/} [-scalfuph]"
echo ""
echo " -s check \$MIRROR freshness & choose to sysupgrade or not"
echo " -c check BASE and PACKAGES build dates from \$MIRROR"
echo " -a check BASE and PACKAGES build dates from all available mirrors"
echo " -l list date and \$MIRROR of the 3 last upgrade using this script"
echo " -f read the online FAQ : Following -current and using snapshots"
echo " -u upgrade snaps to last version"
echo " -p update ports tree to -current"
echo " -h print this help and exit"
echo ""
echo "MIRROR is based upon /etc/installurl and set to: ${MIRROR}"
echo ""
echo "You can set it manually:"
echo "\$ MIRROR=http://mirrors.ircam.fr/pub/OpenBSD snaps -c"
echo ""
}
s_root() {
if [[ $(id -u) != "0" ]]; then
echo "WARNING: You need to be root to do this! Aborting..." 1>&2
exit 1
fi
}
s_toupgrade() {
REMOTESNAPS='https://framagit.org/fredg/snaps/raw/master/snaps'
LASTSNAPS=/tmp/snaps
echo "Checking snaps release..."
if [[ -f "${LASTSNAPS}" ]]; then
rm -f "${LASTSNAPS}"
fi
if $GET -V -o "${LASTSNAPS}" "${REMOTESNAPS}"; then
REMOTEVERSION=$(awk -F '=' '/^VERSION=/ { print $2 }' "${LASTSNAPS}")
if [ "${VERSION}" != "${REMOTEVERSION}" ]; then
echo "WARNING: snaps is not up-to-date !"
echo "Last version: ${REMOTEVERSION}"
echo "To upgrade, run 'snaps -u'"
else
echo "GOOD: snaps is up-to-date."
fi
else
echo "WARNING: Remote snaps not reachable ! Check the connection."
fi
echo ""
}
s_upgrade() {
SELFPATH=$(dirname "$(readlink -f -- "$0")")
echo "Downloading last snaps version..."
$GET -o "${SELFPATH}" "${REMOTESNAPS}"
}
get_log() {
if [[ -f "${LOGF}" ]]; then
tail -n 3 ${LOGF}
else
echo "No ${LOGF} file. Seems you have not yet played with snaps."
exit 1
fi
}
s_upports() {
echo "Updating Ports tree..."
cd /usr/ports || exit 1
/usr/bin/cvs up -Pd || exit 1
echo "New Ports tree fetched!"
}
s_cur() {
CURRENTSYS=$(sed q /var/run/dmesg.boot)
echo "=== LOCAL BASE BUILD DATE ==="
echo "${CURRENTSYS}"
}
s_when() {
CURLB="$(${CURL} -sI "${MIRROR}${BASEF}" | grep Last-Modified)"
CURLP="$(${CURL} -sI "${MIRROR}${PKGSF}" | grep Last-Modified)"
echo "=== ONLINE BASE AND PACKAGES BUILD DATES ==="
echo "From ${MIRROR}"
echo "Base (${ARCH}) => ${CURLB}"
echo "Packages (${ARCH}) => ${CURLP}"
}
s_sysup() {
NOW=$(date "+ %Y-%m-%d %R")
echo ""
echo -n "Do you want to run 'sysupgrade -s' ? (y/n): "
read -r _c
case ${_c} in
y|Y)
;;
*)
echo "Aborting..."
exit 1
;;
esac
echo "${NOW} FROM ${MIRROR}${BASE}" >> ${LOGF}
/usr/sbin/sysupgrade -s
}
read_faq() {
FAQ='https://www.openbsd.org/faq/current.html'
if [ "$(which links 2>/dev/null)" ]; then
READ='links -dump'
elif [ "$(which lynx 2>/dev/null)" ]; then
READ='lynx --dump'
else
echo "WARNING: You need 'links' or 'lynx' to read the online FAQ/CURRENT. Aborting..."
exit 1
fi
${READ} ${FAQ} | less
}
all_mirrors() {
echo "Checking mirrors..."
HTTPSLIST='https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/www/httpslist'
MIRRORLIST=$(${CURL} ${HTTPSLIST} | awk '{print $1}')
echo ""
for _m in ${MIRRORLIST}
do
CB="$(${CURL} -sI "${_m}${BASEF}" | grep Last-Modified |\
sed 's/Last-Modified: //')"
CP="$(${CURL} -sI "${_m}${PKGSF}" | grep Last-Modified |\
sed 's/Last-Modified: //')"
# only print mirror which give an answer
# FIXME try to figure out how to print 1 mirror per line
if [ "${CB}" ]; then
echo "${_m}"
echo "${CB}"
echo "${CP}"
echo ""
fi
done
}
##
## Run
##
if [ $# -eq 0 ]; then
usage
exit 1
fi
case $1 in
-s)
s_root
s_toupgrade
s_cur
echo ""
s_when
s_sysup
;;
-c)
s_cur
s_when
;;
-a)
all_mirrors
;;
-l)
get_log
;;
-f)
read_faq
;;
-u)
s_upgrade
;;
-p)
s_upports
;;
-h|*)
usage
exit 1
;;
esac