File: [local] / openbsd / update_openbsd / update_openbsd (download)
Revision 1.65, Sat Feb 1 19:13:53 2014 UTC (10 years, 3 months ago) by andrew
Branch: MAIN
Changes since 1.64: +24 -31 lines
Require running update_openbsd as root
It doesn't make sense to use SUDO to run specific bits because it is flaky.
That is, sometimes the sudo timeout will happen before the next step so you
will have to notice and type the password again. This is often a problem
on machines with slower disks.
It does mean downloading and verifying the sets as root instead of an
normal user but that is not too big of a deal.
It might be worthwhile to wrap the privileged actions in a function and figure
out how to run that entire function as root but that's complication we don't
actually need.
Thanks to Chris Cappuccio for the suggestion.
|
#!/bin/sh
# $AFresh1: update_openbsd,v 1.65 2014/02/01 19:13:53 andrew Exp $
#
# Copyright (c) 2012 Andrew Fresh <andrew@afresh1.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
installed_sets() {
local misc=/usr/share/doc/README
local man=/usr/share/man/man1/intro.1
local comp=/usr/bin/cc
local game=/usr/games/
local xbase=/usr/X11R6/
local xetc=/etc/X11/xinit/xinitrc
local xfont=/usr/X11R6/lib/X11/fonts
local xserv=/usr/X11R6/bin/X
local xshare=/usr/X11R6/bin/startx
local _c _d _e
echo -n base
echo -n ' etc'
for _d in misc man comp game xbase xetc xfont xserv xshare; do
eval _e=\$${_d}
_c=`ls $_e 2> /dev/null | wc -l`
#echo $_c $_d $_e
if [ $_c -ne 0 ]; then
echo -n " $_d"
fi
done
sendmail -d0.1 --badoption </dev/null 2>/dev/null | grep -q SASL
if [ $? == 0 ]; then
echo -n ' sendmail-smtp_auth'
fi
}
kernel_file_version() {
echo exit | config -e $1 | grep -A1 ^OpenBSD
#what $1 | sed -ne 's/[[:blank:]]\{1,\}//p'
}
version_in() {
local _proto=${FTP%%://*}
local _file
if [ X"ftp" == X"${_proto}" ]; then
local _list=`echo "ls base*.tgz" | ${FTP_CMD} ${FTP}/`
_file=`echo ${_list} | awk '/base[0-9][0-9].tgz/ { print $9 }'`
elif [ X"http" == X"${_proto}" ]; then
local _list=`${FTP_CMD} -V -o - ${FTP}/`
_file=`echo ${_list} | awk '/[^x]base[0-9][0-9]*\.tgz/ {
sub("^.*base","base");
sub("\.tgz.*",".tgz");
print $0;
}'`
elif [ X"scp" == X"${_proto}" ]; then
echo SCP is not yet supported >&2
return 2
else
echo Unsupported FTP ${FTP} >&2
return 2
fi
local _v=${_file##*base}
_v=${_v%.tgz*}
echo $_v
}
set_version() {
CUR_VER=`uname -r`
NEW_VER=`dc -e "$CUR_VER 0.1 + p"`
FILE_VER=""
FTP=""
local _cv=`echo $CUR_VER | sed -e 's/\.//'`
local _nv=`echo $NEW_VER | sed -e 's/\.//'`
local _v
if [ X"No" != X"$FORCE_DIR" -a -d $FORCE_DIR ]; then
_dir=$FORCE_DIR
if [ -e ${_dir}/base${_nv}.tgz ]; then
_v=$_nv
elif [ -e ${_dir}/base${_cv}.tgz ]; then
NEW_VER=$CUR_VER
_v=$_cv
fi
elif [ -d $CUR_VER ]; then
_dir=$CUR_VER
NEW_VER=$CUR_VER
if [ -e ${_dir}/base${_cv}.tgz ]; then
_v=$_cv
fi
elif [ -d $NEW_VER ]; then
_dir=$NEW_VER
if [ -e ${_dir}/base${_nv}.tgz ]; then
_v=$_nv
fi
fi
if [ X"" != X"${MIRROR}" -a X"" == X"${_v}" ]; then
if [ X"No" == X"${FORCE_DIR}" ]; then
_dir=${NEW_VER}
else
_dir=${FORCE_DIR}
fi
FTP=${MIRROR}/${_dir}/`machine`
_v=`version_in`
if [ X"" == X"${_v}" ]; then
if [ X"No" != X"$FORCE_DIR" ]; then
echo No sets in forced [${FTP}] >&2
return 2
fi
NEW_VER=$CUR_VER
_dir=${NEW_VER}
FTP=${MIRROR}/${_dir}/`machine`
_v=`version_in`
fi
if [ X"" == X"${_v}" ]; then
echo No sets in [${FTP}] >&2
return 2
elif [ X"${_cv}" == X"${_v}" ]; then
NEW_VER=$CUR_VER
elif [ X"${_nv}" == X"${_v}" ]; then
NEW_VER=$NEW_VER
else
echo Invalid version [$_v] >&2
return 2
fi
if [ X"No" == X"$FORCE_DIR" ]; then
_dir=$NEW_VER
fi
fi
if [ X"" == X"${_v}" ]; then
if [ X"" == X"${MIRROR}" ]; then
echo ERROR: No sets, and no MIRROR, unable to continue. >&2
else
echo ERROR: Unable to determine FILE_VER, check your MIRROR. >&2
fi
return 1
fi
if [ X"" == X"$RELEASEDIR" ]; then
RELEASEDIR=`pwd`/$_dir
fi
FILE_VER=$_v
if [ X"" != X"${MIRROR}" ]; then
FTP=${MIRROR}/${_dir}/`machine`
fi
BOOT_KERNEL=`( \
echo bsd; \
[ -e /boot.conf ] && sed -E '/^ *(set +image|boot) +/!d ; \
s///; s/^.*://; s/ .*$//' /boot.conf \
) | tail -1`
BOOT_KERNEL=`follow_symlink /$BOOT_KERNEL`
BOOT_KERNEL="/${BOOT_KERNEL#/}"
BOOT_KERNEL_VERSION=`kernel_file_version $BOOT_KERNEL`
BOOTED_KERNEL_VERSION=`sysctl -n kern.version`
NEW_KERNEL_VERSION=""
# We want to default to what we had
INSTALL_KERNELS="${BOOT_KERNEL#/}"
# if the boot kernel was our specially named bsd.sp, we install from bsd
if [ X"$INSTALL_KERNELS" == X"bsd.sp" ]; then
INSTALL_KERNELS="bsd"
fi
# with a second option of an mp kernel if is is a likely candidate
if [ X"$INSTALL_KERNELS" != X"bsd.mp" ]; then
local _ncpu=$(sysctl -n hw.ncpufound)
[ $_ncpu -gt 1 ] && INSTALL_KERNELS="$INSTALL_KERNELS bsd.mp"
fi
# or just bsd otherwise
if [ X"${INSTALL_KERNELS% *}" != X"bsd" ]; then
INSTALL_KERNELS="$INSTALL_KERNELS bsd"
fi
BOOT_KERNELS=$INSTALL_KERNELS
INSTALL_KERNELS="$INSTALL_KERNELS bsd.rd"
}
get_sets() {
echo '==> GETTING SETS'
if [ X"" == X"$FTP" ]; then
echo ERROR: No FTP site set! >&2
return 1
fi
mkdir -p ${RELEASEDIR}
cd $RELEASEDIR
local _v=$FILE_VER
for _b in $INSTALL_KERNELS; do
if [ ! -e ./${_b} ]; then
echo "===> $FTP_CMD ${FTP}/${_b}"
$FTP_CMD ${FTP}/${_b}
fi
done
for _s in $INSTALLED_SETS; do
local _file=${_s}${_v}.tgz
if [ ${_s} == sendmail-smtp_auth ]; then
_file=${_s}.gz
fi
if [ ! -e ./${_file} ]; then
echo "===> $FTP_CMD ${FTP}/${_file}"
$FTP_CMD ${FTP}/${_file}
fi
done
local _type
local _ftp
for _type in $CHECKSUM_TYPES; do
[ -e $_type ] && break
_ftp=`echo "$FTP" | sed -e 's,://[^/]*/,://ftp.openbsd.org/,'`
echo "===> $FTP_CMD ${_ftp}/$_type"
$FTP_CMD ${_ftp}/$_type
done
}
follow_symlink () {
local _file=$1
# This could go circular, but I dunno how to fix that.
if [ -h $_file ]; then
follow_symlink $( file $_file |
grep 'symbolic link' |
sed -e s/^.*\\\`// -e s/\\\'\$// )
else
echo $_file
fi
}
check_sum () {
local _type=$1
echo "==> CHECKING $_type SUMS"
cd $RELEASEDIR
if [ ! -e $_type ]; then
echo $_type File does not exist!
return 1
fi
local _nv=`echo $NEW_VER | sed -e 's/\.//'`
local _signify=`which signify 2>/dev/null`
local _keyfile=/etc/signify/${_nv}base.pub
local _b _s
(
for _b in $INSTALL_KERNELS; do echo "($_b)" ; done
for _s in $INSTALLED_SETS; do echo "($_s$_nv.tgz)"; done
) > index
if [ -n "$_signify" -a "$_type" != "${_type%.sig}" ]; then
echo "===> Checking signature";
if [ ! -e $_keyfile ]; then
echo "key [$_keyfile] does not exist, cannot check $_type" >&2
return 2
fi
signify -V -e -p $_keyfile -x $_type -m - | grep -f index | sum -c -
else
grep -f index $_type | sum -c
fi
if [ $? -ne 0 ]; then
echo ERROR: $_type does not match! >&2
return 1
fi
}
check_sets() {
echo '==> CHECKING SETS'
cd $RELEASEDIR
local _missing_sets
local _v=$FILE_VER
for _n in $INSTALL_KERNELS; do
local _o=$_n
[ X"bsd" == X"${_o}" -a -e /bsd.sp ] && _o=bsd.sp
if [ -e /${_o} -a ! -e ./${_n} ]; then
echo ${_o} does not exist
_missing_sets=1
fi
if [ X"${BOOT_KERNEL}" == X"/${_o}" -a -e ./${_n} ]; then
NEW_KERNEL_VERSION=`kernel_file_version ./${_n}`
fi
done
if [ X"$NEW_KERNEL_VERSION" == X"" ]; then
echo Missing replacement for boot kernel $BOOT_KERNEL >&2
_missing_sets=1
fi
for _s in $INSTALLED_SETS; do
local _file=${_s}${_v}.tgz
if [ ${_s} == sendmail-smtp_auth ]; then
_file=${_s}.gz
fi
if [ ! -e ./${_file} ]; then
echo ${_file} does not exist
_missing_sets=1
fi
done
if [ X"" == X"${_missing_sets}" ]; then
echo '===> All OK'
fi
local _type
for _type in $CHECKSUM_TYPES; do
if [ -e $_type ]; then
check_sum $_type && break
[ -z "$IGNORE_CHECKSUM_ERROR" ] && exit 1
fi
done
return 0
}
install_kernels() {
echo '==> INSTALLING KERNEL'
if [ X"" == X"$RELEASEDIR" ]; then
echo ERROR: no source for new kernels! >&2
exit 1
fi
if [ X"$BOOT_KERNEL_VERSION" != X"$NEW_KERNEL_VERSION" ]; then
echo "===> Backing up $BOOT_KERNEL to /obsd"
ln -f $BOOT_KERNEL /obsd
if [ $? -ne 0 ]; then
echo "Error copying old kernel!" >&2
exit 1
fi
fi
cd $RELEASEDIR
for _b in $INSTALL_KERNELS; do
rm -f /nbsd
local _bd=$_b
[ X"${_b}" == X"bsd" ] && _bd="bsd.sp"
local _is_boot=""
[ X"$BOOT_KERNEL" == X"/${_bd}" ] && _is_boot="# boot kernel"
echo "===> Copying $_b to /$_bd $_is_boot"
cp ${_b} /nbsd && mv /nbsd /${_bd}
if [ $? -ne 0 ]; then
echo ERROR: Could not copy new $_bd kernel! >&2
exit 1
fi
done
cd $OLDPWD
if [ ! -h /bsd ]; then
cd /
for _b in $BOOT_KERNELS; do
[ X"$_b" == X"bsd" ] && _b="bsd.sp"
if [ -e $_b ]; then
echo "===> symlinking $_b to /bsd"
ln -sf $_b bsd
if [ $? -ne 0 ]; then
echo ERROR: Could not symlink new kernel! >&2
exit 1
fi
break
fi
done
cd $OLDPWD
fi
}
install_sets() {
echo '==> INSTALLING SETS'
if [ X"" == X"$RELEASEDIR" ]; then
echo ERROR: no source for sets! >&2
exit 1
else
cd $RELEASEDIR
fi
local _v=$FILE_VER
local _sets=`ls *${_v}.tgz | grep -v ^base `
for _f in ${_sets} base${_v}.tgz; do
_path=$DESTDIR
if [ X"etc${_v}.tgz" == X"$_f" \
-o X"xetc${_v}.tgz" == X"$_f" ]; then
[ X"" != X"$SYSMERGE" ] && continue
_path=/var/tmp/temproot
fi
echo "===> Extracting $_f to $_path"
mkdir -p $_path
tar -C $_path -xzphf ${RELEASEDIR}/${_f}
if [ $? -ne 0 ]; then
echo ERROR: Could not extract ${_f}! >&2
exit 1
fi
done
echo '===> Extracted all sets.'
}
install_sendmail_smtp_auth() {
if [ -e ${RELEASEDIR}/sendmail-smtp_auth.gz ]; then
gzcat ${RELEASEDIR}/sendmail-smtp_auth.gz > \
${RELEASEDIR}/sendmail-smtp_auth
fi
if [ -e ${RELEASEDIR}/sendmail-smtp_auth ]; then
if ! pkg_info -qe 'cyrus-sasl-*'; then
pkg_add -i cyrus-sasl
fi
install -o root -g smmsp -m 2555 \
${RELEASEDIR}/sendmail-smtp_auth \
/usr/libexec/sendmail/sendmail
echo '===> Installed sendmail with smtp_auth'
fi
}
update_etc() {
echo '==> UPDATING ETC'
if [ ! -e $SYSMERGE ]; then
echo "ERROR: Can't find sysmerge!" >&2
exit 1;
fi
if [ X"" == X"$RELEASEDIR" ]; then
echo "ERROR: no source for etc!" >&2
exit 1
fi
cd $RELEASEDIR
local _v=$FILE_VER
local _args=""
if [ -e etc${_v}.tgz ]; then
_args="$_args -s ${RELEASEDIR}/etc${_v}.tgz"
fi
if [ -e xetc${_v}.tgz ]; then
_args="$_args -x ${RELEASEDIR}/xetc${_v}.tgz"
fi
if [ X"" == X"$_args" ]; then
echo ERROR: No upgrade sets found! >&2
else
echo '==> RUNNING SYSMERGE'
$SYSMERGE $_args
fi
cd $OLDPWD
}
if [ $(id -u) != 0 ]; then
echo 'ERROR: need root privileges to run this script' >&2
exit 1
fi
if [ -e /etc/update_openbsd.conf ]; then
. /etc/update_openbsd.conf
fi
if [ -e ${HOME}/.update_openbsdrc ]; then
. ${HOME}/.update_openbsdrc
fi
#MIRROR=${MIRROR:=ftp://ftp.openbsd.org/pub/OpenBSD}
FTP_CMD=${FTP_CMD:=ftp -V}
PKG_PATH=${PKG_PATH:=/usr/ports/packages/`machine`/all/:${MIRROR}/`uname -r`/packages/`machine`/}
DESTDIR=${DESTDIR:=/}
SYSMERGE=${SYSMERGE:=/usr/sbin/sysmerge}
FORCE_DIR=${FORCE_DIR:=No}
INSTALLED_SETS=${INSTALLED_SETS:=`installed_sets`}
CHECKSUM_TYPES=${CHECKSUM_TYPES:=SHA256.sig SHA256}
set_version
local _error=$?
echo
echo "-= update_openbsd - helper script to update OpenBSD =-"
echo "------------------------------------------------------"
echo
echo " SYSMERGE: $SYSMERGE"
echo " MIRROR: $MIRROR"
echo " RELEASEDIR: $RELEASEDIR"
echo " DESTDIR: $DESTDIR"
echo " BOOT_KERNEL: $BOOT_KERNEL"
echo "INSTALL_KERNELS: $INSTALL_KERNELS"
echo " INSTALLED_SETS: $INSTALLED_SETS"
echo
echo " CUR_VER: $CUR_VER"
echo " NEW_VER: $NEW_VER"
#echo " FILE_VER: $FILE_VER"
echo
if [ ${_error} -ne 0 ]; then
exit ${_error}
fi
if [ X"" != X"${FTP}" ]; then
get_sets
fi
check_sets || exit
echo "===> Last booted:\n$BOOTED_KERNEL_VERSION"
if [ X"$BOOT_KERNEL_VERSION" != X"$BOOTED_KERNEL_VERSION" \
-a X"$BOOT_KERNEL_VERSION" != X"$NEW_KERNEL_VERSION" ]; then
echo "Next boot (unless replaced):\n$BOOT_KERNEL_VERSION"
fi
if [ -n "$NEW_KERNEL_VERSION" ]; then
echo "===> New $BOOT_KERNEL:\n$NEW_KERNEL_VERSION";
else
echo "\n!!! WARNING: Will not replace boot kernel $BOOT_KERNEL! !!!\n" >&2
echo "ctrl+C to cancel, enter to continue anyway" >&2
local _temp
read _temp
NEW_KERNEL_VERSION=$BOOT_KERNEL_VERSION
fi
if [ $CUR_VER != $NEW_VER ]; then
echo >&2
echo "!!! You are upgrading between OpenBSD versions. !!!" >&2
echo "!!! You should make sure you have a root shell open !!!" >&2
echo "!!! It is needed in order to run /sbin/oreboot. !!!" >&2
echo "!!! sudo MAY NOT WORK after sets are extracted. !!!" >&2
echo >&2
echo "ctrl+C to cancel, enter to continue" >&2
local _temp
read _temp
fi
if [ X"$NEW_KERNEL_VERSION" != X"$BOOTED_KERNEL_VERSION" \
-a ! -e /sbin/oreboot ]; then
cp /sbin/reboot /sbin/oreboot
if [ $? -ne 0 ]; then
echo "Error copying old reboot command!" >&2
exit 1
fi
echo "/sbin/reboot copied to /sbin/oreboot"
fi
install_kernels
install_sets
if [ X"$NEW_KERNEL_VERSION" == X"$BOOTED_KERNEL_VERSION" ]; then
install_sendmail_smtp_auth
if [ -e /sbin/oreboot ]; then
echo Removing /sbin/oreboot
$rm -f /sbin/oreboot
fi
update_etc
echo '==> UPDATING PACKAGES'
pkg_add -ui -F update -F updatedepends
else
echo Instructions for updating to the new version available from
if [ X"snapshots" == X"$FORCE_DIR" ]; then
echo " http://www.openbsd.org/faq/current.html"
else
echo " http://www.openbsd.org/faq/upgrade${FILE_VER}.html"
fi
fi
echo Update complete press any key to reboot, ctrl+C to cancel
read _temp
if [ -e /sbin/oreboot ]; then
/sbin/oreboot
else
/sbin/reboot
fi