[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.39, Sat Dec 8 19:52:08 2012 UTC (11 years, 5 months ago) by andrew
Branch: MAIN
Changes since 1.38: +103 -82 lines

Redo finding which kernels to install

Loses the ability to have custom kernels in /bsd* but makes makes
the output cleaner.  The functionality could be added back in.

The main goal was to display which kernel versions we have and will
have so we know better what we are installing.

#!/bin/sh
# $AFresh1: update_openbsd,v 1.39 2012/12/08 19:52:08 andrew Exp $

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="/${BOOT_KERNEL#/}"
    BOOT_KERNEL=`follow_symlink $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#/}"
    # 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} -a ! -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
        if [ ! -e $_type ]; then
            echo $FTP_CMD ${FTP}/$_type
            $FTP_CMD ${FTP}/$_type
        fi
    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

    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

    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 [ $CUR_VER != $NEW_VER -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
        SYSMERGE=
    fi

    if [ X"" == X"$SYSMERGE" ]; then
        if [ -e /var/tmp/temproot ]; then
            MERGEMASTER=`which mergemaster`

            if [ $? != 0 ]; then
                $SUDO pkg_add -i mergemaster

                MERGEMASTER=`which mergemaster`
                if [ $? != 0 ]; then
                    echo ERROR: mergemaster not installed! >&2
                    exit 1
                fi
            fi

            echo '### RUNNING MERGEMASTER ###'
            $SUDO $MERGEMASTER -irv
        else 
            echo "ERROR: no source for etc!" >&2
            exit 1
        fi
    else
        if [ X"" == X"$RELEASEDIR" ]; then
            echo "ERROR: no source for etc!" >&2
            exit 1
        else
            cd $RELEASEDIR
        fi

        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 ###'
            if sysmerge 2>&1 | grep -- -a >/dev/null; then
                _args="-a $_args"
            fi
            $SUDO $SYSMERGE $_args
        fi
    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 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 [ X"" != X"$SUDO" ]; then
    echo Please enter your sudo password if prompted.
    echo You may be asked for it again later in the process.
    $SUDO -v
fi

install_kernels
install_sets

if [ $CUR_VER == $NEW_VER ]; 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