[BACK]Return to update_openbsd CVS log [TXT][DIR] Up to [local] / openbsd / update_openbsd

File: [local] / openbsd / update_openbsd / update_openbsd (download)

Revision 1.49, Sun Oct 20 00:13:38 2013 UTC (10 years, 7 months ago) by andrew
Branch: MAIN
Changes since 1.48: +4 -3 lines

Check for a new kernel, not a new version

To better insulate from changes, rather than insisting on a reboot only between versions, instead force the reboot for each kernel change.

This does mean an extra reboot that may not be strictly necessary most of the time, but it is safer.

#!/bin/sh
# $AFresh1: update_openbsd,v 1.49 2013/10/20 00:13:38 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/cat1/intro.0
    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
        echo ERROR: Unable to determine file version! >&2
        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
    for _type in $CHECKSUM_TYPES; do
        [ -e $_type ] && break
        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

    ls bsd* *gz | sed -e 's/\(.*\)/(\1)/' > index 
    grep -f index $_type | sum -c 

    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
        fi
    done
}


install_kernels() {
    echo '### INSTALLING KERNEL ###'
    if [ X"$USER" != X"root" -a X"$SUDO" == X"" ]; then
        echo ${0##*/} must be run as root or SUDO must be set! >&2
        exit 1
    fi

    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"
        $SUDO 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
        $SUDO 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"
        $SUDO cp ${_b} /nbsd && $SUDO 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
                $SUDO 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"$USER" != X"root" -a X"$SUDO" == X"" ]; then
        echo ${0##*/} must be run as root or SUDO must be set! >&2
        exit 1
    fi

    if [ X"" == X"$RELEASEDIR" ]; then
        echo ERROR: no source for sets! >&2
        exit 1
    else
        cd $RELEASEDIR
    fi

    local _v=$FILE_VER

    if [ X"$BOOT_KERNEL_VERSION" != X"$BOOTED_KERNEL_VERSION" \
         -a ! -e /sbin/oreboot ]; then
        $SUDO 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

    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
        $SUDO mkdir -p $_path
        $SUDO 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.

    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
            $SUDO pkg_add -i cyrus-sasl
        fi

        $SUDO 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 etc${_v}.tgz"
    fi
    if [ -e xetc${_v}.tgz ]; then
        _args="$_args -x xetc${_v}.tgz"
    fi
    if [ X"" == X"$_args" ]; then 
        echo ERROR: No upgrade sets found! >&2
    else
        echo '### RUNNING SYSMERGE ###'
        $SUDO $SYSMERGE $_args
    fi

    cd $OLDPWD
}


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 MD5}

set_version
local _error=$?

echo
echo "-= update_openbsd - helper script to update OpenBSD =-"
echo "------------------------------------------------------"
echo
echo "           SUDO: $SUDO"
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
fi

if [ -n "$SUDO" -a $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 [ -n "$SUDO" ]; then
    echo
    echo You may be asked for your sudo password multiple times.
    $SUDO -v -p "sudo Password: "
fi

install_kernels
install_sets

if [ X"$BOOT_KERNEL_VERSION" == X"$BOOTED_KERNEL_VERSION" ]; then
    if [ -e /sbin/oreboot ]; then
        echo Removing /sbin/oreboot
        $SUDO rm -f /sbin/oreboot
    fi
    update_etc

    echo '### UPDATING PACKAGES ###'
    $SUDO 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 New kernel installed.  Please reboot!
if [ -e /sbin/oreboot ]; then
    echo Possibly using /sbin/oreboot
fi

local _send_dmesg=`dirname $0`/send_dmesg 
if [ -e "$_send_dmesg" ]; then
    if [ -e $RELEASEDIR/.send_dmesg ]; then
        $_send_dmesg
        rm -f $RELEASEDIR/.send_dmesg
    elif [ X"$CUR_VER" != X"$NEW_VER" ]; then
        touch $RELEASEDIR/.send_dmesg
    fi
fi