diff options
author | simon <simon@FreeBSD.org> | 2009-08-19 20:47:31 +0000 |
---|---|---|
committer | simon <simon@FreeBSD.org> | 2009-08-19 20:47:31 +0000 |
commit | 5bb5dcc9da07e5a183e368cffe134a4d5e09996f (patch) | |
tree | 9e040ed80ab4fc1b7cc806a08b75a87507b5395b /usr.sbin/freebsd-update | |
parent | 0c0a18c1fff02d650c478b24b66cc5f5a6fa4179 (diff) | |
download | FreeBSD-src-5bb5dcc9da07e5a183e368cffe134a4d5e09996f.zip FreeBSD-src-5bb5dcc9da07e5a183e368cffe134a4d5e09996f.tar.gz |
Add support for backing up the old kernel when installing a new kernel
using freebsd-update. This applies to using freebsd-update in "upgrade
mode" and normal freebsd-update on a security branch.
The backup kernel will be written to /boot/kernel.old, if the directory
does not exist, or the directory was created by freebsd-update in a
previous backup. Otherwise freebsd-update will generate a new directory
name for use by the backup. By default symbol files are not backed up
to save diskspace and avoid filling up the root partition.
This feature is fully configurable in the freebsd-update config file,
but defaults to enabled.
MFC after: 1 week (stable/7)
Reviewed by: cperciva
Approved by: re (kib)
Diffstat (limited to 'usr.sbin/freebsd-update')
-rw-r--r-- | usr.sbin/freebsd-update/freebsd-update.sh | 162 |
1 files changed, 161 insertions, 1 deletions
diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh index 331ef10..2eacca8 100644 --- a/usr.sbin/freebsd-update/freebsd-update.sh +++ b/usr.sbin/freebsd-update/freebsd-update.sh @@ -88,7 +88,7 @@ EOF CONFIGOPTIONS="KEYPRINT WORKDIR SERVERNAME MAILTO ALLOWADD ALLOWDELETE KEEPMODIFIEDMETADATA COMPONENTS IGNOREPATHS UPDATEIFUNMODIFIED BASEDIR VERBOSELEVEL TARGETRELEASE STRICTCOMPONENTS MERGECHANGES - IDSIGNOREPATHS" + IDSIGNOREPATHS BACKUPKERNEL BACKUPKERNELDIR BACKUPKERNELSYMBOLFILES" # Set all the configuration options to "". nullconfig () { @@ -308,6 +308,70 @@ config_VerboseLevel () { fi } +config_BackupKernel () { + if [ -z ${BACKUPKERNEL} ]; then + case $1 in + [Yy][Ee][Ss]) + BACKUPKERNEL=yes + ;; + [Nn][Oo]) + BACKUPKERNEL=no + ;; + *) + return 1 + ;; + esac + else + return 1 + fi +} + +config_BackupKernelDir () { + if [ -z ${BACKUPKERNELDIR} ]; then + if [ -z "$1" ]; then + echo "BackupKernelDir set to empty dir" + return 1 + fi + + # We check for some paths which would be extremely odd + # to use, but which could cause a lot of problems if + # used. + case $1 in + /|/bin|/boot|/etc|/lib|/libexec|/sbin|/usr|/var) + echo "BackupKernelDir set to invalid path $1" + return 1 + ;; + /*) + BACKUPKERNELDIR=$1 + ;; + *) + echo "BackupKernelDir ($1) is not an absolute path" + return 1 + ;; + esac + else + return 1 + fi +} + +config_BackupKernelSymbolFiles () { + if [ -z ${BACKUPKERNELSYMBOLFILES} ]; then + case $1 in + [Yy][Ee][Ss]) + BACKUPKERNELSYMBOLFILES=yes + ;; + [Nn][Oo]) + BACKUPKERNELSYMBOLFILES=no + ;; + *) + return 1 + ;; + esac + else + return 1 + fi +} + # Handle one line of configuration configline () { if [ $# -eq 0 ]; then @@ -461,6 +525,9 @@ default_params () { config_BaseDir / config_VerboseLevel stats config_StrictComponents no + config_BackupKernel yes + config_BackupKernelDir /boot/kernel.old + config_BackupKernelSymbolFiles no # Merge these defaults into the earlier-configured settings mergeconfig @@ -665,6 +732,14 @@ install_check_params () { echo "Re-run '$0 fetch'." exit 1 fi + + # Figure out what directory contains the running kernel + BOOTFILE=`sysctl -n kern.bootfile` + KERNELDIR=${BOOTFILE%/kernel} + if ! [ -d ${KERNELDIR} ]; then + echo "Cannot identify running kernel" + exit 1 + fi } # Perform sanity checks and set some final parameters in @@ -2494,6 +2569,88 @@ install_unschg () { rm filelist } +# Decide which directory name to use for kernel backups. +backup_kernel_finddir () { + CNT=0 + while true ; do + # Pathname does not exist, so it is OK use that name + # for backup directory. + if [ ! -e $BACKUPKERNELDIR ]; then + return 0 + fi + + # If directory do exist, we only use if it has our + # marker file. + if [ -d $BACKUPKERNELDIR -a \ + -e $BACKUPKERNELDIR/.freebsd-update ]; then + return 0 + fi + + # We could not use current directory name, so add counter to + # the end and try again. + CNT=$((CNT + 1)) + if [ $CNT -gt 9 ]; then + echo "Could not find valid backup dir ($BACKUPKERNELDIR)" + exit 1 + fi + BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`" + BACKUPKERNELDIR="${BACKUPKERNELDIR}${CNT}" + done +} + +# Backup the current kernel using hardlinks, if not disabled by user. +# Since we delete all files in the directory used for previous backups +# we create a marker file called ".freebsd-update" in the directory so +# we can determine on the next run that the directory was created by +# freebsd-update and we then do not accidentally remove user files in +# the unlikely case that the user has created a directory with a +# conflicting name. +backup_kernel () { + # Only make kernel backup is so configured. + if [ $BACKUPKERNEL != yes ]; then + return 0 + fi + + # Decide which directory name to use for kernel backups. + backup_kernel_finddir + + # Remove old kernel backup files. If $BACKUPKERNELDIR was + # "not ours", backup_kernel_finddir would have exited, so + # deleting the directory content is as safe as we can make it. + if [ -d $BACKUPKERNELDIR ]; then + rm -f $BACKUPKERNELDIR/* + fi + + # Create directory for backup if it doesn't exist. + mkdir -p $BACKUPKERNELDIR + + # Mark the directory as having been created by freebsd-update. + touch $BACKUPKERNELDIR/.freebsd-update + if [ $? -ne 0 ]; then + echo "Could not create kernel backup directory" + exit 1 + fi + + # Disable pathname expansion to be sure *.symbols is not + # expanded. + set -f + + # Use find to ignore symbol files, unless disabled by user. + if [ $BACKUPKERNELSYMBOLFILES = yes ]; then + FINDFILTER="" + else + FINDFILTER=-"a ! -name *.symbols" + fi + + # Backup all the kernel files using hardlinks. + find $KERNELDIR -type f $FINDFILTER | \ + sed -Ee "s,($KERNELDIR)/?(.*),\1/\2 ${BACKUPKERNELDIR}/\2," | \ + xargs -n 2 cp -pl + + # Re-enable patchname expansion. + set +f +} + # Install new files install_from_index () { # First pass: Do everything apart from setting file flags. We @@ -2575,6 +2732,9 @@ install_files () { grep -E '^/boot/' $1/INDEX-OLD > INDEX-OLD grep -E '^/boot/' $1/INDEX-NEW > INDEX-NEW + # Backup current kernel before installing a new one + backup_kernel || return 1 + # Install new files install_from_index INDEX-NEW || return 1 |