148ffe56aSColin Percival#!/bin/sh 248ffe56aSColin Percival 348ffe56aSColin Percival#- 41de7b4b8SPedro F. Giffuni# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 51de7b4b8SPedro F. Giffuni# 62328d598SColin Percival# Copyright 2004-2007 Colin Percival 748ffe56aSColin Percival# All rights reserved 848ffe56aSColin Percival# 948ffe56aSColin Percival# Redistribution and use in source and binary forms, with or without 1048ffe56aSColin Percival# modification, are permitted providing that the following conditions 1148ffe56aSColin Percival# are met: 1248ffe56aSColin Percival# 1. Redistributions of source code must retain the above copyright 1348ffe56aSColin Percival# notice, this list of conditions and the following disclaimer. 1448ffe56aSColin Percival# 2. Redistributions in binary form must reproduce the above copyright 1548ffe56aSColin Percival# notice, this list of conditions and the following disclaimer in the 1648ffe56aSColin Percival# documentation and/or other materials provided with the distribution. 1748ffe56aSColin Percival# 1848ffe56aSColin Percival# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1948ffe56aSColin Percival# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2048ffe56aSColin Percival# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2148ffe56aSColin Percival# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 2248ffe56aSColin Percival# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2348ffe56aSColin Percival# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2448ffe56aSColin Percival# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2548ffe56aSColin Percival# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2648ffe56aSColin Percival# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2748ffe56aSColin Percival# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2848ffe56aSColin Percival# POSSIBILITY OF SUCH DAMAGE. 2948ffe56aSColin Percival 3048ffe56aSColin Percival# $FreeBSD$ 3148ffe56aSColin Percival 3248ffe56aSColin Percival#### Usage function -- called from command-line handling code. 3348ffe56aSColin Percival 3448ffe56aSColin Percival# Usage instructions. Options not listed: 3548ffe56aSColin Percival# --debug -- don't filter output from utilities 3648ffe56aSColin Percival# --no-stats -- don't show progress statistics while fetching files 3748ffe56aSColin Percivalusage () { 3848ffe56aSColin Percival cat <<EOF 3948ffe56aSColin Percivalusage: `basename $0` [options] command ... [path] 4048ffe56aSColin Percival 4148ffe56aSColin PercivalOptions: 4248ffe56aSColin Percival -b basedir -- Operate on a system mounted at basedir 4348ffe56aSColin Percival (default: /) 4448ffe56aSColin Percival -d workdir -- Store working files in workdir 4548ffe56aSColin Percival (default: /var/db/freebsd-update/) 4648ffe56aSColin Percival -f conffile -- Read configuration options from conffile 4748ffe56aSColin Percival (default: /etc/freebsd-update.conf) 488935f242SAllan Jude -F -- Force a fetch operation to proceed 4948ffe56aSColin Percival -k KEY -- Trust an RSA key with SHA256 hash of KEY 50dd917c79SGleb Smirnoff -r release -- Target for upgrade (e.g., 11.1-RELEASE) 5148ffe56aSColin Percival -s server -- Server from which to fetch updates 5248ffe56aSColin Percival (default: update.FreeBSD.org) 5348ffe56aSColin Percival -t address -- Mail output of cron command, if any, to address 5448ffe56aSColin Percival (default: root) 558935f242SAllan Jude --not-running-from-cron 568935f242SAllan Jude -- Run without a tty, for use by automated tools 57b39ce43eSColin Percival --currently-running release 58b39ce43eSColin Percival -- Update as if currently running this release 5948ffe56aSColin PercivalCommands: 6048ffe56aSColin Percival fetch -- Fetch updates from server 6148ffe56aSColin Percival cron -- Sleep rand(3600) seconds, fetch updates, and send an 6248ffe56aSColin Percival email if updates were found 63db6b0a61SColin Percival upgrade -- Fetch upgrades to FreeBSD version specified via -r option 64db6b0a61SColin Percival install -- Install downloaded updates or upgrades 6548ffe56aSColin Percival rollback -- Uninstall most recently installed updates 6608e23beeSColin Percival IDS -- Compare the system against an index of "known good" files. 6748ffe56aSColin PercivalEOF 6848ffe56aSColin Percival exit 0 6948ffe56aSColin Percival} 7048ffe56aSColin Percival 7148ffe56aSColin Percival#### Configuration processing functions 7248ffe56aSColin Percival 7348ffe56aSColin Percival#- 7448ffe56aSColin Percival# Configuration options are set in the following order of priority: 7548ffe56aSColin Percival# 1. Command line options 7648ffe56aSColin Percival# 2. Configuration file options 7748ffe56aSColin Percival# 3. Default options 7848ffe56aSColin Percival# In addition, certain options (e.g., IgnorePaths) can be specified multiple 7948ffe56aSColin Percival# times and (as long as these are all in the same place, e.g., inside the 8048ffe56aSColin Percival# configuration file) they will accumulate. Finally, because the path to the 8148ffe56aSColin Percival# configuration file can be specified at the command line, the entire command 8248ffe56aSColin Percival# line must be processed before we start reading the configuration file. 8348ffe56aSColin Percival# 8448ffe56aSColin Percival# Sound like a mess? It is. Here's how we handle this: 8548ffe56aSColin Percival# 1. Initialize CONFFILE and all the options to "". 8648ffe56aSColin Percival# 2. Process the command line. Throw an error if a non-accumulating option 8748ffe56aSColin Percival# is specified twice. 8848ffe56aSColin Percival# 3. If CONFFILE is "", set CONFFILE to /etc/freebsd-update.conf . 8948ffe56aSColin Percival# 4. For all the configuration options X, set X_saved to X. 9048ffe56aSColin Percival# 5. Initialize all the options to "". 9148ffe56aSColin Percival# 6. Read CONFFILE line by line, parsing options. 9248ffe56aSColin Percival# 7. For each configuration option X, set X to X_saved iff X_saved is not "". 9348ffe56aSColin Percival# 8. Repeat steps 4-7, except setting options to their default values at (6). 9448ffe56aSColin Percival 9548ffe56aSColin PercivalCONFIGOPTIONS="KEYPRINT WORKDIR SERVERNAME MAILTO ALLOWADD ALLOWDELETE 9648ffe56aSColin Percival KEEPMODIFIEDMETADATA COMPONENTS IGNOREPATHS UPDATEIFUNMODIFIED 9708e23beeSColin Percival BASEDIR VERBOSELEVEL TARGETRELEASE STRICTCOMPONENTS MERGECHANGES 9823d827efSSimon L. B. Nielsen IDSIGNOREPATHS BACKUPKERNEL BACKUPKERNELDIR BACKUPKERNELSYMBOLFILES" 9948ffe56aSColin Percival 10048ffe56aSColin Percival# Set all the configuration options to "". 10148ffe56aSColin Percivalnullconfig () { 10248ffe56aSColin Percival for X in ${CONFIGOPTIONS}; do 10348ffe56aSColin Percival eval ${X}="" 10448ffe56aSColin Percival done 10548ffe56aSColin Percival} 10648ffe56aSColin Percival 10748ffe56aSColin Percival# For each configuration option X, set X_saved to X. 10848ffe56aSColin Percivalsaveconfig () { 10948ffe56aSColin Percival for X in ${CONFIGOPTIONS}; do 11048ffe56aSColin Percival eval ${X}_saved=\$${X} 11148ffe56aSColin Percival done 11248ffe56aSColin Percival} 11348ffe56aSColin Percival 11448ffe56aSColin Percival# For each configuration option X, set X to X_saved if X_saved is not "". 11548ffe56aSColin Percivalmergeconfig () { 11648ffe56aSColin Percival for X in ${CONFIGOPTIONS}; do 11748ffe56aSColin Percival eval _=\$${X}_saved 11848ffe56aSColin Percival if ! [ -z "${_}" ]; then 11948ffe56aSColin Percival eval ${X}=\$${X}_saved 12048ffe56aSColin Percival fi 12148ffe56aSColin Percival done 12248ffe56aSColin Percival} 12348ffe56aSColin Percival 12448ffe56aSColin Percival# Set the trusted keyprint. 12548ffe56aSColin Percivalconfig_KeyPrint () { 12648ffe56aSColin Percival if [ -z ${KEYPRINT} ]; then 12748ffe56aSColin Percival KEYPRINT=$1 12848ffe56aSColin Percival else 12948ffe56aSColin Percival return 1 13048ffe56aSColin Percival fi 13148ffe56aSColin Percival} 13248ffe56aSColin Percival 13348ffe56aSColin Percival# Set the working directory. 13448ffe56aSColin Percivalconfig_WorkDir () { 13548ffe56aSColin Percival if [ -z ${WORKDIR} ]; then 13648ffe56aSColin Percival WORKDIR=$1 13748ffe56aSColin Percival else 13848ffe56aSColin Percival return 1 13948ffe56aSColin Percival fi 14048ffe56aSColin Percival} 14148ffe56aSColin Percival 14248ffe56aSColin Percival# Set the name of the server (pool) from which to fetch updates 14348ffe56aSColin Percivalconfig_ServerName () { 14448ffe56aSColin Percival if [ -z ${SERVERNAME} ]; then 14548ffe56aSColin Percival SERVERNAME=$1 14648ffe56aSColin Percival else 14748ffe56aSColin Percival return 1 14848ffe56aSColin Percival fi 14948ffe56aSColin Percival} 15048ffe56aSColin Percival 15148ffe56aSColin Percival# Set the address to which 'cron' output will be mailed. 15248ffe56aSColin Percivalconfig_MailTo () { 15348ffe56aSColin Percival if [ -z ${MAILTO} ]; then 15448ffe56aSColin Percival MAILTO=$1 15548ffe56aSColin Percival else 15648ffe56aSColin Percival return 1 15748ffe56aSColin Percival fi 15848ffe56aSColin Percival} 15948ffe56aSColin Percival 16048ffe56aSColin Percival# Set whether FreeBSD Update is allowed to add files (or directories, or 16148ffe56aSColin Percival# symlinks) which did not previously exist. 16248ffe56aSColin Percivalconfig_AllowAdd () { 16348ffe56aSColin Percival if [ -z ${ALLOWADD} ]; then 16448ffe56aSColin Percival case $1 in 16548ffe56aSColin Percival [Yy][Ee][Ss]) 16648ffe56aSColin Percival ALLOWADD=yes 16748ffe56aSColin Percival ;; 16848ffe56aSColin Percival [Nn][Oo]) 16948ffe56aSColin Percival ALLOWADD=no 17048ffe56aSColin Percival ;; 17148ffe56aSColin Percival *) 17248ffe56aSColin Percival return 1 17348ffe56aSColin Percival ;; 17448ffe56aSColin Percival esac 17548ffe56aSColin Percival else 17648ffe56aSColin Percival return 1 17748ffe56aSColin Percival fi 17848ffe56aSColin Percival} 17948ffe56aSColin Percival 18048ffe56aSColin Percival# Set whether FreeBSD Update is allowed to remove files/directories/symlinks. 18148ffe56aSColin Percivalconfig_AllowDelete () { 18248ffe56aSColin Percival if [ -z ${ALLOWDELETE} ]; then 18348ffe56aSColin Percival case $1 in 18448ffe56aSColin Percival [Yy][Ee][Ss]) 18548ffe56aSColin Percival ALLOWDELETE=yes 18648ffe56aSColin Percival ;; 18748ffe56aSColin Percival [Nn][Oo]) 18848ffe56aSColin Percival ALLOWDELETE=no 18948ffe56aSColin Percival ;; 19048ffe56aSColin Percival *) 19148ffe56aSColin Percival return 1 19248ffe56aSColin Percival ;; 19348ffe56aSColin Percival esac 19448ffe56aSColin Percival else 19548ffe56aSColin Percival return 1 19648ffe56aSColin Percival fi 19748ffe56aSColin Percival} 19848ffe56aSColin Percival 19948ffe56aSColin Percival# Set whether FreeBSD Update should keep existing inode ownership, 20048ffe56aSColin Percival# permissions, and flags, in the event that they have been modified locally 20148ffe56aSColin Percival# after the release. 20248ffe56aSColin Percivalconfig_KeepModifiedMetadata () { 20348ffe56aSColin Percival if [ -z ${KEEPMODIFIEDMETADATA} ]; then 20448ffe56aSColin Percival case $1 in 20548ffe56aSColin Percival [Yy][Ee][Ss]) 20648ffe56aSColin Percival KEEPMODIFIEDMETADATA=yes 20748ffe56aSColin Percival ;; 20848ffe56aSColin Percival [Nn][Oo]) 20948ffe56aSColin Percival KEEPMODIFIEDMETADATA=no 21048ffe56aSColin Percival ;; 21148ffe56aSColin Percival *) 21248ffe56aSColin Percival return 1 21348ffe56aSColin Percival ;; 21448ffe56aSColin Percival esac 21548ffe56aSColin Percival else 21648ffe56aSColin Percival return 1 21748ffe56aSColin Percival fi 21848ffe56aSColin Percival} 21948ffe56aSColin Percival 22048ffe56aSColin Percival# Add to the list of components which should be kept updated. 22148ffe56aSColin Percivalconfig_Components () { 22248ffe56aSColin Percival for C in $@; do 2235a74378cSXin LI if [ "$C" = "src" ]; then 224cfd9be9cSEd Maste if [ -e "${BASEDIR}/usr/src/COPYRIGHT" ]; then 22548ffe56aSColin Percival COMPONENTS="${COMPONENTS} ${C}" 2265a74378cSXin LI else 2275a74378cSXin LI echo "src component not installed, skipped" 2285a74378cSXin LI fi 2295a74378cSXin LI else 2305a74378cSXin LI COMPONENTS="${COMPONENTS} ${C}" 2315a74378cSXin LI fi 23248ffe56aSColin Percival done 23348ffe56aSColin Percival} 23448ffe56aSColin Percival 23548ffe56aSColin Percival# Add to the list of paths under which updates will be ignored. 23648ffe56aSColin Percivalconfig_IgnorePaths () { 23748ffe56aSColin Percival for C in $@; do 23848ffe56aSColin Percival IGNOREPATHS="${IGNOREPATHS} ${C}" 23948ffe56aSColin Percival done 24048ffe56aSColin Percival} 24148ffe56aSColin Percival 24208e23beeSColin Percival# Add to the list of paths which IDS should ignore. 24308e23beeSColin Percivalconfig_IDSIgnorePaths () { 24408e23beeSColin Percival for C in $@; do 24508e23beeSColin Percival IDSIGNOREPATHS="${IDSIGNOREPATHS} ${C}" 24608e23beeSColin Percival done 24708e23beeSColin Percival} 24808e23beeSColin Percival 24948ffe56aSColin Percival# Add to the list of paths within which updates will be performed only if the 25048ffe56aSColin Percival# file on disk has not been modified locally. 25148ffe56aSColin Percivalconfig_UpdateIfUnmodified () { 25248ffe56aSColin Percival for C in $@; do 25348ffe56aSColin Percival UPDATEIFUNMODIFIED="${UPDATEIFUNMODIFIED} ${C}" 25448ffe56aSColin Percival done 25548ffe56aSColin Percival} 25648ffe56aSColin Percival 257db6b0a61SColin Percival# Add to the list of paths within which updates to text files will be merged 258db6b0a61SColin Percival# instead of overwritten. 259db6b0a61SColin Percivalconfig_MergeChanges () { 260db6b0a61SColin Percival for C in $@; do 261db6b0a61SColin Percival MERGECHANGES="${MERGECHANGES} ${C}" 262db6b0a61SColin Percival done 263db6b0a61SColin Percival} 264db6b0a61SColin Percival 26548ffe56aSColin Percival# Work on a FreeBSD installation mounted under $1 26648ffe56aSColin Percivalconfig_BaseDir () { 26748ffe56aSColin Percival if [ -z ${BASEDIR} ]; then 26848ffe56aSColin Percival BASEDIR=$1 26948ffe56aSColin Percival else 27048ffe56aSColin Percival return 1 27148ffe56aSColin Percival fi 27248ffe56aSColin Percival} 27348ffe56aSColin Percival 274db6b0a61SColin Percival# When fetching upgrades, should we assume the user wants exactly the 275db6b0a61SColin Percival# components listed in COMPONENTS, rather than trying to guess based on 276db6b0a61SColin Percival# what's currently installed? 277db6b0a61SColin Percivalconfig_StrictComponents () { 278db6b0a61SColin Percival if [ -z ${STRICTCOMPONENTS} ]; then 279db6b0a61SColin Percival case $1 in 280db6b0a61SColin Percival [Yy][Ee][Ss]) 281db6b0a61SColin Percival STRICTCOMPONENTS=yes 282db6b0a61SColin Percival ;; 283db6b0a61SColin Percival [Nn][Oo]) 284db6b0a61SColin Percival STRICTCOMPONENTS=no 285db6b0a61SColin Percival ;; 286db6b0a61SColin Percival *) 287db6b0a61SColin Percival return 1 288db6b0a61SColin Percival ;; 289db6b0a61SColin Percival esac 290db6b0a61SColin Percival else 291db6b0a61SColin Percival return 1 292db6b0a61SColin Percival fi 293db6b0a61SColin Percival} 294db6b0a61SColin Percival 295db6b0a61SColin Percival# Upgrade to FreeBSD $1 296db6b0a61SColin Percivalconfig_TargetRelease () { 297db6b0a61SColin Percival if [ -z ${TARGETRELEASE} ]; then 298db6b0a61SColin Percival TARGETRELEASE=$1 299db6b0a61SColin Percival else 300db6b0a61SColin Percival return 1 301db6b0a61SColin Percival fi 302d23dc1eeSColin Percival if echo ${TARGETRELEASE} | grep -qE '^[0-9.]+$'; then 303d23dc1eeSColin Percival TARGETRELEASE="${TARGETRELEASE}-RELEASE" 304d23dc1eeSColin Percival fi 305db6b0a61SColin Percival} 306db6b0a61SColin Percival 3070d5c5243SEd Maste# Pretend current release is FreeBSD $1 3080d5c5243SEd Masteconfig_SourceRelease () { 3090d5c5243SEd Maste UNAME_r=$1 3100d5c5243SEd Maste if echo ${UNAME_r} | grep -qE '^[0-9.]+$'; then 3110d5c5243SEd Maste UNAME_r="${UNAME_r}-RELEASE" 3120d5c5243SEd Maste fi 313b958d4b2SEd Maste export UNAME_r 3140d5c5243SEd Maste} 3150d5c5243SEd Maste 31648ffe56aSColin Percival# Define what happens to output of utilities 31748ffe56aSColin Percivalconfig_VerboseLevel () { 31848ffe56aSColin Percival if [ -z ${VERBOSELEVEL} ]; then 31948ffe56aSColin Percival case $1 in 32048ffe56aSColin Percival [Dd][Ee][Bb][Uu][Gg]) 32148ffe56aSColin Percival VERBOSELEVEL=debug 32248ffe56aSColin Percival ;; 32348ffe56aSColin Percival [Nn][Oo][Ss][Tt][Aa][Tt][Ss]) 32448ffe56aSColin Percival VERBOSELEVEL=nostats 32548ffe56aSColin Percival ;; 32648ffe56aSColin Percival [Ss][Tt][Aa][Tt][Ss]) 32748ffe56aSColin Percival VERBOSELEVEL=stats 32848ffe56aSColin Percival ;; 32948ffe56aSColin Percival *) 33048ffe56aSColin Percival return 1 33148ffe56aSColin Percival ;; 33248ffe56aSColin Percival esac 33348ffe56aSColin Percival else 33448ffe56aSColin Percival return 1 33548ffe56aSColin Percival fi 33648ffe56aSColin Percival} 33748ffe56aSColin Percival 33823d827efSSimon L. B. Nielsenconfig_BackupKernel () { 33923d827efSSimon L. B. Nielsen if [ -z ${BACKUPKERNEL} ]; then 34023d827efSSimon L. B. Nielsen case $1 in 34123d827efSSimon L. B. Nielsen [Yy][Ee][Ss]) 34223d827efSSimon L. B. Nielsen BACKUPKERNEL=yes 34323d827efSSimon L. B. Nielsen ;; 34423d827efSSimon L. B. Nielsen [Nn][Oo]) 34523d827efSSimon L. B. Nielsen BACKUPKERNEL=no 34623d827efSSimon L. B. Nielsen ;; 34723d827efSSimon L. B. Nielsen *) 34823d827efSSimon L. B. Nielsen return 1 34923d827efSSimon L. B. Nielsen ;; 35023d827efSSimon L. B. Nielsen esac 35123d827efSSimon L. B. Nielsen else 35223d827efSSimon L. B. Nielsen return 1 35323d827efSSimon L. B. Nielsen fi 35423d827efSSimon L. B. Nielsen} 35523d827efSSimon L. B. Nielsen 35623d827efSSimon L. B. Nielsenconfig_BackupKernelDir () { 35723d827efSSimon L. B. Nielsen if [ -z ${BACKUPKERNELDIR} ]; then 35823d827efSSimon L. B. Nielsen if [ -z "$1" ]; then 35923d827efSSimon L. B. Nielsen echo "BackupKernelDir set to empty dir" 36023d827efSSimon L. B. Nielsen return 1 36123d827efSSimon L. B. Nielsen fi 36223d827efSSimon L. B. Nielsen 36323d827efSSimon L. B. Nielsen # We check for some paths which would be extremely odd 36423d827efSSimon L. B. Nielsen # to use, but which could cause a lot of problems if 36523d827efSSimon L. B. Nielsen # used. 36623d827efSSimon L. B. Nielsen case $1 in 36723d827efSSimon L. B. Nielsen /|/bin|/boot|/etc|/lib|/libexec|/sbin|/usr|/var) 36823d827efSSimon L. B. Nielsen echo "BackupKernelDir set to invalid path $1" 36923d827efSSimon L. B. Nielsen return 1 37023d827efSSimon L. B. Nielsen ;; 37123d827efSSimon L. B. Nielsen /*) 37223d827efSSimon L. B. Nielsen BACKUPKERNELDIR=$1 37323d827efSSimon L. B. Nielsen ;; 37423d827efSSimon L. B. Nielsen *) 37523d827efSSimon L. B. Nielsen echo "BackupKernelDir ($1) is not an absolute path" 37623d827efSSimon L. B. Nielsen return 1 37723d827efSSimon L. B. Nielsen ;; 37823d827efSSimon L. B. Nielsen esac 37923d827efSSimon L. B. Nielsen else 38023d827efSSimon L. B. Nielsen return 1 38123d827efSSimon L. B. Nielsen fi 38223d827efSSimon L. B. Nielsen} 38323d827efSSimon L. B. Nielsen 38423d827efSSimon L. B. Nielsenconfig_BackupKernelSymbolFiles () { 38523d827efSSimon L. B. Nielsen if [ -z ${BACKUPKERNELSYMBOLFILES} ]; then 38623d827efSSimon L. B. Nielsen case $1 in 38723d827efSSimon L. B. Nielsen [Yy][Ee][Ss]) 38823d827efSSimon L. B. Nielsen BACKUPKERNELSYMBOLFILES=yes 38923d827efSSimon L. B. Nielsen ;; 39023d827efSSimon L. B. Nielsen [Nn][Oo]) 39123d827efSSimon L. B. Nielsen BACKUPKERNELSYMBOLFILES=no 39223d827efSSimon L. B. Nielsen ;; 39323d827efSSimon L. B. Nielsen *) 39423d827efSSimon L. B. Nielsen return 1 39523d827efSSimon L. B. Nielsen ;; 39623d827efSSimon L. B. Nielsen esac 39723d827efSSimon L. B. Nielsen else 39823d827efSSimon L. B. Nielsen return 1 39923d827efSSimon L. B. Nielsen fi 40023d827efSSimon L. B. Nielsen} 40123d827efSSimon L. B. Nielsen 40248ffe56aSColin Percival# Handle one line of configuration 40348ffe56aSColin Percivalconfigline () { 40448ffe56aSColin Percival if [ $# -eq 0 ]; then 40548ffe56aSColin Percival return 40648ffe56aSColin Percival fi 40748ffe56aSColin Percival 40848ffe56aSColin Percival OPT=$1 40948ffe56aSColin Percival shift 41048ffe56aSColin Percival config_${OPT} $@ 41148ffe56aSColin Percival} 41248ffe56aSColin Percival 41348ffe56aSColin Percival#### Parameter handling functions. 41448ffe56aSColin Percival 41548ffe56aSColin Percival# Initialize parameters to null, just in case they're 41648ffe56aSColin Percival# set in the environment. 41748ffe56aSColin Percivalinit_params () { 41848ffe56aSColin Percival # Configration settings 41948ffe56aSColin Percival nullconfig 42048ffe56aSColin Percival 42148ffe56aSColin Percival # No configuration file set yet 42248ffe56aSColin Percival CONFFILE="" 42348ffe56aSColin Percival 42448ffe56aSColin Percival # No commands specified yet 42548ffe56aSColin Percival COMMANDS="" 4268935f242SAllan Jude 4278935f242SAllan Jude # Force fetch to proceed 4288935f242SAllan Jude FORCEFETCH=0 4298935f242SAllan Jude 4308935f242SAllan Jude # Run without a TTY 4318935f242SAllan Jude NOTTYOK=0 43233bd05c3SGuangyuan Yang 43333bd05c3SGuangyuan Yang # Fetched first in a chain of commands 43433bd05c3SGuangyuan Yang ISFETCHED=0 43548ffe56aSColin Percival} 43648ffe56aSColin Percival 43748ffe56aSColin Percival# Parse the command line 43848ffe56aSColin Percivalparse_cmdline () { 43948ffe56aSColin Percival while [ $# -gt 0 ]; do 44048ffe56aSColin Percival case "$1" in 44148ffe56aSColin Percival # Location of configuration file 44248ffe56aSColin Percival -f) 44348ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi 44448ffe56aSColin Percival if [ ! -z "${CONFFILE}" ]; then usage; fi 44548ffe56aSColin Percival shift; CONFFILE="$1" 44648ffe56aSColin Percival ;; 4478935f242SAllan Jude -F) 4488935f242SAllan Jude FORCEFETCH=1 4498935f242SAllan Jude ;; 4508935f242SAllan Jude --not-running-from-cron) 4518935f242SAllan Jude NOTTYOK=1 4528935f242SAllan Jude ;; 453b39ce43eSColin Percival --currently-running) 4540d5c5243SEd Maste shift 4550d5c5243SEd Maste config_SourceRelease $1 || usage 456b39ce43eSColin Percival ;; 45748ffe56aSColin Percival 45848ffe56aSColin Percival # Configuration file equivalents 45948ffe56aSColin Percival -b) 46048ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 46148ffe56aSColin Percival config_BaseDir $1 || usage 46248ffe56aSColin Percival ;; 46348ffe56aSColin Percival -d) 46448ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 46548ffe56aSColin Percival config_WorkDir $1 || usage 46648ffe56aSColin Percival ;; 46748ffe56aSColin Percival -k) 46848ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 46948ffe56aSColin Percival config_KeyPrint $1 || usage 47048ffe56aSColin Percival ;; 47148ffe56aSColin Percival -s) 47248ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 47348ffe56aSColin Percival config_ServerName $1 || usage 47448ffe56aSColin Percival ;; 475db6b0a61SColin Percival -r) 476db6b0a61SColin Percival if [ $# -eq 1 ]; then usage; fi; shift 477db6b0a61SColin Percival config_TargetRelease $1 || usage 478db6b0a61SColin Percival ;; 47948ffe56aSColin Percival -t) 48048ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 48148ffe56aSColin Percival config_MailTo $1 || usage 48248ffe56aSColin Percival ;; 48348ffe56aSColin Percival -v) 48448ffe56aSColin Percival if [ $# -eq 1 ]; then usage; fi; shift 48548ffe56aSColin Percival config_VerboseLevel $1 || usage 48648ffe56aSColin Percival ;; 48748ffe56aSColin Percival 48848ffe56aSColin Percival # Aliases for "-v debug" and "-v nostats" 48948ffe56aSColin Percival --debug) 49048ffe56aSColin Percival config_VerboseLevel debug || usage 49148ffe56aSColin Percival ;; 49248ffe56aSColin Percival --no-stats) 49348ffe56aSColin Percival config_VerboseLevel nostats || usage 49448ffe56aSColin Percival ;; 49548ffe56aSColin Percival 49648ffe56aSColin Percival # Commands 49708e23beeSColin Percival cron | fetch | upgrade | install | rollback | IDS) 49848ffe56aSColin Percival COMMANDS="${COMMANDS} $1" 49948ffe56aSColin Percival ;; 50048ffe56aSColin Percival 50148ffe56aSColin Percival # Anything else is an error 50248ffe56aSColin Percival *) 50348ffe56aSColin Percival usage 50448ffe56aSColin Percival ;; 50548ffe56aSColin Percival esac 50648ffe56aSColin Percival shift 50748ffe56aSColin Percival done 50848ffe56aSColin Percival 50948ffe56aSColin Percival # Make sure we have at least one command 51048ffe56aSColin Percival if [ -z "${COMMANDS}" ]; then 51148ffe56aSColin Percival usage 51248ffe56aSColin Percival fi 51348ffe56aSColin Percival} 51448ffe56aSColin Percival 51548ffe56aSColin Percival# Parse the configuration file 51648ffe56aSColin Percivalparse_conffile () { 51748ffe56aSColin Percival # If a configuration file was specified on the command line, check 51848ffe56aSColin Percival # that it exists and is readable. 51948ffe56aSColin Percival if [ ! -z "${CONFFILE}" ] && [ ! -r "${CONFFILE}" ]; then 52048ffe56aSColin Percival echo -n "File does not exist " 52148ffe56aSColin Percival echo -n "or is not readable: " 52248ffe56aSColin Percival echo ${CONFFILE} 52348ffe56aSColin Percival exit 1 52448ffe56aSColin Percival fi 52548ffe56aSColin Percival 52648ffe56aSColin Percival # If a configuration file was not specified on the command line, 52748ffe56aSColin Percival # use the default configuration file path. If that default does 52848ffe56aSColin Percival # not exist, give up looking for any configuration. 52948ffe56aSColin Percival if [ -z "${CONFFILE}" ]; then 53048ffe56aSColin Percival CONFFILE="/etc/freebsd-update.conf" 53148ffe56aSColin Percival if [ ! -r "${CONFFILE}" ]; then 53248ffe56aSColin Percival return 53348ffe56aSColin Percival fi 53448ffe56aSColin Percival fi 53548ffe56aSColin Percival 53648ffe56aSColin Percival # Save the configuration options specified on the command line, and 53748ffe56aSColin Percival # clear all the options in preparation for reading the config file. 53848ffe56aSColin Percival saveconfig 53948ffe56aSColin Percival nullconfig 54048ffe56aSColin Percival 54148ffe56aSColin Percival # Read the configuration file. Anything after the first '#' is 54248ffe56aSColin Percival # ignored, and any blank lines are ignored. 54348ffe56aSColin Percival L=0 54448ffe56aSColin Percival while read LINE; do 54548ffe56aSColin Percival L=$(($L + 1)) 54648ffe56aSColin Percival LINEX=`echo "${LINE}" | cut -f 1 -d '#'` 54748ffe56aSColin Percival if ! configline ${LINEX}; then 54848ffe56aSColin Percival echo "Error processing configuration file, line $L:" 54948ffe56aSColin Percival echo "==> ${LINE}" 55048ffe56aSColin Percival exit 1 55148ffe56aSColin Percival fi 55248ffe56aSColin Percival done < ${CONFFILE} 55348ffe56aSColin Percival 55448ffe56aSColin Percival # Merge the settings read from the configuration file with those 55548ffe56aSColin Percival # provided at the command line. 55648ffe56aSColin Percival mergeconfig 55748ffe56aSColin Percival} 55848ffe56aSColin Percival 55948ffe56aSColin Percival# Provide some default parameters 56048ffe56aSColin Percivaldefault_params () { 56148ffe56aSColin Percival # Save any parameters already configured, and clear the slate 56248ffe56aSColin Percival saveconfig 56348ffe56aSColin Percival nullconfig 56448ffe56aSColin Percival 56548ffe56aSColin Percival # Default configurations 56648ffe56aSColin Percival config_WorkDir /var/db/freebsd-update 56748ffe56aSColin Percival config_MailTo root 56848ffe56aSColin Percival config_AllowAdd yes 56948ffe56aSColin Percival config_AllowDelete yes 57048ffe56aSColin Percival config_KeepModifiedMetadata yes 57148ffe56aSColin Percival config_BaseDir / 57248ffe56aSColin Percival config_VerboseLevel stats 573db6b0a61SColin Percival config_StrictComponents no 57423d827efSSimon L. B. Nielsen config_BackupKernel yes 57523d827efSSimon L. B. Nielsen config_BackupKernelDir /boot/kernel.old 57623d827efSSimon L. B. Nielsen config_BackupKernelSymbolFiles no 57748ffe56aSColin Percival 57848ffe56aSColin Percival # Merge these defaults into the earlier-configured settings 57948ffe56aSColin Percival mergeconfig 58048ffe56aSColin Percival} 58148ffe56aSColin Percival 58248ffe56aSColin Percival# Set utility output filtering options, based on ${VERBOSELEVEL} 58348ffe56aSColin Percivalfetch_setup_verboselevel () { 58448ffe56aSColin Percival case ${VERBOSELEVEL} in 58548ffe56aSColin Percival debug) 58648ffe56aSColin Percival QUIETREDIR="/dev/stderr" 58748ffe56aSColin Percival QUIETFLAG=" " 58848ffe56aSColin Percival STATSREDIR="/dev/stderr" 58948ffe56aSColin Percival DDSTATS=".." 59048ffe56aSColin Percival XARGST="-t" 59148ffe56aSColin Percival NDEBUG=" " 59248ffe56aSColin Percival ;; 59348ffe56aSColin Percival nostats) 59448ffe56aSColin Percival QUIETREDIR="" 59548ffe56aSColin Percival QUIETFLAG="" 59648ffe56aSColin Percival STATSREDIR="/dev/null" 59748ffe56aSColin Percival DDSTATS=".." 59848ffe56aSColin Percival XARGST="" 59948ffe56aSColin Percival NDEBUG="" 60048ffe56aSColin Percival ;; 60148ffe56aSColin Percival stats) 60248ffe56aSColin Percival QUIETREDIR="/dev/null" 60348ffe56aSColin Percival QUIETFLAG="-q" 60448ffe56aSColin Percival STATSREDIR="/dev/stdout" 60548ffe56aSColin Percival DDSTATS="" 60648ffe56aSColin Percival XARGST="" 60748ffe56aSColin Percival NDEBUG="-n" 60848ffe56aSColin Percival ;; 60948ffe56aSColin Percival esac 61048ffe56aSColin Percival} 61148ffe56aSColin Percival 61248ffe56aSColin Percival# Perform sanity checks and set some final parameters 61348ffe56aSColin Percival# in preparation for fetching files. Figure out which 61448ffe56aSColin Percival# set of updates should be downloaded: If the user is 61548ffe56aSColin Percival# running *-p[0-9]+, strip off the last part; if the 61648ffe56aSColin Percival# user is running -SECURITY, call it -RELEASE. Chdir 61748ffe56aSColin Percival# into the working directory. 618211f2ba0SColin Percivalfetchupgrade_check_params () { 61948ffe56aSColin Percival export HTTP_USER_AGENT="freebsd-update (${COMMAND}, `uname -r`)" 62048ffe56aSColin Percival 62148ffe56aSColin Percival _SERVERNAME_z=\ 62248ffe56aSColin Percival"SERVERNAME must be given via command line or configuration file." 62348ffe56aSColin Percival _KEYPRINT_z="Key must be given via -k option or configuration file." 62448ffe56aSColin Percival _KEYPRINT_bad="Invalid key fingerprint: " 62548ffe56aSColin Percival _WORKDIR_bad="Directory does not exist or is not writable: " 626f88076f0SMark Felder _WORKDIR_bad2="Directory is not on a persistent filesystem: " 62748ffe56aSColin Percival 62848ffe56aSColin Percival if [ -z "${SERVERNAME}" ]; then 62948ffe56aSColin Percival echo -n "`basename $0`: " 63048ffe56aSColin Percival echo "${_SERVERNAME_z}" 63148ffe56aSColin Percival exit 1 63248ffe56aSColin Percival fi 63348ffe56aSColin Percival if [ -z "${KEYPRINT}" ]; then 63448ffe56aSColin Percival echo -n "`basename $0`: " 63548ffe56aSColin Percival echo "${_KEYPRINT_z}" 63648ffe56aSColin Percival exit 1 63748ffe56aSColin Percival fi 63848ffe56aSColin Percival if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then 63948ffe56aSColin Percival echo -n "`basename $0`: " 64048ffe56aSColin Percival echo -n "${_KEYPRINT_bad}" 64148ffe56aSColin Percival echo ${KEYPRINT} 64248ffe56aSColin Percival exit 1 64348ffe56aSColin Percival fi 64448ffe56aSColin Percival if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then 64548ffe56aSColin Percival echo -n "`basename $0`: " 64648ffe56aSColin Percival echo -n "${_WORKDIR_bad}" 64748ffe56aSColin Percival echo ${WORKDIR} 64848ffe56aSColin Percival exit 1 64948ffe56aSColin Percival fi 650dfe9215bSMark Felder case `df -T ${WORKDIR}` in */dev/md[0-9]* | *tmpfs*) 651f88076f0SMark Felder echo -n "`basename $0`: " 652f88076f0SMark Felder echo -n "${_WORKDIR_bad2}" 653f88076f0SMark Felder echo ${WORKDIR} 654f88076f0SMark Felder exit 1 655dfe9215bSMark Felder ;; 656dfe9215bSMark Felder esac 657a2356430SColin Percival chmod 700 ${WORKDIR} 65848ffe56aSColin Percival cd ${WORKDIR} || exit 1 65948ffe56aSColin Percival 66048ffe56aSColin Percival # Generate release number. The s/SECURITY/RELEASE/ bit exists 66148ffe56aSColin Percival # to provide an upgrade path for FreeBSD Update 1.x users, since 66248ffe56aSColin Percival # the kernels provided by FreeBSD Update 1.x are always labelled 66348ffe56aSColin Percival # as X.Y-SECURITY. 66448ffe56aSColin Percival RELNUM=`uname -r | 66548ffe56aSColin Percival sed -E 's,-p[0-9]+,,' | 66648ffe56aSColin Percival sed -E 's,-SECURITY,-RELEASE,'` 66748ffe56aSColin Percival ARCH=`uname -m` 66848ffe56aSColin Percival FETCHDIR=${RELNUM}/${ARCH} 669db6b0a61SColin Percival PATCHDIR=${RELNUM}/${ARCH}/bp 67048ffe56aSColin Percival 6710d5c5243SEd Maste # Disallow upgrade from a version that is not `-RELEASE` 6720d5c5243SEd Maste if ! echo "${RELNUM}" | grep -qE -- "-RELEASE$"; then 6730d5c5243SEd Maste echo -n "`basename $0`: " 6740d5c5243SEd Maste cat <<- EOF 6750d5c5243SEd Maste Cannot upgrade from a version that is not a '-RELEASE' using `basename $0`. 6760d5c5243SEd Maste Instead, FreeBSD can be directly upgraded by source or upgraded to a 6770d5c5243SEd Maste RELEASE/RELENG version prior to running `basename $0`. 6780d5c5243SEd Maste EOF 6790d5c5243SEd Maste echo "System version: ${RELNUM}" 6800d5c5243SEd Maste exit 1 6810d5c5243SEd Maste fi 6820d5c5243SEd Maste 68348ffe56aSColin Percival # Figure out what directory contains the running kernel 68448ffe56aSColin Percival BOOTFILE=`sysctl -n kern.bootfile` 68548ffe56aSColin Percival KERNELDIR=${BOOTFILE%/kernel} 68648ffe56aSColin Percival if ! [ -d ${KERNELDIR} ]; then 68748ffe56aSColin Percival echo "Cannot identify running kernel" 68848ffe56aSColin Percival exit 1 68948ffe56aSColin Percival fi 69048ffe56aSColin Percival 6912c434b2cSColin Percival # Figure out what kernel configuration is running. We start with 6922c434b2cSColin Percival # the output of `uname -i`, and then make the following adjustments: 6932c434b2cSColin Percival # 1. Replace "SMP-GENERIC" with "SMP". Why the SMP kernel config 6942c434b2cSColin Percival # file says "ident SMP-GENERIC", I don't know... 6952c434b2cSColin Percival # 2. If the kernel claims to be GENERIC _and_ ${ARCH} is "amd64" 6962c434b2cSColin Percival # _and_ `sysctl kern.version` contains a line which ends "/SMP", then 6972c434b2cSColin Percival # we're running an SMP kernel. This mis-identification is a bug 6982c434b2cSColin Percival # which was fixed in 6.2-STABLE. 6992c434b2cSColin Percival KERNCONF=`uname -i` 7002c434b2cSColin Percival if [ ${KERNCONF} = "SMP-GENERIC" ]; then 7012c434b2cSColin Percival KERNCONF=SMP 7022c434b2cSColin Percival fi 7032c434b2cSColin Percival if [ ${KERNCONF} = "GENERIC" ] && [ ${ARCH} = "amd64" ]; then 7042c434b2cSColin Percival if sysctl kern.version | grep -qE '/SMP$'; then 7052c434b2cSColin Percival KERNCONF=SMP 7062c434b2cSColin Percival fi 7072c434b2cSColin Percival fi 7082c434b2cSColin Percival 70948ffe56aSColin Percival # Define some paths 71048ffe56aSColin Percival BSPATCH=/usr/bin/bspatch 71148ffe56aSColin Percival SHA256=/sbin/sha256 71248ffe56aSColin Percival PHTTPGET=/usr/libexec/phttpget 71348ffe56aSColin Percival 71448ffe56aSColin Percival # Set up variables relating to VERBOSELEVEL 71548ffe56aSColin Percival fetch_setup_verboselevel 71648ffe56aSColin Percival 71748ffe56aSColin Percival # Construct a unique name from ${BASEDIR} 71848ffe56aSColin Percival BDHASH=`echo ${BASEDIR} | sha256 -q` 71948ffe56aSColin Percival} 72048ffe56aSColin Percival 721211f2ba0SColin Percival# Perform sanity checks etc. before fetching updates. 722211f2ba0SColin Percivalfetch_check_params () { 723211f2ba0SColin Percival fetchupgrade_check_params 724211f2ba0SColin Percival 725211f2ba0SColin Percival if ! [ -z "${TARGETRELEASE}" ]; then 726211f2ba0SColin Percival echo -n "`basename $0`: " 727211f2ba0SColin Percival echo -n "-r option is meaningless with 'fetch' command. " 728211f2ba0SColin Percival echo "(Did you mean 'upgrade' instead?)" 729211f2ba0SColin Percival exit 1 730211f2ba0SColin Percival fi 7318935f242SAllan Jude 7328935f242SAllan Jude # Check that we have updates ready to install 7338bf2dcceSAllan Jude if [ -f ${BDHASH}-install/kerneldone -a $FORCEFETCH -eq 0 ]; then 7348935f242SAllan Jude echo "You have a partially completed upgrade pending" 7358935f242SAllan Jude echo "Run '$0 install' first." 7368935f242SAllan Jude echo "Run '$0 fetch -F' to proceed anyway." 7378935f242SAllan Jude exit 1 7388935f242SAllan Jude fi 739211f2ba0SColin Percival} 740211f2ba0SColin Percival 741db6b0a61SColin Percival# Perform sanity checks etc. before fetching upgrades. 742db6b0a61SColin Percivalupgrade_check_params () { 743211f2ba0SColin Percival fetchupgrade_check_params 744db6b0a61SColin Percival 745db6b0a61SColin Percival # Unless set otherwise, we're upgrading to the same kernel config. 746db6b0a61SColin Percival NKERNCONF=${KERNCONF} 747db6b0a61SColin Percival 748db6b0a61SColin Percival # We need TARGETRELEASE set 749db6b0a61SColin Percival _TARGETRELEASE_z="Release target must be specified via -r option." 750db6b0a61SColin Percival if [ -z "${TARGETRELEASE}" ]; then 751db6b0a61SColin Percival echo -n "`basename $0`: " 752db6b0a61SColin Percival echo "${_TARGETRELEASE_z}" 753db6b0a61SColin Percival exit 1 754db6b0a61SColin Percival fi 755db6b0a61SColin Percival 756db6b0a61SColin Percival # The target release should be != the current release. 757db6b0a61SColin Percival if [ "${TARGETRELEASE}" = "${RELNUM}" ]; then 758db6b0a61SColin Percival echo -n "`basename $0`: " 759db6b0a61SColin Percival echo "Cannot upgrade from ${RELNUM} to itself" 760db6b0a61SColin Percival exit 1 761db6b0a61SColin Percival fi 762db6b0a61SColin Percival 763db6b0a61SColin Percival # Turning off AllowAdd or AllowDelete is a bad idea for upgrades. 764db6b0a61SColin Percival if [ "${ALLOWADD}" = "no" ]; then 765db6b0a61SColin Percival echo -n "`basename $0`: " 766db6b0a61SColin Percival echo -n "WARNING: \"AllowAdd no\" is a bad idea " 767db6b0a61SColin Percival echo "when upgrading between releases." 768db6b0a61SColin Percival echo 769db6b0a61SColin Percival fi 770db6b0a61SColin Percival if [ "${ALLOWDELETE}" = "no" ]; then 771db6b0a61SColin Percival echo -n "`basename $0`: " 772db6b0a61SColin Percival echo -n "WARNING: \"AllowDelete no\" is a bad idea " 773db6b0a61SColin Percival echo "when upgrading between releases." 774db6b0a61SColin Percival echo 775db6b0a61SColin Percival fi 776db6b0a61SColin Percival 777db6b0a61SColin Percival # Set EDITOR to /usr/bin/vi if it isn't already set 778db6b0a61SColin Percival : ${EDITOR:='/usr/bin/vi'} 779db6b0a61SColin Percival} 780db6b0a61SColin Percival 78148ffe56aSColin Percival# Perform sanity checks and set some final parameters in 78248ffe56aSColin Percival# preparation for installing updates. 78348ffe56aSColin Percivalinstall_check_params () { 78448ffe56aSColin Percival # Check that we are root. All sorts of things won't work otherwise. 78548ffe56aSColin Percival if [ `id -u` != 0 ]; then 78648ffe56aSColin Percival echo "You must be root to run this." 78748ffe56aSColin Percival exit 1 78848ffe56aSColin Percival fi 78948ffe56aSColin Percival 7902328d598SColin Percival # Check that securelevel <= 0. Otherwise we can't update schg files. 7912328d598SColin Percival if [ `sysctl -n kern.securelevel` -gt 0 ]; then 7922328d598SColin Percival echo "Updates cannot be installed when the system securelevel" 7932328d598SColin Percival echo "is greater than zero." 7942328d598SColin Percival exit 1 7952328d598SColin Percival fi 7962328d598SColin Percival 79748ffe56aSColin Percival # Check that we have a working directory 79848ffe56aSColin Percival _WORKDIR_bad="Directory does not exist or is not writable: " 79948ffe56aSColin Percival if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then 80048ffe56aSColin Percival echo -n "`basename $0`: " 80148ffe56aSColin Percival echo -n "${_WORKDIR_bad}" 80248ffe56aSColin Percival echo ${WORKDIR} 80348ffe56aSColin Percival exit 1 80448ffe56aSColin Percival fi 80548ffe56aSColin Percival cd ${WORKDIR} || exit 1 80648ffe56aSColin Percival 80748ffe56aSColin Percival # Construct a unique name from ${BASEDIR} 80848ffe56aSColin Percival BDHASH=`echo ${BASEDIR} | sha256 -q` 80948ffe56aSColin Percival 81048ffe56aSColin Percival # Check that we have updates ready to install 81148ffe56aSColin Percival if ! [ -L ${BDHASH}-install ]; then 81248ffe56aSColin Percival echo "No updates are available to install." 81333bd05c3SGuangyuan Yang if [ $ISFETCHED -eq 0 ]; then 81448ffe56aSColin Percival echo "Run '$0 fetch' first." 81533bd05c3SGuangyuan Yang fi 81633bd05c3SGuangyuan Yang exit 0 81748ffe56aSColin Percival fi 81848ffe56aSColin Percival if ! [ -f ${BDHASH}-install/INDEX-OLD ] || 81948ffe56aSColin Percival ! [ -f ${BDHASH}-install/INDEX-NEW ]; then 82048ffe56aSColin Percival echo "Update manifest is corrupt -- this should never happen." 82148ffe56aSColin Percival echo "Re-run '$0 fetch'." 82248ffe56aSColin Percival exit 1 82348ffe56aSColin Percival fi 82423d827efSSimon L. B. Nielsen 82523d827efSSimon L. B. Nielsen # Figure out what directory contains the running kernel 82623d827efSSimon L. B. Nielsen BOOTFILE=`sysctl -n kern.bootfile` 82723d827efSSimon L. B. Nielsen KERNELDIR=${BOOTFILE%/kernel} 82823d827efSSimon L. B. Nielsen if ! [ -d ${KERNELDIR} ]; then 82923d827efSSimon L. B. Nielsen echo "Cannot identify running kernel" 83023d827efSSimon L. B. Nielsen exit 1 83123d827efSSimon L. B. Nielsen fi 83248ffe56aSColin Percival} 83348ffe56aSColin Percival 83448ffe56aSColin Percival# Perform sanity checks and set some final parameters in 83548ffe56aSColin Percival# preparation for UNinstalling updates. 83648ffe56aSColin Percivalrollback_check_params () { 83748ffe56aSColin Percival # Check that we are root. All sorts of things won't work otherwise. 83848ffe56aSColin Percival if [ `id -u` != 0 ]; then 83948ffe56aSColin Percival echo "You must be root to run this." 84048ffe56aSColin Percival exit 1 84148ffe56aSColin Percival fi 84248ffe56aSColin Percival 84348ffe56aSColin Percival # Check that we have a working directory 84448ffe56aSColin Percival _WORKDIR_bad="Directory does not exist or is not writable: " 84548ffe56aSColin Percival if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then 84648ffe56aSColin Percival echo -n "`basename $0`: " 84748ffe56aSColin Percival echo -n "${_WORKDIR_bad}" 84848ffe56aSColin Percival echo ${WORKDIR} 84948ffe56aSColin Percival exit 1 85048ffe56aSColin Percival fi 85148ffe56aSColin Percival cd ${WORKDIR} || exit 1 85248ffe56aSColin Percival 85348ffe56aSColin Percival # Construct a unique name from ${BASEDIR} 85448ffe56aSColin Percival BDHASH=`echo ${BASEDIR} | sha256 -q` 85548ffe56aSColin Percival 85648ffe56aSColin Percival # Check that we have updates ready to rollback 85748ffe56aSColin Percival if ! [ -L ${BDHASH}-rollback ]; then 85848ffe56aSColin Percival echo "No rollback directory found." 85948ffe56aSColin Percival exit 1 86048ffe56aSColin Percival fi 86148ffe56aSColin Percival if ! [ -f ${BDHASH}-rollback/INDEX-OLD ] || 86248ffe56aSColin Percival ! [ -f ${BDHASH}-rollback/INDEX-NEW ]; then 86348ffe56aSColin Percival echo "Update manifest is corrupt -- this should never happen." 86448ffe56aSColin Percival exit 1 86548ffe56aSColin Percival fi 86648ffe56aSColin Percival} 86748ffe56aSColin Percival 86808e23beeSColin Percival# Perform sanity checks and set some final parameters 86908e23beeSColin Percival# in preparation for comparing the system against the 87008e23beeSColin Percival# published index. Figure out which index we should 87108e23beeSColin Percival# compare against: If the user is running *-p[0-9]+, 87208e23beeSColin Percival# strip off the last part; if the user is running 87308e23beeSColin Percival# -SECURITY, call it -RELEASE. Chdir into the working 87408e23beeSColin Percival# directory. 87508e23beeSColin PercivalIDS_check_params () { 87608e23beeSColin Percival export HTTP_USER_AGENT="freebsd-update (${COMMAND}, `uname -r`)" 87708e23beeSColin Percival 87808e23beeSColin Percival _SERVERNAME_z=\ 87908e23beeSColin Percival"SERVERNAME must be given via command line or configuration file." 88008e23beeSColin Percival _KEYPRINT_z="Key must be given via -k option or configuration file." 88108e23beeSColin Percival _KEYPRINT_bad="Invalid key fingerprint: " 88208e23beeSColin Percival _WORKDIR_bad="Directory does not exist or is not writable: " 88308e23beeSColin Percival 88408e23beeSColin Percival if [ -z "${SERVERNAME}" ]; then 88508e23beeSColin Percival echo -n "`basename $0`: " 88608e23beeSColin Percival echo "${_SERVERNAME_z}" 88708e23beeSColin Percival exit 1 88808e23beeSColin Percival fi 88908e23beeSColin Percival if [ -z "${KEYPRINT}" ]; then 89008e23beeSColin Percival echo -n "`basename $0`: " 89108e23beeSColin Percival echo "${_KEYPRINT_z}" 89208e23beeSColin Percival exit 1 89308e23beeSColin Percival fi 89408e23beeSColin Percival if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then 89508e23beeSColin Percival echo -n "`basename $0`: " 89608e23beeSColin Percival echo -n "${_KEYPRINT_bad}" 89708e23beeSColin Percival echo ${KEYPRINT} 89808e23beeSColin Percival exit 1 89908e23beeSColin Percival fi 90008e23beeSColin Percival if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then 90108e23beeSColin Percival echo -n "`basename $0`: " 90208e23beeSColin Percival echo -n "${_WORKDIR_bad}" 90308e23beeSColin Percival echo ${WORKDIR} 90408e23beeSColin Percival exit 1 90508e23beeSColin Percival fi 90608e23beeSColin Percival cd ${WORKDIR} || exit 1 90708e23beeSColin Percival 90808e23beeSColin Percival # Generate release number. The s/SECURITY/RELEASE/ bit exists 90908e23beeSColin Percival # to provide an upgrade path for FreeBSD Update 1.x users, since 91008e23beeSColin Percival # the kernels provided by FreeBSD Update 1.x are always labelled 91108e23beeSColin Percival # as X.Y-SECURITY. 91208e23beeSColin Percival RELNUM=`uname -r | 91308e23beeSColin Percival sed -E 's,-p[0-9]+,,' | 91408e23beeSColin Percival sed -E 's,-SECURITY,-RELEASE,'` 91508e23beeSColin Percival ARCH=`uname -m` 91608e23beeSColin Percival FETCHDIR=${RELNUM}/${ARCH} 91708e23beeSColin Percival PATCHDIR=${RELNUM}/${ARCH}/bp 91808e23beeSColin Percival 91908e23beeSColin Percival # Figure out what directory contains the running kernel 92008e23beeSColin Percival BOOTFILE=`sysctl -n kern.bootfile` 92108e23beeSColin Percival KERNELDIR=${BOOTFILE%/kernel} 92208e23beeSColin Percival if ! [ -d ${KERNELDIR} ]; then 92308e23beeSColin Percival echo "Cannot identify running kernel" 92408e23beeSColin Percival exit 1 92508e23beeSColin Percival fi 92608e23beeSColin Percival 92708e23beeSColin Percival # Figure out what kernel configuration is running. We start with 92808e23beeSColin Percival # the output of `uname -i`, and then make the following adjustments: 92908e23beeSColin Percival # 1. Replace "SMP-GENERIC" with "SMP". Why the SMP kernel config 93008e23beeSColin Percival # file says "ident SMP-GENERIC", I don't know... 93108e23beeSColin Percival # 2. If the kernel claims to be GENERIC _and_ ${ARCH} is "amd64" 93208e23beeSColin Percival # _and_ `sysctl kern.version` contains a line which ends "/SMP", then 93308e23beeSColin Percival # we're running an SMP kernel. This mis-identification is a bug 93408e23beeSColin Percival # which was fixed in 6.2-STABLE. 93508e23beeSColin Percival KERNCONF=`uname -i` 93608e23beeSColin Percival if [ ${KERNCONF} = "SMP-GENERIC" ]; then 93708e23beeSColin Percival KERNCONF=SMP 93808e23beeSColin Percival fi 93908e23beeSColin Percival if [ ${KERNCONF} = "GENERIC" ] && [ ${ARCH} = "amd64" ]; then 94008e23beeSColin Percival if sysctl kern.version | grep -qE '/SMP$'; then 94108e23beeSColin Percival KERNCONF=SMP 94208e23beeSColin Percival fi 94308e23beeSColin Percival fi 94408e23beeSColin Percival 94508e23beeSColin Percival # Define some paths 94608e23beeSColin Percival SHA256=/sbin/sha256 94708e23beeSColin Percival PHTTPGET=/usr/libexec/phttpget 94808e23beeSColin Percival 94908e23beeSColin Percival # Set up variables relating to VERBOSELEVEL 95008e23beeSColin Percival fetch_setup_verboselevel 95108e23beeSColin Percival} 95208e23beeSColin Percival 95348ffe56aSColin Percival#### Core functionality -- the actual work gets done here 95448ffe56aSColin Percival 95548ffe56aSColin Percival# Use an SRV query to pick a server. If the SRV query doesn't provide 95648ffe56aSColin Percival# a useful answer, use the server name specified by the user. 95748ffe56aSColin Percival# Put another way... look up _http._tcp.${SERVERNAME} and pick a server 95848ffe56aSColin Percival# from that; or if no servers are returned, use ${SERVERNAME}. 95948ffe56aSColin Percival# This allows a user to specify "portsnap.freebsd.org" (in which case 96048ffe56aSColin Percival# portsnap will select one of the mirrors) or "portsnap5.tld.freebsd.org" 96148ffe56aSColin Percival# (in which case portsnap will use that particular server, since there 96248ffe56aSColin Percival# won't be an SRV entry for that name). 96348ffe56aSColin Percival# 96448ffe56aSColin Percival# We ignore the Port field, since we are always going to use port 80. 96548ffe56aSColin Percival 96648ffe56aSColin Percival# Fetch the mirror list, but do not pick a mirror yet. Returns 1 if 96748ffe56aSColin Percival# no mirrors are available for any reason. 96848ffe56aSColin Percivalfetch_pick_server_init () { 96948ffe56aSColin Percival : > serverlist_tried 97048ffe56aSColin Percival 97148ffe56aSColin Percival# Check that host(1) exists (i.e., that the system wasn't built with the 97248ffe56aSColin Percival# WITHOUT_BIND set) and don't try to find a mirror if it doesn't exist. 97348ffe56aSColin Percival if ! which -s host; then 97448ffe56aSColin Percival : > serverlist_full 97548ffe56aSColin Percival return 1 97648ffe56aSColin Percival fi 97748ffe56aSColin Percival 97848ffe56aSColin Percival echo -n "Looking up ${SERVERNAME} mirrors... " 97948ffe56aSColin Percival 98048ffe56aSColin Percival# Issue the SRV query and pull out the Priority, Weight, and Target fields. 98148ffe56aSColin Percival# BIND 9 prints "$name has SRV record ..." while BIND 8 prints 98248ffe56aSColin Percival# "$name server selection ..."; we allow either format. 98348ffe56aSColin Percival MLIST="_http._tcp.${SERVERNAME}" 98448ffe56aSColin Percival host -t srv "${MLIST}" | 985e7fd266eSColin Percival sed -nE "s/${MLIST} (has SRV record|server selection) //Ip" | 98648ffe56aSColin Percival cut -f 1,2,4 -d ' ' | 98748ffe56aSColin Percival sed -e 's/\.$//' | 98848ffe56aSColin Percival sort > serverlist_full 98948ffe56aSColin Percival 99048ffe56aSColin Percival# If no records, give up -- we'll just use the server name we were given. 99148ffe56aSColin Percival if [ `wc -l < serverlist_full` -eq 0 ]; then 99248ffe56aSColin Percival echo "none found." 99348ffe56aSColin Percival return 1 99448ffe56aSColin Percival fi 99548ffe56aSColin Percival 99648ffe56aSColin Percival# Report how many mirrors we found. 99748ffe56aSColin Percival echo `wc -l < serverlist_full` "mirrors found." 99848ffe56aSColin Percival 99948ffe56aSColin Percival# Generate a random seed for use in picking mirrors. If HTTP_PROXY 100048ffe56aSColin Percival# is set, this will be used to generate the seed; otherwise, the seed 100148ffe56aSColin Percival# will be random. 100248ffe56aSColin Percival if [ -n "${HTTP_PROXY}${http_proxy}" ]; then 100348ffe56aSColin Percival RANDVALUE=`sha256 -qs "${HTTP_PROXY}${http_proxy}" | 100448ffe56aSColin Percival tr -d 'a-f' | 100548ffe56aSColin Percival cut -c 1-9` 100648ffe56aSColin Percival else 100748ffe56aSColin Percival RANDVALUE=`jot -r 1 0 999999999` 100848ffe56aSColin Percival fi 100948ffe56aSColin Percival} 101048ffe56aSColin Percival 101148ffe56aSColin Percival# Pick a mirror. Returns 1 if we have run out of mirrors to try. 101248ffe56aSColin Percivalfetch_pick_server () { 101348ffe56aSColin Percival# Generate a list of not-yet-tried mirrors 101448ffe56aSColin Percival sort serverlist_tried | 101548ffe56aSColin Percival comm -23 serverlist_full - > serverlist 101648ffe56aSColin Percival 101748ffe56aSColin Percival# Have we run out of mirrors? 101848ffe56aSColin Percival if [ `wc -l < serverlist` -eq 0 ]; then 101948ffe56aSColin Percival echo "No mirrors remaining, giving up." 102048ffe56aSColin Percival return 1 102148ffe56aSColin Percival fi 102248ffe56aSColin Percival 102348ffe56aSColin Percival# Find the highest priority level (lowest numeric value). 102448ffe56aSColin Percival SRV_PRIORITY=`cut -f 1 -d ' ' serverlist | sort -n | head -1` 102548ffe56aSColin Percival 102648ffe56aSColin Percival# Add up the weights of the response lines at that priority level. 102748ffe56aSColin Percival SRV_WSUM=0; 102848ffe56aSColin Percival while read X; do 102948ffe56aSColin Percival case "$X" in 103048ffe56aSColin Percival ${SRV_PRIORITY}\ *) 103148ffe56aSColin Percival SRV_W=`echo $X | cut -f 2 -d ' '` 103248ffe56aSColin Percival SRV_WSUM=$(($SRV_WSUM + $SRV_W)) 103348ffe56aSColin Percival ;; 103448ffe56aSColin Percival esac 103548ffe56aSColin Percival done < serverlist 103648ffe56aSColin Percival 103748ffe56aSColin Percival# If all the weights are 0, pretend that they are all 1 instead. 103848ffe56aSColin Percival if [ ${SRV_WSUM} -eq 0 ]; then 103948ffe56aSColin Percival SRV_WSUM=`grep -E "^${SRV_PRIORITY} " serverlist | wc -l` 104048ffe56aSColin Percival SRV_W_ADD=1 104148ffe56aSColin Percival else 104248ffe56aSColin Percival SRV_W_ADD=0 104348ffe56aSColin Percival fi 104448ffe56aSColin Percival 104548ffe56aSColin Percival# Pick a value between 0 and the sum of the weights - 1 104648ffe56aSColin Percival SRV_RND=`expr ${RANDVALUE} % ${SRV_WSUM}` 104748ffe56aSColin Percival 104848ffe56aSColin Percival# Read through the list of mirrors and set SERVERNAME. Write the line 104948ffe56aSColin Percival# corresponding to the mirror we selected into serverlist_tried so that 105048ffe56aSColin Percival# we won't try it again. 105148ffe56aSColin Percival while read X; do 105248ffe56aSColin Percival case "$X" in 105348ffe56aSColin Percival ${SRV_PRIORITY}\ *) 105448ffe56aSColin Percival SRV_W=`echo $X | cut -f 2 -d ' '` 105548ffe56aSColin Percival SRV_W=$(($SRV_W + $SRV_W_ADD)) 105648ffe56aSColin Percival if [ $SRV_RND -lt $SRV_W ]; then 105748ffe56aSColin Percival SERVERNAME=`echo $X | cut -f 3 -d ' '` 105848ffe56aSColin Percival echo "$X" >> serverlist_tried 105948ffe56aSColin Percival break 106048ffe56aSColin Percival else 106148ffe56aSColin Percival SRV_RND=$(($SRV_RND - $SRV_W)) 106248ffe56aSColin Percival fi 106348ffe56aSColin Percival ;; 106448ffe56aSColin Percival esac 106548ffe56aSColin Percival done < serverlist 106648ffe56aSColin Percival} 106748ffe56aSColin Percival 106848ffe56aSColin Percival# Take a list of ${oldhash}|${newhash} and output a list of needed patches, 106948ffe56aSColin Percival# i.e., those for which we have ${oldhash} and don't have ${newhash}. 107048ffe56aSColin Percivalfetch_make_patchlist () { 107148ffe56aSColin Percival grep -vE "^([0-9a-f]{64})\|\1$" | 107248ffe56aSColin Percival tr '|' ' ' | 107348ffe56aSColin Percival while read X Y; do 107448ffe56aSColin Percival if [ -f "files/${Y}.gz" ] || 107548ffe56aSColin Percival [ ! -f "files/${X}.gz" ]; then 107648ffe56aSColin Percival continue 107748ffe56aSColin Percival fi 107848ffe56aSColin Percival echo "${X}|${Y}" 1079f6e21461SEd Maste done | sort -u 108048ffe56aSColin Percival} 108148ffe56aSColin Percival 108248ffe56aSColin Percival# Print user-friendly progress statistics 108348ffe56aSColin Percivalfetch_progress () { 108448ffe56aSColin Percival LNC=0 108548ffe56aSColin Percival while read x; do 108648ffe56aSColin Percival LNC=$(($LNC + 1)) 108748ffe56aSColin Percival if [ $(($LNC % 10)) = 0 ]; then 108848ffe56aSColin Percival echo -n $LNC 108948ffe56aSColin Percival elif [ $(($LNC % 2)) = 0 ]; then 109048ffe56aSColin Percival echo -n . 109148ffe56aSColin Percival fi 109248ffe56aSColin Percival done 109348ffe56aSColin Percival echo -n " " 109448ffe56aSColin Percival} 109548ffe56aSColin Percival 1096db6b0a61SColin Percival# Function for asking the user if everything is ok 1097db6b0a61SColin Percivalcontinuep () { 1098db6b0a61SColin Percival while read -p "Does this look reasonable (y/n)? " CONTINUE; do 1099db6b0a61SColin Percival case "${CONTINUE}" in 1100db6b0a61SColin Percival y*) 1101db6b0a61SColin Percival return 0 1102db6b0a61SColin Percival ;; 1103db6b0a61SColin Percival n*) 1104db6b0a61SColin Percival return 1 1105db6b0a61SColin Percival ;; 1106db6b0a61SColin Percival esac 1107db6b0a61SColin Percival done 1108db6b0a61SColin Percival} 1109db6b0a61SColin Percival 111048ffe56aSColin Percival# Initialize the working directory 111148ffe56aSColin Percivalworkdir_init () { 111248ffe56aSColin Percival mkdir -p files 111348ffe56aSColin Percival touch tINDEX.present 111448ffe56aSColin Percival} 111548ffe56aSColin Percival 111648ffe56aSColin Percival# Check that we have a public key with an appropriate hash, or 111748ffe56aSColin Percival# fetch the key if it doesn't exist. Returns 1 if the key has 111848ffe56aSColin Percival# not yet been fetched. 111948ffe56aSColin Percivalfetch_key () { 112048ffe56aSColin Percival if [ -r pub.ssl ] && [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 112148ffe56aSColin Percival return 0 112248ffe56aSColin Percival fi 112348ffe56aSColin Percival 112448ffe56aSColin Percival echo -n "Fetching public key from ${SERVERNAME}... " 112548ffe56aSColin Percival rm -f pub.ssl 112648ffe56aSColin Percival fetch ${QUIETFLAG} http://${SERVERNAME}/${FETCHDIR}/pub.ssl \ 112748ffe56aSColin Percival 2>${QUIETREDIR} || true 112848ffe56aSColin Percival if ! [ -r pub.ssl ]; then 112948ffe56aSColin Percival echo "failed." 113048ffe56aSColin Percival return 1 113148ffe56aSColin Percival fi 113248ffe56aSColin Percival if ! [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 113348ffe56aSColin Percival echo "key has incorrect hash." 113448ffe56aSColin Percival rm -f pub.ssl 113548ffe56aSColin Percival return 1 113648ffe56aSColin Percival fi 113748ffe56aSColin Percival echo "done." 113848ffe56aSColin Percival} 113948ffe56aSColin Percival 114048ffe56aSColin Percival# Fetch metadata signature, aka "tag". 114148ffe56aSColin Percivalfetch_tag () { 1142db6b0a61SColin Percival echo -n "Fetching metadata signature " 1143db6b0a61SColin Percival echo ${NDEBUG} "for ${RELNUM} from ${SERVERNAME}... " 114448ffe56aSColin Percival rm -f latest.ssl 114548ffe56aSColin Percival fetch ${QUIETFLAG} http://${SERVERNAME}/${FETCHDIR}/latest.ssl \ 114648ffe56aSColin Percival 2>${QUIETREDIR} || true 114748ffe56aSColin Percival if ! [ -r latest.ssl ]; then 114848ffe56aSColin Percival echo "failed." 114948ffe56aSColin Percival return 1 115048ffe56aSColin Percival fi 115148ffe56aSColin Percival 115248ffe56aSColin Percival openssl rsautl -pubin -inkey pub.ssl -verify \ 115348ffe56aSColin Percival < latest.ssl > tag.new 2>${QUIETREDIR} || true 115448ffe56aSColin Percival rm latest.ssl 115548ffe56aSColin Percival 115648ffe56aSColin Percival if ! [ `wc -l < tag.new` = 1 ] || 115748ffe56aSColin Percival ! grep -qE \ 115848ffe56aSColin Percival "^freebsd-update\|${ARCH}\|${RELNUM}\|[0-9]+\|[0-9a-f]{64}\|[0-9]{10}" \ 115948ffe56aSColin Percival tag.new; then 116048ffe56aSColin Percival echo "invalid signature." 116148ffe56aSColin Percival return 1 116248ffe56aSColin Percival fi 116348ffe56aSColin Percival 116448ffe56aSColin Percival echo "done." 116548ffe56aSColin Percival 116648ffe56aSColin Percival RELPATCHNUM=`cut -f 4 -d '|' < tag.new` 116748ffe56aSColin Percival TINDEXHASH=`cut -f 5 -d '|' < tag.new` 116848ffe56aSColin Percival EOLTIME=`cut -f 6 -d '|' < tag.new` 116948ffe56aSColin Percival} 117048ffe56aSColin Percival 117148ffe56aSColin Percival# Sanity-check the patch number in a tag, to make sure that we're not 117248ffe56aSColin Percival# going to "update" backwards and to prevent replay attacks. 117348ffe56aSColin Percivalfetch_tagsanity () { 117448ffe56aSColin Percival # Check that we're not going to move from -pX to -pY with Y < X. 117548ffe56aSColin Percival RELPX=`uname -r | sed -E 's,.*-,,'` 117648ffe56aSColin Percival if echo ${RELPX} | grep -qE '^p[0-9]+$'; then 117748ffe56aSColin Percival RELPX=`echo ${RELPX} | cut -c 2-` 117848ffe56aSColin Percival else 117948ffe56aSColin Percival RELPX=0 118048ffe56aSColin Percival fi 118148ffe56aSColin Percival if [ "${RELPATCHNUM}" -lt "${RELPX}" ]; then 118248ffe56aSColin Percival echo 118348ffe56aSColin Percival echo -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" 118448ffe56aSColin Percival echo " appear older than what" 118548ffe56aSColin Percival echo "we are currently running (`uname -r`)!" 118648ffe56aSColin Percival echo "Cowardly refusing to proceed any further." 118748ffe56aSColin Percival return 1 118848ffe56aSColin Percival fi 118948ffe56aSColin Percival 119048ffe56aSColin Percival # If "tag" exists and corresponds to ${RELNUM}, make sure that 119148ffe56aSColin Percival # it contains a patch number <= RELPATCHNUM, in order to protect 119248ffe56aSColin Percival # against rollback (replay) attacks. 119348ffe56aSColin Percival if [ -f tag ] && 119448ffe56aSColin Percival grep -qE \ 119548ffe56aSColin Percival "^freebsd-update\|${ARCH}\|${RELNUM}\|[0-9]+\|[0-9a-f]{64}\|[0-9]{10}" \ 119648ffe56aSColin Percival tag; then 119748ffe56aSColin Percival LASTRELPATCHNUM=`cut -f 4 -d '|' < tag` 119848ffe56aSColin Percival 119948ffe56aSColin Percival if [ "${RELPATCHNUM}" -lt "${LASTRELPATCHNUM}" ]; then 120048ffe56aSColin Percival echo 120148ffe56aSColin Percival echo -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" 120248ffe56aSColin Percival echo " are older than the" 120348ffe56aSColin Percival echo -n "most recently seen updates" 120448ffe56aSColin Percival echo " (${RELNUM}-p${LASTRELPATCHNUM})." 120548ffe56aSColin Percival echo "Cowardly refusing to proceed any further." 120648ffe56aSColin Percival return 1 120748ffe56aSColin Percival fi 120848ffe56aSColin Percival fi 120948ffe56aSColin Percival} 121048ffe56aSColin Percival 121148ffe56aSColin Percival# Fetch metadata index file 121248ffe56aSColin Percivalfetch_metadata_index () { 121348ffe56aSColin Percival echo ${NDEBUG} "Fetching metadata index... " 121448ffe56aSColin Percival rm -f ${TINDEXHASH} 121548ffe56aSColin Percival fetch ${QUIETFLAG} http://${SERVERNAME}/${FETCHDIR}/t/${TINDEXHASH} 121648ffe56aSColin Percival 2>${QUIETREDIR} 121748ffe56aSColin Percival if ! [ -f ${TINDEXHASH} ]; then 121848ffe56aSColin Percival echo "failed." 121948ffe56aSColin Percival return 1 122048ffe56aSColin Percival fi 122148ffe56aSColin Percival if [ `${SHA256} -q ${TINDEXHASH}` != ${TINDEXHASH} ]; then 122248ffe56aSColin Percival echo "update metadata index corrupt." 122348ffe56aSColin Percival return 1 122448ffe56aSColin Percival fi 122548ffe56aSColin Percival echo "done." 122648ffe56aSColin Percival} 122748ffe56aSColin Percival 122848ffe56aSColin Percival# Print an error message about signed metadata being bogus. 122948ffe56aSColin Percivalfetch_metadata_bogus () { 123048ffe56aSColin Percival echo 123148ffe56aSColin Percival echo "The update metadata$1 is correctly signed, but" 123248ffe56aSColin Percival echo "failed an integrity check." 123348ffe56aSColin Percival echo "Cowardly refusing to proceed any further." 123448ffe56aSColin Percival return 1 123548ffe56aSColin Percival} 123648ffe56aSColin Percival 123748ffe56aSColin Percival# Construct tINDEX.new by merging the lines named in $1 from ${TINDEXHASH} 123848ffe56aSColin Percival# with the lines not named in $@ from tINDEX.present (if that file exists). 123948ffe56aSColin Percivalfetch_metadata_index_merge () { 124048ffe56aSColin Percival for METAFILE in $@; do 124148ffe56aSColin Percival if [ `grep -E "^${METAFILE}\|" ${TINDEXHASH} | wc -l` \ 124248ffe56aSColin Percival -ne 1 ]; then 124348ffe56aSColin Percival fetch_metadata_bogus " index" 124448ffe56aSColin Percival return 1 124548ffe56aSColin Percival fi 124648ffe56aSColin Percival 124748ffe56aSColin Percival grep -E "${METAFILE}\|" ${TINDEXHASH} 124848ffe56aSColin Percival done | 124948ffe56aSColin Percival sort > tINDEX.wanted 125048ffe56aSColin Percival 125148ffe56aSColin Percival if [ -f tINDEX.present ]; then 125248ffe56aSColin Percival join -t '|' -v 2 tINDEX.wanted tINDEX.present | 125348ffe56aSColin Percival sort -m - tINDEX.wanted > tINDEX.new 125448ffe56aSColin Percival rm tINDEX.wanted 125548ffe56aSColin Percival else 125648ffe56aSColin Percival mv tINDEX.wanted tINDEX.new 125748ffe56aSColin Percival fi 125848ffe56aSColin Percival} 125948ffe56aSColin Percival 126048ffe56aSColin Percival# Sanity check all the lines of tINDEX.new. Even if more metadata lines 126148ffe56aSColin Percival# are added by future versions of the server, this won't cause problems, 126248ffe56aSColin Percival# since the only lines which appear in tINDEX.new are the ones which we 126348ffe56aSColin Percival# specifically grepped out of ${TINDEXHASH}. 126448ffe56aSColin Percivalfetch_metadata_index_sanity () { 126548ffe56aSColin Percival if grep -qvE '^[0-9A-Z.-]+\|[0-9a-f]{64}$' tINDEX.new; then 126648ffe56aSColin Percival fetch_metadata_bogus " index" 126748ffe56aSColin Percival return 1 126848ffe56aSColin Percival fi 126948ffe56aSColin Percival} 127048ffe56aSColin Percival 127148ffe56aSColin Percival# Sanity check the metadata file $1. 127248ffe56aSColin Percivalfetch_metadata_sanity () { 127348ffe56aSColin Percival # Some aliases to save space later: ${P} is a character which can 127448ffe56aSColin Percival # appear in a path; ${M} is the four numeric metadata fields; and 127548ffe56aSColin Percival # ${H} is a sha256 hash. 12767c06c7c5SKris Moore P="[-+./:=,%@_[~[:alnum:]]" 127748ffe56aSColin Percival M="[0-9]+\|[0-9]+\|[0-9]+\|[0-9]+" 127848ffe56aSColin Percival H="[0-9a-f]{64}" 127948ffe56aSColin Percival 128048ffe56aSColin Percival # Check that the first four fields make sense. 128148ffe56aSColin Percival if gunzip -c < files/$1.gz | 1282823c0d5fSXin LI grep -qvE "^[a-z]+\|[0-9a-z-]+\|${P}+\|[fdL-]\|"; then 128348ffe56aSColin Percival fetch_metadata_bogus "" 128448ffe56aSColin Percival return 1 128548ffe56aSColin Percival fi 128648ffe56aSColin Percival 128748ffe56aSColin Percival # Remove the first three fields. 128848ffe56aSColin Percival gunzip -c < files/$1.gz | 128948ffe56aSColin Percival cut -f 4- -d '|' > sanitycheck.tmp 129048ffe56aSColin Percival 129148ffe56aSColin Percival # Sanity check entries with type 'f' 129248ffe56aSColin Percival if grep -E '^f' sanitycheck.tmp | 129348ffe56aSColin Percival grep -qvE "^f\|${M}\|${H}\|${P}*\$"; then 129448ffe56aSColin Percival fetch_metadata_bogus "" 129548ffe56aSColin Percival return 1 129648ffe56aSColin Percival fi 129748ffe56aSColin Percival 129848ffe56aSColin Percival # Sanity check entries with type 'd' 129948ffe56aSColin Percival if grep -E '^d' sanitycheck.tmp | 130048ffe56aSColin Percival grep -qvE "^d\|${M}\|\|\$"; then 130148ffe56aSColin Percival fetch_metadata_bogus "" 130248ffe56aSColin Percival return 1 130348ffe56aSColin Percival fi 130448ffe56aSColin Percival 130548ffe56aSColin Percival # Sanity check entries with type 'L' 130648ffe56aSColin Percival if grep -E '^L' sanitycheck.tmp | 130748ffe56aSColin Percival grep -qvE "^L\|${M}\|${P}*\|\$"; then 130848ffe56aSColin Percival fetch_metadata_bogus "" 130948ffe56aSColin Percival return 1 131048ffe56aSColin Percival fi 131148ffe56aSColin Percival 131248ffe56aSColin Percival # Sanity check entries with type '-' 131348ffe56aSColin Percival if grep -E '^-' sanitycheck.tmp | 131448ffe56aSColin Percival grep -qvE "^-\|\|\|\|\|\|"; then 131548ffe56aSColin Percival fetch_metadata_bogus "" 131648ffe56aSColin Percival return 1 131748ffe56aSColin Percival fi 131848ffe56aSColin Percival 131948ffe56aSColin Percival # Clean up 132048ffe56aSColin Percival rm sanitycheck.tmp 132148ffe56aSColin Percival} 132248ffe56aSColin Percival 132348ffe56aSColin Percival# Fetch the metadata index and metadata files listed in $@, 132448ffe56aSColin Percival# taking advantage of metadata patches where possible. 132548ffe56aSColin Percivalfetch_metadata () { 132648ffe56aSColin Percival fetch_metadata_index || return 1 132748ffe56aSColin Percival fetch_metadata_index_merge $@ || return 1 132848ffe56aSColin Percival fetch_metadata_index_sanity || return 1 132948ffe56aSColin Percival 133048ffe56aSColin Percival # Generate a list of wanted metadata patches 133148ffe56aSColin Percival join -t '|' -o 1.2,2.2 tINDEX.present tINDEX.new | 133248ffe56aSColin Percival fetch_make_patchlist > patchlist 133348ffe56aSColin Percival 133448ffe56aSColin Percival if [ -s patchlist ]; then 133548ffe56aSColin Percival # Attempt to fetch metadata patches 133648ffe56aSColin Percival echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 133748ffe56aSColin Percival echo ${NDEBUG} "metadata patches.${DDSTATS}" 133848ffe56aSColin Percival tr '|' '-' < patchlist | 133948ffe56aSColin Percival lam -s "${FETCHDIR}/tp/" - -s ".gz" | 134048ffe56aSColin Percival xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 134148ffe56aSColin Percival 2>${STATSREDIR} | fetch_progress 134248ffe56aSColin Percival echo "done." 134348ffe56aSColin Percival 134448ffe56aSColin Percival # Attempt to apply metadata patches 134548ffe56aSColin Percival echo -n "Applying metadata patches... " 134648ffe56aSColin Percival tr '|' ' ' < patchlist | 134748ffe56aSColin Percival while read X Y; do 134848ffe56aSColin Percival if [ ! -f "${X}-${Y}.gz" ]; then continue; fi 134948ffe56aSColin Percival gunzip -c < ${X}-${Y}.gz > diff 135048ffe56aSColin Percival gunzip -c < files/${X}.gz > diff-OLD 135148ffe56aSColin Percival 135248ffe56aSColin Percival # Figure out which lines are being added and removed 135348ffe56aSColin Percival grep -E '^-' diff | 135448ffe56aSColin Percival cut -c 2- | 135548ffe56aSColin Percival while read PREFIX; do 135648ffe56aSColin Percival look "${PREFIX}" diff-OLD 135748ffe56aSColin Percival done | 135848ffe56aSColin Percival sort > diff-rm 135948ffe56aSColin Percival grep -E '^\+' diff | 136048ffe56aSColin Percival cut -c 2- > diff-add 136148ffe56aSColin Percival 136248ffe56aSColin Percival # Generate the new file 136348ffe56aSColin Percival comm -23 diff-OLD diff-rm | 136448ffe56aSColin Percival sort - diff-add > diff-NEW 136548ffe56aSColin Percival 136648ffe56aSColin Percival if [ `${SHA256} -q diff-NEW` = ${Y} ]; then 136748ffe56aSColin Percival mv diff-NEW files/${Y} 136848ffe56aSColin Percival gzip -n files/${Y} 136948ffe56aSColin Percival else 137048ffe56aSColin Percival mv diff-NEW ${Y}.bad 137148ffe56aSColin Percival fi 137248ffe56aSColin Percival rm -f ${X}-${Y}.gz diff 137348ffe56aSColin Percival rm -f diff-OLD diff-NEW diff-add diff-rm 137448ffe56aSColin Percival done 2>${QUIETREDIR} 137548ffe56aSColin Percival echo "done." 137648ffe56aSColin Percival fi 137748ffe56aSColin Percival 137848ffe56aSColin Percival # Update metadata without patches 137948ffe56aSColin Percival cut -f 2 -d '|' < tINDEX.new | 138048ffe56aSColin Percival while read Y; do 138148ffe56aSColin Percival if [ ! -f "files/${Y}.gz" ]; then 138248ffe56aSColin Percival echo ${Y}; 138348ffe56aSColin Percival fi 1384bce02f98SColin Percival done | 1385bce02f98SColin Percival sort -u > filelist 138648ffe56aSColin Percival 138748ffe56aSColin Percival if [ -s filelist ]; then 138848ffe56aSColin Percival echo -n "Fetching `wc -l < filelist | tr -d ' '` " 138948ffe56aSColin Percival echo ${NDEBUG} "metadata files... " 139048ffe56aSColin Percival lam -s "${FETCHDIR}/m/" - -s ".gz" < filelist | 139148ffe56aSColin Percival xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 139248ffe56aSColin Percival 2>${QUIETREDIR} 139348ffe56aSColin Percival 139448ffe56aSColin Percival while read Y; do 139548ffe56aSColin Percival if ! [ -f ${Y}.gz ]; then 139648ffe56aSColin Percival echo "failed." 139748ffe56aSColin Percival return 1 139848ffe56aSColin Percival fi 139948ffe56aSColin Percival if [ `gunzip -c < ${Y}.gz | 140048ffe56aSColin Percival ${SHA256} -q` = ${Y} ]; then 140148ffe56aSColin Percival mv ${Y}.gz files/${Y}.gz 140248ffe56aSColin Percival else 140348ffe56aSColin Percival echo "metadata is corrupt." 140448ffe56aSColin Percival return 1 140548ffe56aSColin Percival fi 140648ffe56aSColin Percival done < filelist 140748ffe56aSColin Percival echo "done." 140848ffe56aSColin Percival fi 140948ffe56aSColin Percival 141048ffe56aSColin Percival# Sanity-check the metadata files. 141148ffe56aSColin Percival cut -f 2 -d '|' tINDEX.new > filelist 141248ffe56aSColin Percival while read X; do 141348ffe56aSColin Percival fetch_metadata_sanity ${X} || return 1 141448ffe56aSColin Percival done < filelist 141548ffe56aSColin Percival 141648ffe56aSColin Percival# Remove files which are no longer needed 141748ffe56aSColin Percival cut -f 2 -d '|' tINDEX.present | 141848ffe56aSColin Percival sort > oldfiles 141948ffe56aSColin Percival cut -f 2 -d '|' tINDEX.new | 142048ffe56aSColin Percival sort | 142148ffe56aSColin Percival comm -13 - oldfiles | 142248ffe56aSColin Percival lam -s "files/" - -s ".gz" | 142348ffe56aSColin Percival xargs rm -f 142448ffe56aSColin Percival rm patchlist filelist oldfiles 142548ffe56aSColin Percival rm ${TINDEXHASH} 142648ffe56aSColin Percival 142748ffe56aSColin Percival# We're done! 142848ffe56aSColin Percival mv tINDEX.new tINDEX.present 142948ffe56aSColin Percival mv tag.new tag 143048ffe56aSColin Percival 143148ffe56aSColin Percival return 0 143248ffe56aSColin Percival} 143348ffe56aSColin Percival 1434db6b0a61SColin Percival# Extract a subset of a downloaded metadata file containing only the parts 1435db6b0a61SColin Percival# which are listed in COMPONENTS. 1436db6b0a61SColin Percivalfetch_filter_metadata_components () { 1437db6b0a61SColin Percival METAHASH=`look "$1|" tINDEX.present | cut -f 2 -d '|'` 1438db6b0a61SColin Percival gunzip -c < files/${METAHASH}.gz > $1.all 1439db6b0a61SColin Percival 1440db6b0a61SColin Percival # Fish out the lines belonging to components we care about. 1441db6b0a61SColin Percival for C in ${COMPONENTS}; do 1442db6b0a61SColin Percival look "`echo ${C} | tr '/' '|'`|" $1.all 1443db6b0a61SColin Percival done > $1 1444db6b0a61SColin Percival 1445db6b0a61SColin Percival # Remove temporary file. 1446db6b0a61SColin Percival rm $1.all 1447db6b0a61SColin Percival} 1448db6b0a61SColin Percival 1449b698a3abSColin Percival# Generate a filtered version of the metadata file $1 from the downloaded 145048ffe56aSColin Percival# file, by fishing out the lines corresponding to components we're trying 145148ffe56aSColin Percival# to keep updated, and then removing lines corresponding to paths we want 145248ffe56aSColin Percival# to ignore. 145348ffe56aSColin Percivalfetch_filter_metadata () { 145448ffe56aSColin Percival # Fish out the lines belonging to components we care about. 1455db6b0a61SColin Percival fetch_filter_metadata_components $1 1456db6b0a61SColin Percival 145748ffe56aSColin Percival # Canonicalize directory names by removing any trailing / in 145848ffe56aSColin Percival # order to avoid listing directories multiple times if they 145948ffe56aSColin Percival # belong to multiple components. Turning "/" into "" doesn't 146048ffe56aSColin Percival # matter, since we add a leading "/" when we use paths later. 1461db6b0a61SColin Percival cut -f 3- -d '|' $1 | 146248ffe56aSColin Percival sed -e 's,/|d|,|d|,' | 14637e654612SColin Percival sed -e 's,/|-|,|-|,' | 146448ffe56aSColin Percival sort -u > $1.tmp 146548ffe56aSColin Percival 146648ffe56aSColin Percival # Figure out which lines to ignore and remove them. 146748ffe56aSColin Percival for X in ${IGNOREPATHS}; do 146848ffe56aSColin Percival grep -E "^${X}" $1.tmp 146948ffe56aSColin Percival done | 147048ffe56aSColin Percival sort -u | 147148ffe56aSColin Percival comm -13 - $1.tmp > $1 147248ffe56aSColin Percival 147348ffe56aSColin Percival # Remove temporary files. 1474db6b0a61SColin Percival rm $1.tmp 147548ffe56aSColin Percival} 147648ffe56aSColin Percival 1477db6b0a61SColin Percival# Filter the metadata file $1 by adding lines with "/boot/$2" 1478bce02f98SColin Percival# replaced by ${KERNELDIR} (which is `sysctl -n kern.bootfile` minus the 1479db6b0a61SColin Percival# trailing "/kernel"); and if "/boot/$2" does not exist, remove 1480bce02f98SColin Percival# the original lines which start with that. 1481bce02f98SColin Percival# Put another way: Deal with the fact that the FOO kernel is sometimes 1482bce02f98SColin Percival# installed in /boot/FOO/ and is sometimes installed elsewhere. 148348ffe56aSColin Percivalfetch_filter_kernel_names () { 1484db6b0a61SColin Percival grep ^/boot/$2 $1 | 1485db6b0a61SColin Percival sed -e "s,/boot/$2,${KERNELDIR},g" | 148648ffe56aSColin Percival sort - $1 > $1.tmp 148748ffe56aSColin Percival mv $1.tmp $1 1488bce02f98SColin Percival 1489db6b0a61SColin Percival if ! [ -d /boot/$2 ]; then 1490db6b0a61SColin Percival grep -v ^/boot/$2 $1 > $1.tmp 1491bce02f98SColin Percival mv $1.tmp $1 1492bce02f98SColin Percival fi 149348ffe56aSColin Percival} 149448ffe56aSColin Percival 149548ffe56aSColin Percival# For all paths appearing in $1 or $3, inspect the system 149648ffe56aSColin Percival# and generate $2 describing what is currently installed. 149748ffe56aSColin Percivalfetch_inspect_system () { 149848ffe56aSColin Percival # No errors yet... 149948ffe56aSColin Percival rm -f .err 150048ffe56aSColin Percival 150148ffe56aSColin Percival # Tell the user why his disk is suddenly making lots of noise 150248ffe56aSColin Percival echo -n "Inspecting system... " 150348ffe56aSColin Percival 150448ffe56aSColin Percival # Generate list of files to inspect 150548ffe56aSColin Percival cat $1 $3 | 150648ffe56aSColin Percival cut -f 1 -d '|' | 150748ffe56aSColin Percival sort -u > filelist 150848ffe56aSColin Percival 150948ffe56aSColin Percival # Examine each file and output lines of the form 151048ffe56aSColin Percival # /path/to/file|type|device-inum|user|group|perm|flags|value 151148ffe56aSColin Percival # sorted by device and inode number. 151248ffe56aSColin Percival while read F; do 151348ffe56aSColin Percival # If the symlink/file/directory does not exist, record this. 151448ffe56aSColin Percival if ! [ -e ${BASEDIR}/${F} ]; then 151548ffe56aSColin Percival echo "${F}|-||||||" 151648ffe56aSColin Percival continue 151748ffe56aSColin Percival fi 151848ffe56aSColin Percival if ! [ -r ${BASEDIR}/${F} ]; then 151948ffe56aSColin Percival echo "Cannot read file: ${BASEDIR}/${F}" \ 152048ffe56aSColin Percival >/dev/stderr 152148ffe56aSColin Percival touch .err 152248ffe56aSColin Percival return 1 152348ffe56aSColin Percival fi 152448ffe56aSColin Percival 152548ffe56aSColin Percival # Otherwise, output an index line. 152648ffe56aSColin Percival if [ -L ${BASEDIR}/${F} ]; then 152748ffe56aSColin Percival echo -n "${F}|L|" 152848ffe56aSColin Percival stat -n -f '%d-%i|%u|%g|%Mp%Lp|%Of|' ${BASEDIR}/${F}; 152948ffe56aSColin Percival readlink ${BASEDIR}/${F}; 153048ffe56aSColin Percival elif [ -f ${BASEDIR}/${F} ]; then 153148ffe56aSColin Percival echo -n "${F}|f|" 153248ffe56aSColin Percival stat -n -f '%d-%i|%u|%g|%Mp%Lp|%Of|' ${BASEDIR}/${F}; 153348ffe56aSColin Percival sha256 -q ${BASEDIR}/${F}; 153448ffe56aSColin Percival elif [ -d ${BASEDIR}/${F} ]; then 153548ffe56aSColin Percival echo -n "${F}|d|" 153648ffe56aSColin Percival stat -f '%d-%i|%u|%g|%Mp%Lp|%Of|' ${BASEDIR}/${F}; 153748ffe56aSColin Percival else 153848ffe56aSColin Percival echo "Unknown file type: ${BASEDIR}/${F}" \ 153948ffe56aSColin Percival >/dev/stderr 154048ffe56aSColin Percival touch .err 154148ffe56aSColin Percival return 1 154248ffe56aSColin Percival fi 154348ffe56aSColin Percival done < filelist | 154448ffe56aSColin Percival sort -k 3,3 -t '|' > $2.tmp 154548ffe56aSColin Percival rm filelist 154648ffe56aSColin Percival 15476dcc68c8SBenedict Reuschling # Check if an error occurred during system inspection 154848ffe56aSColin Percival if [ -f .err ]; then 154948ffe56aSColin Percival return 1 155048ffe56aSColin Percival fi 155148ffe56aSColin Percival 155248ffe56aSColin Percival # Convert to the form 155348ffe56aSColin Percival # /path/to/file|type|user|group|perm|flags|value|hlink 155448ffe56aSColin Percival # by resolving identical device and inode numbers into hard links. 155548ffe56aSColin Percival cut -f 1,3 -d '|' $2.tmp | 155648ffe56aSColin Percival sort -k 1,1 -t '|' | 155748ffe56aSColin Percival sort -s -u -k 2,2 -t '|' | 155848ffe56aSColin Percival join -1 2 -2 3 -t '|' - $2.tmp | 155948ffe56aSColin Percival awk -F \| -v OFS=\| \ 156048ffe56aSColin Percival '{ 156148ffe56aSColin Percival if (($2 == $3) || ($4 == "-")) 156248ffe56aSColin Percival print $3,$4,$5,$6,$7,$8,$9,"" 156348ffe56aSColin Percival else 156448ffe56aSColin Percival print $3,$4,$5,$6,$7,$8,$9,$2 156548ffe56aSColin Percival }' | 156648ffe56aSColin Percival sort > $2 156748ffe56aSColin Percival rm $2.tmp 156848ffe56aSColin Percival 156948ffe56aSColin Percival # We're finished looking around 157048ffe56aSColin Percival echo "done." 157148ffe56aSColin Percival} 157248ffe56aSColin Percival 1573db6b0a61SColin Percival# For any paths matching ${MERGECHANGES}, compare $1 and $2 and find any 1574db6b0a61SColin Percival# files which differ; generate $3 containing these paths and the old hashes. 1575db6b0a61SColin Percivalfetch_filter_mergechanges () { 1576db6b0a61SColin Percival # Pull out the paths and hashes of the files matching ${MERGECHANGES}. 1577db6b0a61SColin Percival for F in $1 $2; do 1578db6b0a61SColin Percival for X in ${MERGECHANGES}; do 1579db6b0a61SColin Percival grep -E "^${X}" ${F} 1580db6b0a61SColin Percival done | 1581db6b0a61SColin Percival cut -f 1,2,7 -d '|' | 1582db6b0a61SColin Percival sort > ${F}-values 1583db6b0a61SColin Percival done 1584db6b0a61SColin Percival 1585db6b0a61SColin Percival # Any line in $2-values which doesn't appear in $1-values and is a 1586db6b0a61SColin Percival # file means that we should list the path in $3. 1587db6b0a61SColin Percival comm -13 $1-values $2-values | 1588db6b0a61SColin Percival fgrep '|f|' | 1589db6b0a61SColin Percival cut -f 1 -d '|' > $2-paths 1590db6b0a61SColin Percival 1591db6b0a61SColin Percival # For each path, pull out one (and only one!) entry from $1-values. 1592db6b0a61SColin Percival # Note that we cannot distinguish which "old" version the user made 1593db6b0a61SColin Percival # changes to; but hopefully any changes which occur due to security 1594db6b0a61SColin Percival # updates will exist in both the "new" version and the version which 1595db6b0a61SColin Percival # the user has installed, so the merging will still work. 1596db6b0a61SColin Percival while read X; do 1597db6b0a61SColin Percival look "${X}|" $1-values | 1598db6b0a61SColin Percival head -1 1599db6b0a61SColin Percival done < $2-paths > $3 1600db6b0a61SColin Percival 1601db6b0a61SColin Percival # Clean up 1602db6b0a61SColin Percival rm $1-values $2-values $2-paths 1603db6b0a61SColin Percival} 1604db6b0a61SColin Percival 160548ffe56aSColin Percival# For any paths matching ${UPDATEIFUNMODIFIED}, remove lines from $[123] 1606db6b0a61SColin Percival# which correspond to lines in $2 with hashes not matching $1 or $3, unless 1607db6b0a61SColin Percival# the paths are listed in $4. For entries in $2 marked "not present" 1608db6b0a61SColin Percival# (aka. type -), remove lines from $[123] unless there is a corresponding 1609db6b0a61SColin Percival# entry in $1. 161048ffe56aSColin Percivalfetch_filter_unmodified_notpresent () { 161148ffe56aSColin Percival # Figure out which lines of $1 and $3 correspond to bits which 161248ffe56aSColin Percival # should only be updated if they haven't changed, and fish out 161348ffe56aSColin Percival # the (path, type, value) tuples. 161448ffe56aSColin Percival # NOTE: We don't consider a file to be "modified" if it matches 161548ffe56aSColin Percival # the hash from $3. 161648ffe56aSColin Percival for X in ${UPDATEIFUNMODIFIED}; do 161748ffe56aSColin Percival grep -E "^${X}" $1 161848ffe56aSColin Percival grep -E "^${X}" $3 161948ffe56aSColin Percival done | 162048ffe56aSColin Percival cut -f 1,2,7 -d '|' | 162148ffe56aSColin Percival sort > $1-values 162248ffe56aSColin Percival 162348ffe56aSColin Percival # Do the same for $2. 162448ffe56aSColin Percival for X in ${UPDATEIFUNMODIFIED}; do 162548ffe56aSColin Percival grep -E "^${X}" $2 162648ffe56aSColin Percival done | 162748ffe56aSColin Percival cut -f 1,2,7 -d '|' | 162848ffe56aSColin Percival sort > $2-values 162948ffe56aSColin Percival 163048ffe56aSColin Percival # Any entry in $2-values which is not in $1-values corresponds to 1631db6b0a61SColin Percival # a path which we need to remove from $1, $2, and $3, unless it 1632db6b0a61SColin Percival # that path appears in $4. 1633db6b0a61SColin Percival comm -13 $1-values $2-values | 1634db6b0a61SColin Percival sort -t '|' -k 1,1 > mlines.tmp 1635db6b0a61SColin Percival cut -f 1 -d '|' $4 | 1636db6b0a61SColin Percival sort | 1637db6b0a61SColin Percival join -v 2 -t '|' - mlines.tmp | 1638db6b0a61SColin Percival sort > mlines 1639db6b0a61SColin Percival rm $1-values $2-values mlines.tmp 164048ffe56aSColin Percival 164148ffe56aSColin Percival # Any lines in $2 which are not in $1 AND are "not present" lines 164248ffe56aSColin Percival # also belong in mlines. 164348ffe56aSColin Percival comm -13 $1 $2 | 164448ffe56aSColin Percival cut -f 1,2,7 -d '|' | 164548ffe56aSColin Percival fgrep '|-|' >> mlines 164648ffe56aSColin Percival 164748ffe56aSColin Percival # Remove lines from $1, $2, and $3 164848ffe56aSColin Percival for X in $1 $2 $3; do 164948ffe56aSColin Percival sort -t '|' -k 1,1 ${X} > ${X}.tmp 165048ffe56aSColin Percival cut -f 1 -d '|' < mlines | 165148ffe56aSColin Percival sort | 165248ffe56aSColin Percival join -v 2 -t '|' - ${X}.tmp | 165348ffe56aSColin Percival sort > ${X} 165448ffe56aSColin Percival rm ${X}.tmp 165548ffe56aSColin Percival done 165648ffe56aSColin Percival 165748ffe56aSColin Percival # Store a list of the modified files, for future reference 165848ffe56aSColin Percival fgrep -v '|-|' mlines | 165948ffe56aSColin Percival cut -f 1 -d '|' > modifiedfiles 166048ffe56aSColin Percival rm mlines 166148ffe56aSColin Percival} 166248ffe56aSColin Percival 166348ffe56aSColin Percival# For each entry in $1 of type -, remove any corresponding 166448ffe56aSColin Percival# entry from $2 if ${ALLOWADD} != "yes". Remove all entries 166548ffe56aSColin Percival# of type - from $1. 166648ffe56aSColin Percivalfetch_filter_allowadd () { 166748ffe56aSColin Percival cut -f 1,2 -d '|' < $1 | 166848ffe56aSColin Percival fgrep '|-' | 166948ffe56aSColin Percival cut -f 1 -d '|' > filesnotpresent 167048ffe56aSColin Percival 167148ffe56aSColin Percival if [ ${ALLOWADD} != "yes" ]; then 167248ffe56aSColin Percival sort < $2 | 167348ffe56aSColin Percival join -v 1 -t '|' - filesnotpresent | 167448ffe56aSColin Percival sort > $2.tmp 167548ffe56aSColin Percival mv $2.tmp $2 167648ffe56aSColin Percival fi 167748ffe56aSColin Percival 167848ffe56aSColin Percival sort < $1 | 167948ffe56aSColin Percival join -v 1 -t '|' - filesnotpresent | 168048ffe56aSColin Percival sort > $1.tmp 168148ffe56aSColin Percival mv $1.tmp $1 168248ffe56aSColin Percival rm filesnotpresent 168348ffe56aSColin Percival} 168448ffe56aSColin Percival 168548ffe56aSColin Percival# If ${ALLOWDELETE} != "yes", then remove any entries from $1 168648ffe56aSColin Percival# which don't correspond to entries in $2. 168748ffe56aSColin Percivalfetch_filter_allowdelete () { 168848ffe56aSColin Percival # Produce a lists ${PATH}|${TYPE} 168948ffe56aSColin Percival for X in $1 $2; do 169048ffe56aSColin Percival cut -f 1-2 -d '|' < ${X} | 169148ffe56aSColin Percival sort -u > ${X}.nodes 169248ffe56aSColin Percival done 169348ffe56aSColin Percival 169448ffe56aSColin Percival # Figure out which lines need to be removed from $1. 169548ffe56aSColin Percival if [ ${ALLOWDELETE} != "yes" ]; then 169648ffe56aSColin Percival comm -23 $1.nodes $2.nodes > $1.badnodes 169748ffe56aSColin Percival else 169848ffe56aSColin Percival : > $1.badnodes 169948ffe56aSColin Percival fi 170048ffe56aSColin Percival 170148ffe56aSColin Percival # Remove the relevant lines from $1 170248ffe56aSColin Percival while read X; do 170348ffe56aSColin Percival look "${X}|" $1 170448ffe56aSColin Percival done < $1.badnodes | 170548ffe56aSColin Percival comm -13 - $1 > $1.tmp 170648ffe56aSColin Percival mv $1.tmp $1 170748ffe56aSColin Percival 170848ffe56aSColin Percival rm $1.badnodes $1.nodes $2.nodes 170948ffe56aSColin Percival} 171048ffe56aSColin Percival 171148ffe56aSColin Percival# If ${KEEPMODIFIEDMETADATA} == "yes", then for each entry in $2 171248ffe56aSColin Percival# with metadata not matching any entry in $1, replace the corresponding 171348ffe56aSColin Percival# line of $3 with one having the same metadata as the entry in $2. 171448ffe56aSColin Percivalfetch_filter_modified_metadata () { 171548ffe56aSColin Percival # Fish out the metadata from $1 and $2 171648ffe56aSColin Percival for X in $1 $2; do 171748ffe56aSColin Percival cut -f 1-6 -d '|' < ${X} > ${X}.metadata 171848ffe56aSColin Percival done 171948ffe56aSColin Percival 172048ffe56aSColin Percival # Find the metadata we need to keep 172148ffe56aSColin Percival if [ ${KEEPMODIFIEDMETADATA} = "yes" ]; then 172248ffe56aSColin Percival comm -13 $1.metadata $2.metadata > keepmeta 172348ffe56aSColin Percival else 172448ffe56aSColin Percival : > keepmeta 172548ffe56aSColin Percival fi 172648ffe56aSColin Percival 172748ffe56aSColin Percival # Extract the lines which we need to remove from $3, and 172848ffe56aSColin Percival # construct the lines which we need to add to $3. 172948ffe56aSColin Percival : > $3.remove 173048ffe56aSColin Percival : > $3.add 173148ffe56aSColin Percival while read LINE; do 173248ffe56aSColin Percival NODE=`echo "${LINE}" | cut -f 1-2 -d '|'` 173348ffe56aSColin Percival look "${NODE}|" $3 >> $3.remove 173448ffe56aSColin Percival look "${NODE}|" $3 | 173548ffe56aSColin Percival cut -f 7- -d '|' | 173648ffe56aSColin Percival lam -s "${LINE}|" - >> $3.add 173748ffe56aSColin Percival done < keepmeta 173848ffe56aSColin Percival 173948ffe56aSColin Percival # Remove the specified lines and add the new lines. 174048ffe56aSColin Percival sort $3.remove | 174148ffe56aSColin Percival comm -13 - $3 | 174248ffe56aSColin Percival sort -u - $3.add > $3.tmp 174348ffe56aSColin Percival mv $3.tmp $3 174448ffe56aSColin Percival 174548ffe56aSColin Percival rm keepmeta $1.metadata $2.metadata $3.add $3.remove 174648ffe56aSColin Percival} 174748ffe56aSColin Percival 174848ffe56aSColin Percival# Remove lines from $1 and $2 which are identical; 174948ffe56aSColin Percival# no need to update a file if it isn't changing. 175048ffe56aSColin Percivalfetch_filter_uptodate () { 175148ffe56aSColin Percival comm -23 $1 $2 > $1.tmp 175248ffe56aSColin Percival comm -13 $1 $2 > $2.tmp 175348ffe56aSColin Percival 175448ffe56aSColin Percival mv $1.tmp $1 175548ffe56aSColin Percival mv $2.tmp $2 175648ffe56aSColin Percival} 175748ffe56aSColin Percival 1758db6b0a61SColin Percival# Fetch any "clean" old versions of files we need for merging changes. 1759db6b0a61SColin Percivalfetch_files_premerge () { 1760db6b0a61SColin Percival # We only need to do anything if $1 is non-empty. 1761db6b0a61SColin Percival if [ -s $1 ]; then 1762db6b0a61SColin Percival # Tell the user what we're doing 1763db6b0a61SColin Percival echo -n "Fetching files from ${OLDRELNUM} for merging... " 1764db6b0a61SColin Percival 1765db6b0a61SColin Percival # List of files wanted 1766db6b0a61SColin Percival fgrep '|f|' < $1 | 1767db6b0a61SColin Percival cut -f 3 -d '|' | 1768db6b0a61SColin Percival sort -u > files.wanted 1769db6b0a61SColin Percival 1770db6b0a61SColin Percival # Only fetch the files we don't already have 1771db6b0a61SColin Percival while read Y; do 1772db6b0a61SColin Percival if [ ! -f "files/${Y}.gz" ]; then 1773db6b0a61SColin Percival echo ${Y}; 1774db6b0a61SColin Percival fi 1775db6b0a61SColin Percival done < files.wanted > filelist 1776db6b0a61SColin Percival 1777db6b0a61SColin Percival # Actually fetch them 1778db6b0a61SColin Percival lam -s "${OLDFETCHDIR}/f/" - -s ".gz" < filelist | 1779db6b0a61SColin Percival xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 1780db6b0a61SColin Percival 2>${QUIETREDIR} 1781db6b0a61SColin Percival 1782db6b0a61SColin Percival # Make sure we got them all, and move them into /files/ 1783db6b0a61SColin Percival while read Y; do 1784db6b0a61SColin Percival if ! [ -f ${Y}.gz ]; then 1785db6b0a61SColin Percival echo "failed." 1786db6b0a61SColin Percival return 1 1787db6b0a61SColin Percival fi 1788db6b0a61SColin Percival if [ `gunzip -c < ${Y}.gz | 1789db6b0a61SColin Percival ${SHA256} -q` = ${Y} ]; then 1790db6b0a61SColin Percival mv ${Y}.gz files/${Y}.gz 1791db6b0a61SColin Percival else 1792db6b0a61SColin Percival echo "${Y} has incorrect hash." 1793db6b0a61SColin Percival return 1 1794db6b0a61SColin Percival fi 1795db6b0a61SColin Percival done < filelist 1796db6b0a61SColin Percival echo "done." 1797db6b0a61SColin Percival 1798db6b0a61SColin Percival # Clean up 1799db6b0a61SColin Percival rm filelist files.wanted 1800db6b0a61SColin Percival fi 1801db6b0a61SColin Percival} 1802db6b0a61SColin Percival 180348ffe56aSColin Percival# Prepare to fetch files: Generate a list of the files we need, 180448ffe56aSColin Percival# copy the unmodified files we have into /files/, and generate 180548ffe56aSColin Percival# a list of patches to download. 180648ffe56aSColin Percivalfetch_files_prepare () { 180748ffe56aSColin Percival # Tell the user why his disk is suddenly making lots of noise 180848ffe56aSColin Percival echo -n "Preparing to download files... " 180948ffe56aSColin Percival 181048ffe56aSColin Percival # Reduce indices to ${PATH}|${HASH} pairs 181148ffe56aSColin Percival for X in $1 $2 $3; do 181248ffe56aSColin Percival cut -f 1,2,7 -d '|' < ${X} | 181348ffe56aSColin Percival fgrep '|f|' | 181448ffe56aSColin Percival cut -f 1,3 -d '|' | 181548ffe56aSColin Percival sort > ${X}.hashes 181648ffe56aSColin Percival done 181748ffe56aSColin Percival 181848ffe56aSColin Percival # List of files wanted 181948ffe56aSColin Percival cut -f 2 -d '|' < $3.hashes | 18202328d598SColin Percival sort -u | 18212328d598SColin Percival while read HASH; do 18222328d598SColin Percival if ! [ -f files/${HASH}.gz ]; then 18232328d598SColin Percival echo ${HASH} 18242328d598SColin Percival fi 18252328d598SColin Percival done > files.wanted 182648ffe56aSColin Percival 182748ffe56aSColin Percival # Generate a list of unmodified files 182848ffe56aSColin Percival comm -12 $1.hashes $2.hashes | 182948ffe56aSColin Percival sort -k 1,1 -t '|' > unmodified.files 183048ffe56aSColin Percival 183148ffe56aSColin Percival # Copy all files into /files/. We only need the unmodified files 183248ffe56aSColin Percival # for use in patching; but we'll want all of them if the user asks 183348ffe56aSColin Percival # to rollback the updates later. 1834210b8123SColin Percival while read LINE; do 1835210b8123SColin Percival F=`echo "${LINE}" | cut -f 1 -d '|'` 1836210b8123SColin Percival HASH=`echo "${LINE}" | cut -f 2 -d '|'` 1837210b8123SColin Percival 1838210b8123SColin Percival # Skip files we already have. 1839210b8123SColin Percival if [ -f files/${HASH}.gz ]; then 1840210b8123SColin Percival continue 1841210b8123SColin Percival fi 1842210b8123SColin Percival 1843210b8123SColin Percival # Make sure the file hasn't changed. 184448ffe56aSColin Percival cp "${BASEDIR}/${F}" tmpfile 1845210b8123SColin Percival if [ `sha256 -q tmpfile` != ${HASH} ]; then 1846210b8123SColin Percival echo 1847210b8123SColin Percival echo "File changed while FreeBSD Update running: ${F}" 1848210b8123SColin Percival return 1 1849210b8123SColin Percival fi 1850210b8123SColin Percival 1851210b8123SColin Percival # Place the file into storage. 1852210b8123SColin Percival gzip -c < tmpfile > files/${HASH}.gz 185348ffe56aSColin Percival rm tmpfile 1854210b8123SColin Percival done < $2.hashes 185548ffe56aSColin Percival 185648ffe56aSColin Percival # Produce a list of patches to download 185748ffe56aSColin Percival sort -k 1,1 -t '|' $3.hashes | 185848ffe56aSColin Percival join -t '|' -o 2.2,1.2 - unmodified.files | 185948ffe56aSColin Percival fetch_make_patchlist > patchlist 186048ffe56aSColin Percival 186148ffe56aSColin Percival # Garbage collect 186248ffe56aSColin Percival rm unmodified.files $1.hashes $2.hashes $3.hashes 186348ffe56aSColin Percival 186448ffe56aSColin Percival # We don't need the list of possible old files any more. 186548ffe56aSColin Percival rm $1 186648ffe56aSColin Percival 186748ffe56aSColin Percival # We're finished making noise 186848ffe56aSColin Percival echo "done." 186948ffe56aSColin Percival} 187048ffe56aSColin Percival 187148ffe56aSColin Percival# Fetch files. 187248ffe56aSColin Percivalfetch_files () { 187348ffe56aSColin Percival # Attempt to fetch patches 187448ffe56aSColin Percival if [ -s patchlist ]; then 187548ffe56aSColin Percival echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 187648ffe56aSColin Percival echo ${NDEBUG} "patches.${DDSTATS}" 187748ffe56aSColin Percival tr '|' '-' < patchlist | 1878db6b0a61SColin Percival lam -s "${PATCHDIR}/" - | 187948ffe56aSColin Percival xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 188048ffe56aSColin Percival 2>${STATSREDIR} | fetch_progress 188148ffe56aSColin Percival echo "done." 188248ffe56aSColin Percival 188348ffe56aSColin Percival # Attempt to apply patches 188448ffe56aSColin Percival echo -n "Applying patches... " 188548ffe56aSColin Percival tr '|' ' ' < patchlist | 188648ffe56aSColin Percival while read X Y; do 188748ffe56aSColin Percival if [ ! -f "${X}-${Y}" ]; then continue; fi 188848ffe56aSColin Percival gunzip -c < files/${X}.gz > OLD 188948ffe56aSColin Percival 189048ffe56aSColin Percival bspatch OLD NEW ${X}-${Y} 189148ffe56aSColin Percival 189248ffe56aSColin Percival if [ `${SHA256} -q NEW` = ${Y} ]; then 189348ffe56aSColin Percival mv NEW files/${Y} 189448ffe56aSColin Percival gzip -n files/${Y} 189548ffe56aSColin Percival fi 189648ffe56aSColin Percival rm -f diff OLD NEW ${X}-${Y} 189748ffe56aSColin Percival done 2>${QUIETREDIR} 189848ffe56aSColin Percival echo "done." 189948ffe56aSColin Percival fi 190048ffe56aSColin Percival 190148ffe56aSColin Percival # Download files which couldn't be generate via patching 190248ffe56aSColin Percival while read Y; do 190348ffe56aSColin Percival if [ ! -f "files/${Y}.gz" ]; then 190448ffe56aSColin Percival echo ${Y}; 190548ffe56aSColin Percival fi 190648ffe56aSColin Percival done < files.wanted > filelist 190748ffe56aSColin Percival 190848ffe56aSColin Percival if [ -s filelist ]; then 190948ffe56aSColin Percival echo -n "Fetching `wc -l < filelist | tr -d ' '` " 191048ffe56aSColin Percival echo ${NDEBUG} "files... " 191148ffe56aSColin Percival lam -s "${FETCHDIR}/f/" - -s ".gz" < filelist | 191248ffe56aSColin Percival xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 1913d6e1e31aSConrad Meyer 2>${STATSREDIR} | fetch_progress 191448ffe56aSColin Percival 191548ffe56aSColin Percival while read Y; do 191648ffe56aSColin Percival if ! [ -f ${Y}.gz ]; then 191748ffe56aSColin Percival echo "failed." 191848ffe56aSColin Percival return 1 191948ffe56aSColin Percival fi 192048ffe56aSColin Percival if [ `gunzip -c < ${Y}.gz | 192148ffe56aSColin Percival ${SHA256} -q` = ${Y} ]; then 192248ffe56aSColin Percival mv ${Y}.gz files/${Y}.gz 192348ffe56aSColin Percival else 192448ffe56aSColin Percival echo "${Y} has incorrect hash." 192548ffe56aSColin Percival return 1 192648ffe56aSColin Percival fi 192748ffe56aSColin Percival done < filelist 192848ffe56aSColin Percival echo "done." 192948ffe56aSColin Percival fi 193048ffe56aSColin Percival 193148ffe56aSColin Percival # Clean up 193248ffe56aSColin Percival rm files.wanted filelist patchlist 193348ffe56aSColin Percival} 193448ffe56aSColin Percival 193548ffe56aSColin Percival# Create and populate install manifest directory; and report what updates 193648ffe56aSColin Percival# are available. 193748ffe56aSColin Percivalfetch_create_manifest () { 193848ffe56aSColin Percival # If we have an existing install manifest, nuke it. 193948ffe56aSColin Percival if [ -L "${BDHASH}-install" ]; then 194048ffe56aSColin Percival rm -r ${BDHASH}-install/ 194148ffe56aSColin Percival rm ${BDHASH}-install 194248ffe56aSColin Percival fi 194348ffe56aSColin Percival 194448ffe56aSColin Percival # Report to the user if any updates were avoided due to local changes 194548ffe56aSColin Percival if [ -s modifiedfiles ]; then 194648ffe56aSColin Percival echo 194748ffe56aSColin Percival echo -n "The following files are affected by updates, " 194848ffe56aSColin Percival echo "but no changes have" 194948ffe56aSColin Percival echo -n "been downloaded because the files have been " 195048ffe56aSColin Percival echo "modified locally:" 195148ffe56aSColin Percival cat modifiedfiles 19529c990fb2SGordon Tetlow fi | $PAGER 195348ffe56aSColin Percival rm modifiedfiles 195448ffe56aSColin Percival 195548ffe56aSColin Percival # If no files will be updated, tell the user and exit 195648ffe56aSColin Percival if ! [ -s INDEX-PRESENT ] && 195748ffe56aSColin Percival ! [ -s INDEX-NEW ]; then 195848ffe56aSColin Percival rm INDEX-PRESENT INDEX-NEW 195948ffe56aSColin Percival echo 196048ffe56aSColin Percival echo -n "No updates needed to update system to " 196148ffe56aSColin Percival echo "${RELNUM}-p${RELPATCHNUM}." 196248ffe56aSColin Percival return 196348ffe56aSColin Percival fi 196448ffe56aSColin Percival 196548ffe56aSColin Percival # Divide files into (a) removed files, (b) added files, and 196648ffe56aSColin Percival # (c) updated files. 196748ffe56aSColin Percival cut -f 1 -d '|' < INDEX-PRESENT | 196848ffe56aSColin Percival sort > INDEX-PRESENT.flist 196948ffe56aSColin Percival cut -f 1 -d '|' < INDEX-NEW | 197048ffe56aSColin Percival sort > INDEX-NEW.flist 197148ffe56aSColin Percival comm -23 INDEX-PRESENT.flist INDEX-NEW.flist > files.removed 197248ffe56aSColin Percival comm -13 INDEX-PRESENT.flist INDEX-NEW.flist > files.added 197348ffe56aSColin Percival comm -12 INDEX-PRESENT.flist INDEX-NEW.flist > files.updated 197448ffe56aSColin Percival rm INDEX-PRESENT.flist INDEX-NEW.flist 197548ffe56aSColin Percival 197648ffe56aSColin Percival # Report removed files, if any 197748ffe56aSColin Percival if [ -s files.removed ]; then 197848ffe56aSColin Percival echo 197948ffe56aSColin Percival echo -n "The following files will be removed " 198048ffe56aSColin Percival echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" 198148ffe56aSColin Percival cat files.removed 19829c990fb2SGordon Tetlow fi | $PAGER 198348ffe56aSColin Percival rm files.removed 198448ffe56aSColin Percival 198548ffe56aSColin Percival # Report added files, if any 198648ffe56aSColin Percival if [ -s files.added ]; then 198748ffe56aSColin Percival echo 198848ffe56aSColin Percival echo -n "The following files will be added " 198948ffe56aSColin Percival echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" 199048ffe56aSColin Percival cat files.added 19919c990fb2SGordon Tetlow fi | $PAGER 199248ffe56aSColin Percival rm files.added 199348ffe56aSColin Percival 199448ffe56aSColin Percival # Report updated files, if any 199548ffe56aSColin Percival if [ -s files.updated ]; then 199648ffe56aSColin Percival echo 199748ffe56aSColin Percival echo -n "The following files will be updated " 199848ffe56aSColin Percival echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" 199948ffe56aSColin Percival 200048ffe56aSColin Percival cat files.updated 20019c990fb2SGordon Tetlow fi | $PAGER 200248ffe56aSColin Percival rm files.updated 200348ffe56aSColin Percival 200448ffe56aSColin Percival # Create a directory for the install manifest. 200548ffe56aSColin Percival MDIR=`mktemp -d install.XXXXXX` || return 1 200648ffe56aSColin Percival 200748ffe56aSColin Percival # Populate it 200848ffe56aSColin Percival mv INDEX-PRESENT ${MDIR}/INDEX-OLD 200948ffe56aSColin Percival mv INDEX-NEW ${MDIR}/INDEX-NEW 201048ffe56aSColin Percival 201148ffe56aSColin Percival # Link it into place 201248ffe56aSColin Percival ln -s ${MDIR} ${BDHASH}-install 201348ffe56aSColin Percival} 201448ffe56aSColin Percival 201548ffe56aSColin Percival# Warn about any upcoming EoL 201648ffe56aSColin Percivalfetch_warn_eol () { 201748ffe56aSColin Percival # What's the current time? 201848ffe56aSColin Percival NOWTIME=`date "+%s"` 201948ffe56aSColin Percival 202048ffe56aSColin Percival # When did we last warn about the EoL date? 202148ffe56aSColin Percival if [ -f lasteolwarn ]; then 202248ffe56aSColin Percival LASTWARN=`cat lasteolwarn` 202348ffe56aSColin Percival else 202448ffe56aSColin Percival LASTWARN=`expr ${NOWTIME} - 63072000` 202548ffe56aSColin Percival fi 202648ffe56aSColin Percival 202748ffe56aSColin Percival # If the EoL time is past, warn. 202848ffe56aSColin Percival if [ ${EOLTIME} -lt ${NOWTIME} ]; then 202948ffe56aSColin Percival echo 203048ffe56aSColin Percival cat <<-EOF 2031b698a3abSColin Percival WARNING: `uname -sr` HAS PASSED ITS END-OF-LIFE DATE. 203248ffe56aSColin Percival Any security issues discovered after `date -r ${EOLTIME}` 203348ffe56aSColin Percival will not have been corrected. 203448ffe56aSColin Percival EOF 203548ffe56aSColin Percival return 1 203648ffe56aSColin Percival fi 203748ffe56aSColin Percival 203848ffe56aSColin Percival # Figure out how long it has been since we last warned about the 203948ffe56aSColin Percival # upcoming EoL, and how much longer we have left. 204048ffe56aSColin Percival SINCEWARN=`expr ${NOWTIME} - ${LASTWARN}` 204148ffe56aSColin Percival TIMELEFT=`expr ${EOLTIME} - ${NOWTIME}` 204248ffe56aSColin Percival 204389b14566SColin Percival # Don't warn if the EoL is more than 3 months away 204489b14566SColin Percival if [ ${TIMELEFT} -gt 7884000 ]; then 204548ffe56aSColin Percival return 0 204648ffe56aSColin Percival fi 204748ffe56aSColin Percival 204848ffe56aSColin Percival # Don't warn if the time remaining is more than 3 times the time 204948ffe56aSColin Percival # since the last warning. 205048ffe56aSColin Percival if [ ${TIMELEFT} -gt `expr ${SINCEWARN} \* 3` ]; then 205148ffe56aSColin Percival return 0 205248ffe56aSColin Percival fi 205348ffe56aSColin Percival 205448ffe56aSColin Percival # Figure out what time units to use. 205548ffe56aSColin Percival if [ ${TIMELEFT} -lt 604800 ]; then 205648ffe56aSColin Percival UNIT="day" 205748ffe56aSColin Percival SIZE=86400 205848ffe56aSColin Percival elif [ ${TIMELEFT} -lt 2678400 ]; then 205948ffe56aSColin Percival UNIT="week" 206048ffe56aSColin Percival SIZE=604800 206148ffe56aSColin Percival else 206248ffe56aSColin Percival UNIT="month" 206348ffe56aSColin Percival SIZE=2678400 206448ffe56aSColin Percival fi 206548ffe56aSColin Percival 206648ffe56aSColin Percival # Compute the right number of units 206748ffe56aSColin Percival NUM=`expr ${TIMELEFT} / ${SIZE}` 206848ffe56aSColin Percival if [ ${NUM} != 1 ]; then 206948ffe56aSColin Percival UNIT="${UNIT}s" 207048ffe56aSColin Percival fi 207148ffe56aSColin Percival 207248ffe56aSColin Percival # Print the warning 207348ffe56aSColin Percival echo 207448ffe56aSColin Percival cat <<-EOF 207548ffe56aSColin Percival WARNING: `uname -sr` is approaching its End-of-Life date. 207648ffe56aSColin Percival It is strongly recommended that you upgrade to a newer 207748ffe56aSColin Percival release within the next ${NUM} ${UNIT}. 207848ffe56aSColin Percival EOF 207948ffe56aSColin Percival 208048ffe56aSColin Percival # Update the stored time of last warning 208148ffe56aSColin Percival echo ${NOWTIME} > lasteolwarn 208248ffe56aSColin Percival} 208348ffe56aSColin Percival 208448ffe56aSColin Percival# Do the actual work involved in "fetch" / "cron". 208548ffe56aSColin Percivalfetch_run () { 208648ffe56aSColin Percival workdir_init || return 1 208748ffe56aSColin Percival 208848ffe56aSColin Percival # Prepare the mirror list. 208948ffe56aSColin Percival fetch_pick_server_init && fetch_pick_server 209048ffe56aSColin Percival 209148ffe56aSColin Percival # Try to fetch the public key until we run out of servers. 209248ffe56aSColin Percival while ! fetch_key; do 209348ffe56aSColin Percival fetch_pick_server || return 1 209448ffe56aSColin Percival done 209548ffe56aSColin Percival 209648ffe56aSColin Percival # Try to fetch the metadata index signature ("tag") until we run 209748ffe56aSColin Percival # out of available servers; and sanity check the downloaded tag. 209848ffe56aSColin Percival while ! fetch_tag; do 209948ffe56aSColin Percival fetch_pick_server || return 1 210048ffe56aSColin Percival done 210148ffe56aSColin Percival fetch_tagsanity || return 1 210248ffe56aSColin Percival 210348ffe56aSColin Percival # Fetch the latest INDEX-NEW and INDEX-OLD files. 210448ffe56aSColin Percival fetch_metadata INDEX-NEW INDEX-OLD || return 1 210548ffe56aSColin Percival 210648ffe56aSColin Percival # Generate filtered INDEX-NEW and INDEX-OLD files containing only 210748ffe56aSColin Percival # the lines which (a) belong to components we care about, and (b) 210848ffe56aSColin Percival # don't correspond to paths we're explicitly ignoring. 210948ffe56aSColin Percival fetch_filter_metadata INDEX-NEW || return 1 211048ffe56aSColin Percival fetch_filter_metadata INDEX-OLD || return 1 211148ffe56aSColin Percival 2112db6b0a61SColin Percival # Translate /boot/${KERNCONF} into ${KERNELDIR} 2113db6b0a61SColin Percival fetch_filter_kernel_names INDEX-NEW ${KERNCONF} 2114db6b0a61SColin Percival fetch_filter_kernel_names INDEX-OLD ${KERNCONF} 211548ffe56aSColin Percival 211648ffe56aSColin Percival # For all paths appearing in INDEX-OLD or INDEX-NEW, inspect the 211748ffe56aSColin Percival # system and generate an INDEX-PRESENT file. 211848ffe56aSColin Percival fetch_inspect_system INDEX-OLD INDEX-PRESENT INDEX-NEW || return 1 211948ffe56aSColin Percival 212048ffe56aSColin Percival # Based on ${UPDATEIFUNMODIFIED}, remove lines from INDEX-* which 212148ffe56aSColin Percival # correspond to lines in INDEX-PRESENT with hashes not appearing 212248ffe56aSColin Percival # in INDEX-OLD or INDEX-NEW. Also remove lines where the entry in 212348ffe56aSColin Percival # INDEX-PRESENT has type - and there isn't a corresponding entry in 212448ffe56aSColin Percival # INDEX-OLD with type -. 2125db6b0a61SColin Percival fetch_filter_unmodified_notpresent \ 2126db6b0a61SColin Percival INDEX-OLD INDEX-PRESENT INDEX-NEW /dev/null 212748ffe56aSColin Percival 212848ffe56aSColin Percival # For each entry in INDEX-PRESENT of type -, remove any corresponding 212948ffe56aSColin Percival # entry from INDEX-NEW if ${ALLOWADD} != "yes". Remove all entries 213048ffe56aSColin Percival # of type - from INDEX-PRESENT. 213148ffe56aSColin Percival fetch_filter_allowadd INDEX-PRESENT INDEX-NEW 213248ffe56aSColin Percival 213348ffe56aSColin Percival # If ${ALLOWDELETE} != "yes", then remove any entries from 213448ffe56aSColin Percival # INDEX-PRESENT which don't correspond to entries in INDEX-NEW. 213548ffe56aSColin Percival fetch_filter_allowdelete INDEX-PRESENT INDEX-NEW 213648ffe56aSColin Percival 213748ffe56aSColin Percival # If ${KEEPMODIFIEDMETADATA} == "yes", then for each entry in 213848ffe56aSColin Percival # INDEX-PRESENT with metadata not matching any entry in INDEX-OLD, 213948ffe56aSColin Percival # replace the corresponding line of INDEX-NEW with one having the 214048ffe56aSColin Percival # same metadata as the entry in INDEX-PRESENT. 214148ffe56aSColin Percival fetch_filter_modified_metadata INDEX-OLD INDEX-PRESENT INDEX-NEW 214248ffe56aSColin Percival 214348ffe56aSColin Percival # Remove lines from INDEX-PRESENT and INDEX-NEW which are identical; 214448ffe56aSColin Percival # no need to update a file if it isn't changing. 214548ffe56aSColin Percival fetch_filter_uptodate INDEX-PRESENT INDEX-NEW 214648ffe56aSColin Percival 214748ffe56aSColin Percival # Prepare to fetch files: Generate a list of the files we need, 214848ffe56aSColin Percival # copy the unmodified files we have into /files/, and generate 214948ffe56aSColin Percival # a list of patches to download. 2150210b8123SColin Percival fetch_files_prepare INDEX-OLD INDEX-PRESENT INDEX-NEW || return 1 215148ffe56aSColin Percival 215248ffe56aSColin Percival # Fetch files. 215348ffe56aSColin Percival fetch_files || return 1 215448ffe56aSColin Percival 215548ffe56aSColin Percival # Create and populate install manifest directory; and report what 215648ffe56aSColin Percival # updates are available. 215748ffe56aSColin Percival fetch_create_manifest || return 1 215848ffe56aSColin Percival 215948ffe56aSColin Percival # Warn about any upcoming EoL 216048ffe56aSColin Percival fetch_warn_eol || return 1 216148ffe56aSColin Percival} 216248ffe56aSColin Percival 2163db6b0a61SColin Percival# If StrictComponents is not "yes", generate a new components list 2164db6b0a61SColin Percival# with only the components which appear to be installed. 2165db6b0a61SColin Percivalupgrade_guess_components () { 2166db6b0a61SColin Percival if [ "${STRICTCOMPONENTS}" = "no" ]; then 2167db6b0a61SColin Percival # Generate filtered INDEX-ALL with only the components listed 2168db6b0a61SColin Percival # in COMPONENTS. 2169db6b0a61SColin Percival fetch_filter_metadata_components $1 || return 1 2170db6b0a61SColin Percival 2171db6b0a61SColin Percival # Tell the user why his disk is suddenly making lots of noise 2172db6b0a61SColin Percival echo -n "Inspecting system... " 2173db6b0a61SColin Percival 2174db6b0a61SColin Percival # Look at the files on disk, and assume that a component is 2175db6b0a61SColin Percival # supposed to be present if it is more than half-present. 2176db6b0a61SColin Percival cut -f 1-3 -d '|' < INDEX-ALL | 2177db6b0a61SColin Percival tr '|' ' ' | 2178db6b0a61SColin Percival while read C S F; do 2179db6b0a61SColin Percival if [ -e ${BASEDIR}/${F} ]; then 2180db6b0a61SColin Percival echo "+ ${C}|${S}" 2181db6b0a61SColin Percival fi 2182db6b0a61SColin Percival echo "= ${C}|${S}" 2183db6b0a61SColin Percival done | 2184db6b0a61SColin Percival sort | 2185db6b0a61SColin Percival uniq -c | 2186db6b0a61SColin Percival sed -E 's,^ +,,' > compfreq 2187db6b0a61SColin Percival grep ' = ' compfreq | 2188db6b0a61SColin Percival cut -f 1,3 -d ' ' | 2189db6b0a61SColin Percival sort -k 2,2 -t ' ' > compfreq.total 2190db6b0a61SColin Percival grep ' + ' compfreq | 2191db6b0a61SColin Percival cut -f 1,3 -d ' ' | 2192db6b0a61SColin Percival sort -k 2,2 -t ' ' > compfreq.present 2193db6b0a61SColin Percival join -t ' ' -1 2 -2 2 compfreq.present compfreq.total | 2194db6b0a61SColin Percival while read S P T; do 2195db6b0a61SColin Percival if [ ${P} -gt `expr ${T} / 2` ]; then 2196db6b0a61SColin Percival echo ${S} 2197db6b0a61SColin Percival fi 2198db6b0a61SColin Percival done > comp.present 2199db6b0a61SColin Percival cut -f 2 -d ' ' < compfreq.total > comp.total 2200db6b0a61SColin Percival rm INDEX-ALL compfreq compfreq.total compfreq.present 2201db6b0a61SColin Percival 2202db6b0a61SColin Percival # We're done making noise. 2203db6b0a61SColin Percival echo "done." 2204db6b0a61SColin Percival 2205db6b0a61SColin Percival # Sometimes the kernel isn't installed where INDEX-ALL 2206db6b0a61SColin Percival # thinks that it should be: In particular, it is often in 2207db6b0a61SColin Percival # /boot/kernel instead of /boot/GENERIC or /boot/SMP. To 2208db6b0a61SColin Percival # deal with this, if "kernel|X" is listed in comp.total 2209db6b0a61SColin Percival # (i.e., is a component which would be upgraded if it is 2210db6b0a61SColin Percival # found to be present) we will add it to comp.present. 2211db6b0a61SColin Percival # If "kernel|<anything>" is in comp.total but "kernel|X" is 2212db6b0a61SColin Percival # not, we print a warning -- the user is running a kernel 2213db6b0a61SColin Percival # which isn't part of the release. 2214db6b0a61SColin Percival KCOMP=`echo ${KERNCONF} | tr 'A-Z' 'a-z'` 2215db6b0a61SColin Percival grep -E "^kernel\|${KCOMP}\$" comp.total >> comp.present 2216db6b0a61SColin Percival 2217db6b0a61SColin Percival if grep -qE "^kernel\|" comp.total && 2218db6b0a61SColin Percival ! grep -qE "^kernel\|${KCOMP}\$" comp.total; then 2219db6b0a61SColin Percival cat <<-EOF 2220db6b0a61SColin Percival 2221db6b0a61SColin PercivalWARNING: This system is running a "${KCOMP}" kernel, which is not a 2222db6b0a61SColin Percivalkernel configuration distributed as part of FreeBSD ${RELNUM}. 2223db6b0a61SColin PercivalThis kernel will not be updated: you MUST update the kernel manually 2224db6b0a61SColin Percivalbefore running "$0 install". 2225db6b0a61SColin Percival EOF 2226db6b0a61SColin Percival fi 2227db6b0a61SColin Percival 2228db6b0a61SColin Percival # Re-sort the list of installed components and generate 2229db6b0a61SColin Percival # the list of non-installed components. 2230db6b0a61SColin Percival sort -u < comp.present > comp.present.tmp 2231db6b0a61SColin Percival mv comp.present.tmp comp.present 2232db6b0a61SColin Percival comm -13 comp.present comp.total > comp.absent 2233db6b0a61SColin Percival 2234db6b0a61SColin Percival # Ask the user to confirm that what we have is correct. To 2235db6b0a61SColin Percival # reduce user confusion, translate "X|Y" back to "X/Y" (as 2236db6b0a61SColin Percival # subcomponents must be listed in the configuration file). 2237db6b0a61SColin Percival echo 2238db6b0a61SColin Percival echo -n "The following components of FreeBSD " 2239db6b0a61SColin Percival echo "seem to be installed:" 2240db6b0a61SColin Percival tr '|' '/' < comp.present | 2241db6b0a61SColin Percival fmt -72 2242db6b0a61SColin Percival echo 2243db6b0a61SColin Percival echo -n "The following components of FreeBSD " 2244db6b0a61SColin Percival echo "do not seem to be installed:" 2245db6b0a61SColin Percival tr '|' '/' < comp.absent | 2246db6b0a61SColin Percival fmt -72 2247db6b0a61SColin Percival echo 2248db6b0a61SColin Percival continuep || return 1 2249db6b0a61SColin Percival echo 2250db6b0a61SColin Percival 2251db6b0a61SColin Percival # Suck the generated list of components into ${COMPONENTS}. 2252db6b0a61SColin Percival # Note that comp.present.tmp is used due to issues with 2253db6b0a61SColin Percival # pipelines and setting variables. 2254db6b0a61SColin Percival COMPONENTS="" 2255db6b0a61SColin Percival tr '|' '/' < comp.present > comp.present.tmp 2256db6b0a61SColin Percival while read C; do 2257db6b0a61SColin Percival COMPONENTS="${COMPONENTS} ${C}" 2258db6b0a61SColin Percival done < comp.present.tmp 2259db6b0a61SColin Percival 2260db6b0a61SColin Percival # Delete temporary files 2261db6b0a61SColin Percival rm comp.present comp.present.tmp comp.absent comp.total 2262db6b0a61SColin Percival fi 2263db6b0a61SColin Percival} 2264db6b0a61SColin Percival 2265db6b0a61SColin Percival# If StrictComponents is not "yes", COMPONENTS contains an entry 2266db6b0a61SColin Percival# corresponding to the currently running kernel, and said kernel 2267db6b0a61SColin Percival# does not exist in the new release, add "kernel/generic" to the 2268db6b0a61SColin Percival# list of components. 2269db6b0a61SColin Percivalupgrade_guess_new_kernel () { 2270db6b0a61SColin Percival if [ "${STRICTCOMPONENTS}" = "no" ]; then 2271db6b0a61SColin Percival # Grab the unfiltered metadata file. 2272db6b0a61SColin Percival METAHASH=`look "$1|" tINDEX.present | cut -f 2 -d '|'` 2273db6b0a61SColin Percival gunzip -c < files/${METAHASH}.gz > $1.all 2274db6b0a61SColin Percival 2275db6b0a61SColin Percival # If "kernel/${KCOMP}" is in ${COMPONENTS} and that component 2276db6b0a61SColin Percival # isn't in $1.all, we need to add kernel/generic. 2277db6b0a61SColin Percival for C in ${COMPONENTS}; do 2278db6b0a61SColin Percival if [ ${C} = "kernel/${KCOMP}" ] && 2279db6b0a61SColin Percival ! grep -qE "^kernel\|${KCOMP}\|" $1.all; then 2280db6b0a61SColin Percival COMPONENTS="${COMPONENTS} kernel/generic" 2281db6b0a61SColin Percival NKERNCONF="GENERIC" 2282db6b0a61SColin Percival cat <<-EOF 2283db6b0a61SColin Percival 2284db6b0a61SColin PercivalWARNING: This system is running a "${KCOMP}" kernel, which is not a 2285db6b0a61SColin Percivalkernel configuration distributed as part of FreeBSD ${RELNUM}. 2286db6b0a61SColin PercivalAs part of upgrading to FreeBSD ${RELNUM}, this kernel will be 2287db6b0a61SColin Percivalreplaced with a "generic" kernel. 2288db6b0a61SColin Percival EOF 2289db6b0a61SColin Percival continuep || return 1 2290db6b0a61SColin Percival fi 2291db6b0a61SColin Percival done 2292db6b0a61SColin Percival 2293db6b0a61SColin Percival # Don't need this any more... 2294db6b0a61SColin Percival rm $1.all 2295db6b0a61SColin Percival fi 2296db6b0a61SColin Percival} 2297db6b0a61SColin Percival 2298db6b0a61SColin Percival# Convert INDEX-OLD (last release) and INDEX-ALL (new release) into 2299db6b0a61SColin Percival# INDEX-OLD and INDEX-NEW files (in the sense of normal upgrades). 2300db6b0a61SColin Percivalupgrade_oldall_to_oldnew () { 2301db6b0a61SColin Percival # For each ${F}|... which appears in INDEX-ALL but does not appear 2302db6b0a61SColin Percival # in INDEX-OLD, add ${F}|-|||||| to INDEX-OLD. 2303db6b0a61SColin Percival cut -f 1 -d '|' < $1 | 2304db6b0a61SColin Percival sort -u > $1.paths 2305db6b0a61SColin Percival cut -f 1 -d '|' < $2 | 2306db6b0a61SColin Percival sort -u | 2307db6b0a61SColin Percival comm -13 $1.paths - | 2308db6b0a61SColin Percival lam - -s "|-||||||" | 2309db6b0a61SColin Percival sort - $1 > $1.tmp 2310db6b0a61SColin Percival mv $1.tmp $1 2311db6b0a61SColin Percival 2312db6b0a61SColin Percival # Remove lines from INDEX-OLD which also appear in INDEX-ALL 2313db6b0a61SColin Percival comm -23 $1 $2 > $1.tmp 2314db6b0a61SColin Percival mv $1.tmp $1 2315db6b0a61SColin Percival 2316db6b0a61SColin Percival # Remove lines from INDEX-ALL which have a file name not appearing 2317db6b0a61SColin Percival # anywhere in INDEX-OLD (since these must be files which haven't 2318db6b0a61SColin Percival # changed -- if they were new, there would be an entry of type "-"). 2319db6b0a61SColin Percival cut -f 1 -d '|' < $1 | 2320db6b0a61SColin Percival sort -u > $1.paths 2321db6b0a61SColin Percival sort -k 1,1 -t '|' < $2 | 2322db6b0a61SColin Percival join -t '|' - $1.paths | 2323db6b0a61SColin Percival sort > $2.tmp 2324db6b0a61SColin Percival rm $1.paths 2325db6b0a61SColin Percival mv $2.tmp $2 2326db6b0a61SColin Percival 2327db6b0a61SColin Percival # Rename INDEX-ALL to INDEX-NEW. 2328db6b0a61SColin Percival mv $2 $3 2329db6b0a61SColin Percival} 2330db6b0a61SColin Percival 23317449d2f5SColin Percival# Helper for upgrade_merge: Return zero true iff the two files differ only 23326d514f10SDag-Erling Smørgrav# in the contents of their RCS tags. 23337449d2f5SColin Percivalsamef () { 23347449d2f5SColin Percival X=`sed -E 's/\\$FreeBSD.*\\$/\$FreeBSD\$/' < $1 | ${SHA256}` 23357449d2f5SColin Percival Y=`sed -E 's/\\$FreeBSD.*\\$/\$FreeBSD\$/' < $2 | ${SHA256}` 23367449d2f5SColin Percival 23377449d2f5SColin Percival if [ $X = $Y ]; then 23387449d2f5SColin Percival return 0; 23397449d2f5SColin Percival else 23407449d2f5SColin Percival return 1; 23417449d2f5SColin Percival fi 23427449d2f5SColin Percival} 23437449d2f5SColin Percival 2344db6b0a61SColin Percival# From the list of "old" files in $1, merge changes in $2 with those in $3, 2345db6b0a61SColin Percival# and update $3 to reflect the hashes of merged files. 2346db6b0a61SColin Percivalupgrade_merge () { 2347db6b0a61SColin Percival # We only need to do anything if $1 is non-empty. 2348db6b0a61SColin Percival if [ -s $1 ]; then 2349db6b0a61SColin Percival cut -f 1 -d '|' $1 | 2350db6b0a61SColin Percival sort > $1-paths 2351db6b0a61SColin Percival 2352db6b0a61SColin Percival # Create staging area for merging files 2353db6b0a61SColin Percival rm -rf merge/ 2354db6b0a61SColin Percival while read F; do 2355db6b0a61SColin Percival D=`dirname ${F}` 2356db6b0a61SColin Percival mkdir -p merge/old/${D} 2357db6b0a61SColin Percival mkdir -p merge/${OLDRELNUM}/${D} 2358db6b0a61SColin Percival mkdir -p merge/${RELNUM}/${D} 2359db6b0a61SColin Percival mkdir -p merge/new/${D} 2360db6b0a61SColin Percival done < $1-paths 2361db6b0a61SColin Percival 2362db6b0a61SColin Percival # Copy in files 2363db6b0a61SColin Percival while read F; do 2364db6b0a61SColin Percival # Currently installed file 2365db6b0a61SColin Percival V=`look "${F}|" $2 | cut -f 7 -d '|'` 2366db6b0a61SColin Percival gunzip < files/${V}.gz > merge/old/${F} 2367db6b0a61SColin Percival 2368db6b0a61SColin Percival # Old release 2369db6b0a61SColin Percival if look "${F}|" $1 | fgrep -q "|f|"; then 2370db6b0a61SColin Percival V=`look "${F}|" $1 | cut -f 3 -d '|'` 2371db6b0a61SColin Percival gunzip < files/${V}.gz \ 2372db6b0a61SColin Percival > merge/${OLDRELNUM}/${F} 2373db6b0a61SColin Percival fi 2374db6b0a61SColin Percival 2375db6b0a61SColin Percival # New release 2376db6b0a61SColin Percival if look "${F}|" $3 | cut -f 1,2,7 -d '|' | 2377db6b0a61SColin Percival fgrep -q "|f|"; then 2378db6b0a61SColin Percival V=`look "${F}|" $3 | cut -f 7 -d '|'` 2379db6b0a61SColin Percival gunzip < files/${V}.gz \ 2380db6b0a61SColin Percival > merge/${RELNUM}/${F} 2381db6b0a61SColin Percival fi 2382db6b0a61SColin Percival done < $1-paths 2383db6b0a61SColin Percival 2384db6b0a61SColin Percival # Attempt to automatically merge changes 2385db6b0a61SColin Percival echo -n "Attempting to automatically merge " 2386db6b0a61SColin Percival echo -n "changes in files..." 2387db6b0a61SColin Percival : > failed.merges 2388db6b0a61SColin Percival while read F; do 2389db6b0a61SColin Percival # If the file doesn't exist in the new release, 2390db6b0a61SColin Percival # the result of "merging changes" is having the file 2391db6b0a61SColin Percival # not exist. 2392db6b0a61SColin Percival if ! [ -f merge/${RELNUM}/${F} ]; then 2393db6b0a61SColin Percival continue 2394db6b0a61SColin Percival fi 2395db6b0a61SColin Percival 2396db6b0a61SColin Percival # If the file didn't exist in the old release, we're 2397db6b0a61SColin Percival # going to throw away the existing file and hope that 2398db6b0a61SColin Percival # the version from the new release is what we want. 2399db6b0a61SColin Percival if ! [ -f merge/${OLDRELNUM}/${F} ]; then 2400db6b0a61SColin Percival cp merge/${RELNUM}/${F} merge/new/${F} 2401db6b0a61SColin Percival continue 2402db6b0a61SColin Percival fi 2403db6b0a61SColin Percival 2404db6b0a61SColin Percival # Some files need special treatment. 2405db6b0a61SColin Percival case ${F} in 2406db6b0a61SColin Percival /etc/spwd.db | /etc/pwd.db | /etc/login.conf.db) 2407db6b0a61SColin Percival # Don't merge these -- we're rebuild them 2408db6b0a61SColin Percival # after updates are installed. 2409db6b0a61SColin Percival cp merge/old/${F} merge/new/${F} 2410db6b0a61SColin Percival ;; 2411db6b0a61SColin Percival *) 2412073dd712SBaptiste Daroussin if ! diff3 -E -m -L "current version" \ 2413db6b0a61SColin Percival -L "${OLDRELNUM}" -L "${RELNUM}" \ 2414db6b0a61SColin Percival merge/old/${F} \ 2415db6b0a61SColin Percival merge/${OLDRELNUM}/${F} \ 2416db6b0a61SColin Percival merge/${RELNUM}/${F} \ 2417db6b0a61SColin Percival > merge/new/${F} 2>/dev/null; then 2418db6b0a61SColin Percival echo ${F} >> failed.merges 2419db6b0a61SColin Percival fi 2420db6b0a61SColin Percival ;; 2421db6b0a61SColin Percival esac 2422db6b0a61SColin Percival done < $1-paths 2423db6b0a61SColin Percival echo " done." 2424db6b0a61SColin Percival 2425db6b0a61SColin Percival # Ask the user to handle any files which didn't merge. 2426db6b0a61SColin Percival while read F; do 24277449d2f5SColin Percival # If the installed file differs from the version in 24286d514f10SDag-Erling Smørgrav # the old release only due to RCS tag expansion 24297449d2f5SColin Percival # then just use the version in the new release. 24307449d2f5SColin Percival if samef merge/old/${F} merge/${OLDRELNUM}/${F}; then 24317449d2f5SColin Percival cp merge/${RELNUM}/${F} merge/new/${F} 24327449d2f5SColin Percival continue 24337449d2f5SColin Percival fi 24347449d2f5SColin Percival 2435db6b0a61SColin Percival cat <<-EOF 2436db6b0a61SColin Percival 2437db6b0a61SColin PercivalThe following file could not be merged automatically: ${F} 2438db6b0a61SColin PercivalPress Enter to edit this file in ${EDITOR} and resolve the conflicts 2439db6b0a61SColin Percivalmanually... 2440db6b0a61SColin Percival EOF 2441db6b0a61SColin Percival read dummy </dev/tty 2442db6b0a61SColin Percival ${EDITOR} `pwd`/merge/new/${F} < /dev/tty 2443db6b0a61SColin Percival done < failed.merges 2444db6b0a61SColin Percival rm failed.merges 2445db6b0a61SColin Percival 2446db6b0a61SColin Percival # Ask the user to confirm that he likes how the result 2447db6b0a61SColin Percival # of merging files. 2448db6b0a61SColin Percival while read F; do 24497449d2f5SColin Percival # Skip files which haven't changed except possibly 24506d514f10SDag-Erling Smørgrav # in their RCS tags. 24517449d2f5SColin Percival if [ -f merge/old/${F} ] && [ -f merge/new/${F} ] && 24527449d2f5SColin Percival samef merge/old/${F} merge/new/${F}; then 24537449d2f5SColin Percival continue 24547449d2f5SColin Percival fi 24557449d2f5SColin Percival 24567449d2f5SColin Percival # Skip files where the installed file differs from 24576d514f10SDag-Erling Smørgrav # the old file only due to RCS tags. 24587449d2f5SColin Percival if [ -f merge/old/${F} ] && 24597449d2f5SColin Percival [ -f merge/${OLDRELNUM}/${F} ] && 24607449d2f5SColin Percival samef merge/old/${F} merge/${OLDRELNUM}/${F}; then 2461db6b0a61SColin Percival continue 2462db6b0a61SColin Percival fi 2463db6b0a61SColin Percival 2464db6b0a61SColin Percival # Warn about files which are ceasing to exist. 2465db6b0a61SColin Percival if ! [ -f merge/new/${F} ]; then 2466db6b0a61SColin Percival cat <<-EOF 2467db6b0a61SColin Percival 2468db6b0a61SColin PercivalThe following file will be removed, as it no longer exists in 2469db6b0a61SColin PercivalFreeBSD ${RELNUM}: ${F} 2470db6b0a61SColin Percival EOF 2471db6b0a61SColin Percival continuep < /dev/tty || return 1 2472db6b0a61SColin Percival continue 2473db6b0a61SColin Percival fi 2474db6b0a61SColin Percival 2475db6b0a61SColin Percival # Print changes for the user's approval. 2476db6b0a61SColin Percival cat <<-EOF 2477db6b0a61SColin Percival 2478db6b0a61SColin PercivalThe following changes, which occurred between FreeBSD ${OLDRELNUM} and 2479db6b0a61SColin PercivalFreeBSD ${RELNUM} have been merged into ${F}: 2480db6b0a61SColin PercivalEOF 2481db6b0a61SColin Percival diff -U 5 -L "current version" -L "new version" \ 2482db6b0a61SColin Percival merge/old/${F} merge/new/${F} || true 2483db6b0a61SColin Percival continuep < /dev/tty || return 1 2484db6b0a61SColin Percival done < $1-paths 2485db6b0a61SColin Percival 2486db6b0a61SColin Percival # Store merged files. 2487db6b0a61SColin Percival while read F; do 2488c58b62efSColin Percival if [ -f merge/new/${F} ]; then 2489db6b0a61SColin Percival V=`${SHA256} -q merge/new/${F}` 2490db6b0a61SColin Percival 2491db6b0a61SColin Percival gzip -c < merge/new/${F} > files/${V}.gz 2492db6b0a61SColin Percival echo "${F}|${V}" 2493db6b0a61SColin Percival fi 2494db6b0a61SColin Percival done < $1-paths > newhashes 2495db6b0a61SColin Percival 2496db6b0a61SColin Percival # Pull lines out from $3 which need to be updated to 2497db6b0a61SColin Percival # reflect merged files. 2498db6b0a61SColin Percival while read F; do 2499db6b0a61SColin Percival look "${F}|" $3 2500db6b0a61SColin Percival done < $1-paths > $3-oldlines 2501db6b0a61SColin Percival 2502db6b0a61SColin Percival # Update lines to reflect merged files 2503db6b0a61SColin Percival join -t '|' -o 1.1,1.2,1.3,1.4,1.5,1.6,2.2,1.8 \ 2504db6b0a61SColin Percival $3-oldlines newhashes > $3-newlines 2505db6b0a61SColin Percival 2506db6b0a61SColin Percival # Remove old lines from $3 and add new lines. 2507db6b0a61SColin Percival sort $3-oldlines | 2508db6b0a61SColin Percival comm -13 - $3 | 2509db6b0a61SColin Percival sort - $3-newlines > $3.tmp 2510db6b0a61SColin Percival mv $3.tmp $3 2511db6b0a61SColin Percival 2512db6b0a61SColin Percival # Clean up 2513db6b0a61SColin Percival rm $1-paths newhashes $3-oldlines $3-newlines 2514db6b0a61SColin Percival rm -rf merge/ 2515db6b0a61SColin Percival fi 2516db6b0a61SColin Percival 2517db6b0a61SColin Percival # We're done with merging files. 2518db6b0a61SColin Percival rm $1 2519db6b0a61SColin Percival} 2520db6b0a61SColin Percival 2521db6b0a61SColin Percival# Do the work involved in fetching upgrades to a new release 2522db6b0a61SColin Percivalupgrade_run () { 2523db6b0a61SColin Percival workdir_init || return 1 2524db6b0a61SColin Percival 2525db6b0a61SColin Percival # Prepare the mirror list. 2526db6b0a61SColin Percival fetch_pick_server_init && fetch_pick_server 2527db6b0a61SColin Percival 2528db6b0a61SColin Percival # Try to fetch the public key until we run out of servers. 2529db6b0a61SColin Percival while ! fetch_key; do 2530db6b0a61SColin Percival fetch_pick_server || return 1 2531db6b0a61SColin Percival done 2532db6b0a61SColin Percival 2533db6b0a61SColin Percival # Try to fetch the metadata index signature ("tag") until we run 2534db6b0a61SColin Percival # out of available servers; and sanity check the downloaded tag. 2535db6b0a61SColin Percival while ! fetch_tag; do 2536db6b0a61SColin Percival fetch_pick_server || return 1 2537db6b0a61SColin Percival done 2538db6b0a61SColin Percival fetch_tagsanity || return 1 2539db6b0a61SColin Percival 2540db6b0a61SColin Percival # Fetch the INDEX-OLD and INDEX-ALL. 2541db6b0a61SColin Percival fetch_metadata INDEX-OLD INDEX-ALL || return 1 2542db6b0a61SColin Percival 2543db6b0a61SColin Percival # If StrictComponents is not "yes", generate a new components list 2544db6b0a61SColin Percival # with only the components which appear to be installed. 2545db6b0a61SColin Percival upgrade_guess_components INDEX-ALL || return 1 2546db6b0a61SColin Percival 2547db6b0a61SColin Percival # Generate filtered INDEX-OLD and INDEX-ALL files containing only 2548db6b0a61SColin Percival # the components we want and without anything marked as "Ignore". 2549db6b0a61SColin Percival fetch_filter_metadata INDEX-OLD || return 1 2550db6b0a61SColin Percival fetch_filter_metadata INDEX-ALL || return 1 2551db6b0a61SColin Percival 2552db6b0a61SColin Percival # Merge the INDEX-OLD and INDEX-ALL files into INDEX-OLD. 2553db6b0a61SColin Percival sort INDEX-OLD INDEX-ALL > INDEX-OLD.tmp 2554db6b0a61SColin Percival mv INDEX-OLD.tmp INDEX-OLD 2555db6b0a61SColin Percival rm INDEX-ALL 2556db6b0a61SColin Percival 2557db6b0a61SColin Percival # Adjust variables for fetching files from the new release. 2558db6b0a61SColin Percival OLDRELNUM=${RELNUM} 2559db6b0a61SColin Percival RELNUM=${TARGETRELEASE} 2560db6b0a61SColin Percival OLDFETCHDIR=${FETCHDIR} 2561db6b0a61SColin Percival FETCHDIR=${RELNUM}/${ARCH} 2562db6b0a61SColin Percival 2563db6b0a61SColin Percival # Try to fetch the NEW metadata index signature ("tag") until we run 2564db6b0a61SColin Percival # out of available servers; and sanity check the downloaded tag. 2565db6b0a61SColin Percival while ! fetch_tag; do 2566db6b0a61SColin Percival fetch_pick_server || return 1 2567db6b0a61SColin Percival done 2568db6b0a61SColin Percival 2569db6b0a61SColin Percival # Fetch the new INDEX-ALL. 2570db6b0a61SColin Percival fetch_metadata INDEX-ALL || return 1 2571db6b0a61SColin Percival 2572db6b0a61SColin Percival # If StrictComponents is not "yes", COMPONENTS contains an entry 2573db6b0a61SColin Percival # corresponding to the currently running kernel, and said kernel 2574db6b0a61SColin Percival # does not exist in the new release, add "kernel/generic" to the 2575db6b0a61SColin Percival # list of components. 2576db6b0a61SColin Percival upgrade_guess_new_kernel INDEX-ALL || return 1 2577db6b0a61SColin Percival 2578db6b0a61SColin Percival # Filter INDEX-ALL to contain only the components we want and without 2579db6b0a61SColin Percival # anything marked as "Ignore". 2580db6b0a61SColin Percival fetch_filter_metadata INDEX-ALL || return 1 2581db6b0a61SColin Percival 2582db6b0a61SColin Percival # Convert INDEX-OLD (last release) and INDEX-ALL (new release) into 2583db6b0a61SColin Percival # INDEX-OLD and INDEX-NEW files (in the sense of normal upgrades). 2584db6b0a61SColin Percival upgrade_oldall_to_oldnew INDEX-OLD INDEX-ALL INDEX-NEW 2585db6b0a61SColin Percival 2586db6b0a61SColin Percival # Translate /boot/${KERNCONF} or /boot/${NKERNCONF} into ${KERNELDIR} 2587db6b0a61SColin Percival fetch_filter_kernel_names INDEX-NEW ${NKERNCONF} 2588db6b0a61SColin Percival fetch_filter_kernel_names INDEX-OLD ${KERNCONF} 2589db6b0a61SColin Percival 2590db6b0a61SColin Percival # For all paths appearing in INDEX-OLD or INDEX-NEW, inspect the 2591db6b0a61SColin Percival # system and generate an INDEX-PRESENT file. 2592db6b0a61SColin Percival fetch_inspect_system INDEX-OLD INDEX-PRESENT INDEX-NEW || return 1 2593db6b0a61SColin Percival 2594db6b0a61SColin Percival # Based on ${MERGECHANGES}, generate a file tomerge-old with the 2595db6b0a61SColin Percival # paths and hashes of old versions of files to merge. 2596db6b0a61SColin Percival fetch_filter_mergechanges INDEX-OLD INDEX-PRESENT tomerge-old 2597db6b0a61SColin Percival 2598db6b0a61SColin Percival # Based on ${UPDATEIFUNMODIFIED}, remove lines from INDEX-* which 2599db6b0a61SColin Percival # correspond to lines in INDEX-PRESENT with hashes not appearing 2600db6b0a61SColin Percival # in INDEX-OLD or INDEX-NEW. Also remove lines where the entry in 2601db6b0a61SColin Percival # INDEX-PRESENT has type - and there isn't a corresponding entry in 2602db6b0a61SColin Percival # INDEX-OLD with type -. 2603db6b0a61SColin Percival fetch_filter_unmodified_notpresent \ 2604db6b0a61SColin Percival INDEX-OLD INDEX-PRESENT INDEX-NEW tomerge-old 2605db6b0a61SColin Percival 2606db6b0a61SColin Percival # For each entry in INDEX-PRESENT of type -, remove any corresponding 2607db6b0a61SColin Percival # entry from INDEX-NEW if ${ALLOWADD} != "yes". Remove all entries 2608db6b0a61SColin Percival # of type - from INDEX-PRESENT. 2609db6b0a61SColin Percival fetch_filter_allowadd INDEX-PRESENT INDEX-NEW 2610db6b0a61SColin Percival 2611db6b0a61SColin Percival # If ${ALLOWDELETE} != "yes", then remove any entries from 2612db6b0a61SColin Percival # INDEX-PRESENT which don't correspond to entries in INDEX-NEW. 2613db6b0a61SColin Percival fetch_filter_allowdelete INDEX-PRESENT INDEX-NEW 2614db6b0a61SColin Percival 2615db6b0a61SColin Percival # If ${KEEPMODIFIEDMETADATA} == "yes", then for each entry in 2616db6b0a61SColin Percival # INDEX-PRESENT with metadata not matching any entry in INDEX-OLD, 2617db6b0a61SColin Percival # replace the corresponding line of INDEX-NEW with one having the 2618db6b0a61SColin Percival # same metadata as the entry in INDEX-PRESENT. 2619db6b0a61SColin Percival fetch_filter_modified_metadata INDEX-OLD INDEX-PRESENT INDEX-NEW 2620db6b0a61SColin Percival 2621db6b0a61SColin Percival # Remove lines from INDEX-PRESENT and INDEX-NEW which are identical; 2622db6b0a61SColin Percival # no need to update a file if it isn't changing. 2623db6b0a61SColin Percival fetch_filter_uptodate INDEX-PRESENT INDEX-NEW 2624db6b0a61SColin Percival 2625db6b0a61SColin Percival # Fetch "clean" files from the old release for merging changes. 2626db6b0a61SColin Percival fetch_files_premerge tomerge-old 2627db6b0a61SColin Percival 2628db6b0a61SColin Percival # Prepare to fetch files: Generate a list of the files we need, 2629db6b0a61SColin Percival # copy the unmodified files we have into /files/, and generate 2630db6b0a61SColin Percival # a list of patches to download. 2631db6b0a61SColin Percival fetch_files_prepare INDEX-OLD INDEX-PRESENT INDEX-NEW || return 1 2632db6b0a61SColin Percival 2633db6b0a61SColin Percival # Fetch patches from to-${RELNUM}/${ARCH}/bp/ 2634db6b0a61SColin Percival PATCHDIR=to-${RELNUM}/${ARCH}/bp 2635db6b0a61SColin Percival fetch_files || return 1 2636db6b0a61SColin Percival 2637db6b0a61SColin Percival # Merge configuration file changes. 2638db6b0a61SColin Percival upgrade_merge tomerge-old INDEX-PRESENT INDEX-NEW || return 1 2639db6b0a61SColin Percival 2640db6b0a61SColin Percival # Create and populate install manifest directory; and report what 2641db6b0a61SColin Percival # updates are available. 2642db6b0a61SColin Percival fetch_create_manifest || return 1 2643db6b0a61SColin Percival 2644db6b0a61SColin Percival # Leave a note behind to tell the "install" command that the kernel 2645db6b0a61SColin Percival # needs to be installed before the world. 2646db6b0a61SColin Percival touch ${BDHASH}-install/kernelfirst 264785451f90SColin Percival 264885451f90SColin Percival # Remind the user that they need to run "freebsd-update install" 264985451f90SColin Percival # to install the downloaded bits, in case they didn't RTFM. 265085451f90SColin Percival echo "To install the downloaded upgrades, run \"$0 install\"." 2651db6b0a61SColin Percival} 2652db6b0a61SColin Percival 265348ffe56aSColin Percival# Make sure that all the file hashes mentioned in $@ have corresponding 265448ffe56aSColin Percival# gzipped files stored in /files/. 265548ffe56aSColin Percivalinstall_verify () { 265648ffe56aSColin Percival # Generate a list of hashes 265748ffe56aSColin Percival cat $@ | 265848ffe56aSColin Percival cut -f 2,7 -d '|' | 265948ffe56aSColin Percival grep -E '^f' | 266048ffe56aSColin Percival cut -f 2 -d '|' | 266148ffe56aSColin Percival sort -u > filelist 266248ffe56aSColin Percival 266348ffe56aSColin Percival # Make sure all the hashes exist 266448ffe56aSColin Percival while read HASH; do 266548ffe56aSColin Percival if ! [ -f files/${HASH}.gz ]; then 266648ffe56aSColin Percival echo -n "Update files missing -- " 266748ffe56aSColin Percival echo "this should never happen." 266848ffe56aSColin Percival echo "Re-run '$0 fetch'." 266948ffe56aSColin Percival return 1 267048ffe56aSColin Percival fi 267148ffe56aSColin Percival done < filelist 267248ffe56aSColin Percival 267348ffe56aSColin Percival # Clean up 267448ffe56aSColin Percival rm filelist 267548ffe56aSColin Percival} 267648ffe56aSColin Percival 267748ffe56aSColin Percival# Remove the system immutable flag from files 267848ffe56aSColin Percivalinstall_unschg () { 267948ffe56aSColin Percival # Generate file list 268048ffe56aSColin Percival cat $@ | 268148ffe56aSColin Percival cut -f 1 -d '|' > filelist 268248ffe56aSColin Percival 268348ffe56aSColin Percival # Remove flags 268448ffe56aSColin Percival while read F; do 2685e829ed67SColin Percival if ! [ -e ${BASEDIR}/${F} ]; then 268648ffe56aSColin Percival continue 26875a74378cSXin LI else 26885a74378cSXin LI echo ${BASEDIR}/${F} 268948ffe56aSColin Percival fi 26905a74378cSXin LI done < filelist | xargs chflags noschg || return 1 269148ffe56aSColin Percival 269248ffe56aSColin Percival # Clean up 269348ffe56aSColin Percival rm filelist 269448ffe56aSColin Percival} 269548ffe56aSColin Percival 269623d827efSSimon L. B. Nielsen# Decide which directory name to use for kernel backups. 269723d827efSSimon L. B. Nielsenbackup_kernel_finddir () { 269823d827efSSimon L. B. Nielsen CNT=0 269923d827efSSimon L. B. Nielsen while true ; do 270023d827efSSimon L. B. Nielsen # Pathname does not exist, so it is OK use that name 270123d827efSSimon L. B. Nielsen # for backup directory. 2702c4a0c62cSThomas Quinot if [ ! -e $BASEDIR/$BACKUPKERNELDIR ]; then 270323d827efSSimon L. B. Nielsen return 0 270423d827efSSimon L. B. Nielsen fi 270523d827efSSimon L. B. Nielsen 270623d827efSSimon L. B. Nielsen # If directory do exist, we only use if it has our 270723d827efSSimon L. B. Nielsen # marker file. 2708c4a0c62cSThomas Quinot if [ -d $BASEDIR/$BACKUPKERNELDIR -a \ 2709c4a0c62cSThomas Quinot -e $BASEDIR/$BACKUPKERNELDIR/.freebsd-update ]; then 271023d827efSSimon L. B. Nielsen return 0 271123d827efSSimon L. B. Nielsen fi 271223d827efSSimon L. B. Nielsen 271323d827efSSimon L. B. Nielsen # We could not use current directory name, so add counter to 271423d827efSSimon L. B. Nielsen # the end and try again. 271523d827efSSimon L. B. Nielsen CNT=$((CNT + 1)) 271623d827efSSimon L. B. Nielsen if [ $CNT -gt 9 ]; then 2717c4a0c62cSThomas Quinot echo "Could not find valid backup dir ($BASEDIR/$BACKUPKERNELDIR)" 271823d827efSSimon L. B. Nielsen exit 1 271923d827efSSimon L. B. Nielsen fi 272023d827efSSimon L. B. Nielsen BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`" 272123d827efSSimon L. B. Nielsen BACKUPKERNELDIR="${BACKUPKERNELDIR}${CNT}" 272223d827efSSimon L. B. Nielsen done 272323d827efSSimon L. B. Nielsen} 272423d827efSSimon L. B. Nielsen 272523d827efSSimon L. B. Nielsen# Backup the current kernel using hardlinks, if not disabled by user. 272623d827efSSimon L. B. Nielsen# Since we delete all files in the directory used for previous backups 272723d827efSSimon L. B. Nielsen# we create a marker file called ".freebsd-update" in the directory so 272823d827efSSimon L. B. Nielsen# we can determine on the next run that the directory was created by 272923d827efSSimon L. B. Nielsen# freebsd-update and we then do not accidentally remove user files in 273023d827efSSimon L. B. Nielsen# the unlikely case that the user has created a directory with a 273123d827efSSimon L. B. Nielsen# conflicting name. 273223d827efSSimon L. B. Nielsenbackup_kernel () { 273323d827efSSimon L. B. Nielsen # Only make kernel backup is so configured. 273423d827efSSimon L. B. Nielsen if [ $BACKUPKERNEL != yes ]; then 273523d827efSSimon L. B. Nielsen return 0 273623d827efSSimon L. B. Nielsen fi 273723d827efSSimon L. B. Nielsen 273823d827efSSimon L. B. Nielsen # Decide which directory name to use for kernel backups. 273923d827efSSimon L. B. Nielsen backup_kernel_finddir 274023d827efSSimon L. B. Nielsen 274123d827efSSimon L. B. Nielsen # Remove old kernel backup files. If $BACKUPKERNELDIR was 274223d827efSSimon L. B. Nielsen # "not ours", backup_kernel_finddir would have exited, so 274323d827efSSimon L. B. Nielsen # deleting the directory content is as safe as we can make it. 2744c4a0c62cSThomas Quinot if [ -d $BASEDIR/$BACKUPKERNELDIR ]; then 2745c4a0c62cSThomas Quinot rm -fr $BASEDIR/$BACKUPKERNELDIR 274623d827efSSimon L. B. Nielsen fi 274723d827efSSimon L. B. Nielsen 2748ab7d0151SJaakko Heinonen # Create directories for backup. 2749c4a0c62cSThomas Quinot mkdir -p $BASEDIR/$BACKUPKERNELDIR 2750c4a0c62cSThomas Quinot mtree -cdn -p "${BASEDIR}/${KERNELDIR}" | \ 2751c4a0c62cSThomas Quinot mtree -Ue -p "${BASEDIR}/${BACKUPKERNELDIR}" > /dev/null 275223d827efSSimon L. B. Nielsen 275323d827efSSimon L. B. Nielsen # Mark the directory as having been created by freebsd-update. 2754c4a0c62cSThomas Quinot touch $BASEDIR/$BACKUPKERNELDIR/.freebsd-update 275523d827efSSimon L. B. Nielsen if [ $? -ne 0 ]; then 275623d827efSSimon L. B. Nielsen echo "Could not create kernel backup directory" 275723d827efSSimon L. B. Nielsen exit 1 275823d827efSSimon L. B. Nielsen fi 275923d827efSSimon L. B. Nielsen 276023d827efSSimon L. B. Nielsen # Disable pathname expansion to be sure *.symbols is not 276123d827efSSimon L. B. Nielsen # expanded. 276223d827efSSimon L. B. Nielsen set -f 276323d827efSSimon L. B. Nielsen 276423d827efSSimon L. B. Nielsen # Use find to ignore symbol files, unless disabled by user. 276523d827efSSimon L. B. Nielsen if [ $BACKUPKERNELSYMBOLFILES = yes ]; then 276623d827efSSimon L. B. Nielsen FINDFILTER="" 276723d827efSSimon L. B. Nielsen else 27687e1ed2c7SEd Maste FINDFILTER="-a ! -name *.debug -a ! -name *.symbols" 276923d827efSSimon L. B. Nielsen fi 277023d827efSSimon L. B. Nielsen 277123d827efSSimon L. B. Nielsen # Backup all the kernel files using hardlinks. 2772c4a0c62cSThomas Quinot (cd ${BASEDIR}/${KERNELDIR} && find . -type f $FINDFILTER -exec \ 2773c4a0c62cSThomas Quinot cp -pl '{}' ${BASEDIR}/${BACKUPKERNELDIR}/'{}' \;) 277423d827efSSimon L. B. Nielsen 277523d827efSSimon L. B. Nielsen # Re-enable patchname expansion. 277623d827efSSimon L. B. Nielsen set +f 277723d827efSSimon L. B. Nielsen} 277823d827efSSimon L. B. Nielsen 277948ffe56aSColin Percival# Install new files 278048ffe56aSColin Percivalinstall_from_index () { 278148ffe56aSColin Percival # First pass: Do everything apart from setting file flags. We 278248ffe56aSColin Percival # can't set flags yet, because schg inhibits hard linking. 278348ffe56aSColin Percival sort -k 1,1 -t '|' $1 | 278448ffe56aSColin Percival tr '|' ' ' | 278548ffe56aSColin Percival while read FPATH TYPE OWNER GROUP PERM FLAGS HASH LINK; do 278648ffe56aSColin Percival case ${TYPE} in 278748ffe56aSColin Percival d) 278848ffe56aSColin Percival # Create a directory 278948ffe56aSColin Percival install -d -o ${OWNER} -g ${GROUP} \ 279048ffe56aSColin Percival -m ${PERM} ${BASEDIR}/${FPATH} 279148ffe56aSColin Percival ;; 279248ffe56aSColin Percival f) 279348ffe56aSColin Percival if [ -z "${LINK}" ]; then 279448ffe56aSColin Percival # Create a file, without setting flags. 279548ffe56aSColin Percival gunzip < files/${HASH}.gz > ${HASH} 279648ffe56aSColin Percival install -S -o ${OWNER} -g ${GROUP} \ 279748ffe56aSColin Percival -m ${PERM} ${HASH} ${BASEDIR}/${FPATH} 279848ffe56aSColin Percival rm ${HASH} 279948ffe56aSColin Percival else 280048ffe56aSColin Percival # Create a hard link. 2801e829ed67SColin Percival ln -f ${BASEDIR}/${LINK} ${BASEDIR}/${FPATH} 280248ffe56aSColin Percival fi 280348ffe56aSColin Percival ;; 280448ffe56aSColin Percival L) 280548ffe56aSColin Percival # Create a symlink 280648ffe56aSColin Percival ln -sfh ${HASH} ${BASEDIR}/${FPATH} 280748ffe56aSColin Percival ;; 280848ffe56aSColin Percival esac 280948ffe56aSColin Percival done 281048ffe56aSColin Percival 281148ffe56aSColin Percival # Perform a second pass, adding file flags. 281248ffe56aSColin Percival tr '|' ' ' < $1 | 281348ffe56aSColin Percival while read FPATH TYPE OWNER GROUP PERM FLAGS HASH LINK; do 281448ffe56aSColin Percival if [ ${TYPE} = "f" ] && 281548ffe56aSColin Percival ! [ ${FLAGS} = "0" ]; then 281648ffe56aSColin Percival chflags ${FLAGS} ${BASEDIR}/${FPATH} 281748ffe56aSColin Percival fi 281848ffe56aSColin Percival done 281948ffe56aSColin Percival} 282048ffe56aSColin Percival 282148ffe56aSColin Percival# Remove files which we want to delete 282248ffe56aSColin Percivalinstall_delete () { 282348ffe56aSColin Percival # Generate list of new files 282448ffe56aSColin Percival cut -f 1 -d '|' < $2 | 282548ffe56aSColin Percival sort > newfiles 282648ffe56aSColin Percival 282748ffe56aSColin Percival # Generate subindex of old files we want to nuke 282848ffe56aSColin Percival sort -k 1,1 -t '|' $1 | 282948ffe56aSColin Percival join -t '|' -v 1 - newfiles | 2830bce02f98SColin Percival sort -r -k 1,1 -t '|' | 283148ffe56aSColin Percival cut -f 1,2 -d '|' | 283248ffe56aSColin Percival tr '|' ' ' > killfiles 283348ffe56aSColin Percival 283448ffe56aSColin Percival # Remove the offending bits 283548ffe56aSColin Percival while read FPATH TYPE; do 283648ffe56aSColin Percival case ${TYPE} in 283748ffe56aSColin Percival d) 283848ffe56aSColin Percival rmdir ${BASEDIR}/${FPATH} 283948ffe56aSColin Percival ;; 284048ffe56aSColin Percival f) 284148ffe56aSColin Percival rm ${BASEDIR}/${FPATH} 284248ffe56aSColin Percival ;; 284348ffe56aSColin Percival L) 284448ffe56aSColin Percival rm ${BASEDIR}/${FPATH} 284548ffe56aSColin Percival ;; 284648ffe56aSColin Percival esac 284748ffe56aSColin Percival done < killfiles 284848ffe56aSColin Percival 284948ffe56aSColin Percival # Clean up 285048ffe56aSColin Percival rm newfiles killfiles 285148ffe56aSColin Percival} 285248ffe56aSColin Percival 2853db6b0a61SColin Percival# Install new files, delete old files, and update linker.hints 2854db6b0a61SColin Percivalinstall_files () { 2855db6b0a61SColin Percival # If we haven't already dealt with the kernel, deal with it. 2856db6b0a61SColin Percival if ! [ -f $1/kerneldone ]; then 2857db6b0a61SColin Percival grep -E '^/boot/' $1/INDEX-OLD > INDEX-OLD 2858db6b0a61SColin Percival grep -E '^/boot/' $1/INDEX-NEW > INDEX-NEW 2859db6b0a61SColin Percival 286023d827efSSimon L. B. Nielsen # Backup current kernel before installing a new one 286123d827efSSimon L. B. Nielsen backup_kernel || return 1 286223d827efSSimon L. B. Nielsen 2863db6b0a61SColin Percival # Install new files 2864db6b0a61SColin Percival install_from_index INDEX-NEW || return 1 2865db6b0a61SColin Percival 2866db6b0a61SColin Percival # Remove files which need to be deleted 2867db6b0a61SColin Percival install_delete INDEX-OLD INDEX-NEW || return 1 2868db6b0a61SColin Percival 2869db6b0a61SColin Percival # Update linker.hints if necessary 2870db6b0a61SColin Percival if [ -s INDEX-OLD -o -s INDEX-NEW ]; then 2871c4a0c62cSThomas Quinot kldxref -R ${BASEDIR}/boot/ 2>/dev/null 287248ffe56aSColin Percival fi 2873db6b0a61SColin Percival 2874db6b0a61SColin Percival # We've finished updating the kernel. 2875db6b0a61SColin Percival touch $1/kerneldone 2876db6b0a61SColin Percival 2877db6b0a61SColin Percival # Do we need to ask for a reboot now? 2878db6b0a61SColin Percival if [ -f $1/kernelfirst ] && 2879db6b0a61SColin Percival [ -s INDEX-OLD -o -s INDEX-NEW ]; then 2880db6b0a61SColin Percival cat <<-EOF 2881db6b0a61SColin Percival 2882db6b0a61SColin PercivalKernel updates have been installed. Please reboot and run 2883db6b0a61SColin Percival"$0 install" again to finish installing updates. 2884db6b0a61SColin Percival EOF 2885db6b0a61SColin Percival exit 0 2886db6b0a61SColin Percival fi 2887db6b0a61SColin Percival fi 2888db6b0a61SColin Percival 2889db6b0a61SColin Percival # If we haven't already dealt with the world, deal with it. 2890db6b0a61SColin Percival if ! [ -f $1/worlddone ]; then 2891cd1ab228SColin Percival # Create any necessary directories first 2892cd1ab228SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 2893cd1ab228SColin Percival grep -E '^[^|]+\|d\|' > INDEX-NEW 2894cd1ab228SColin Percival install_from_index INDEX-NEW || return 1 2895cd1ab228SColin Percival 2896722d81b5SBrooks Davis # Install new runtime linker 2897722d81b5SBrooks Davis grep -vE '^/boot/' $1/INDEX-NEW | 2898722d81b5SBrooks Davis grep -vE '^[^|]+\|d\|' | 2899722d81b5SBrooks Davis grep -E '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' > INDEX-NEW 2900722d81b5SBrooks Davis install_from_index INDEX-NEW || return 1 2901722d81b5SBrooks Davis 2902db6b0a61SColin Percival # Install new shared libraries next 2903db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 2904cd1ab228SColin Percival grep -vE '^[^|]+\|d\|' | 2905722d81b5SBrooks Davis grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' | 29069546dbd1SColin Percival grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW 2907db6b0a61SColin Percival install_from_index INDEX-NEW || return 1 2908db6b0a61SColin Percival 2909db6b0a61SColin Percival # Deal with everything else 2910db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 2911cd1ab228SColin Percival grep -vE '^[^|]+\|d\|' | 2912722d81b5SBrooks Davis grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' | 29139546dbd1SColin Percival grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD 2914db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 2915cd1ab228SColin Percival grep -vE '^[^|]+\|d\|' | 2916722d81b5SBrooks Davis grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' | 29179546dbd1SColin Percival grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW 2918db6b0a61SColin Percival install_from_index INDEX-NEW || return 1 2919db6b0a61SColin Percival install_delete INDEX-OLD INDEX-NEW || return 1 2920db6b0a61SColin Percival 2921*9b659110SEd Maste # Rebuild generated pwd files. 2922c4a0c62cSThomas Quinot if [ ${BASEDIR}/etc/master.passwd -nt ${BASEDIR}/etc/spwd.db ] || 2923*9b659110SEd Maste [ ${BASEDIR}/etc/master.passwd -nt ${BASEDIR}/etc/pwd.db ] || 2924*9b659110SEd Maste [ ${BASEDIR}/etc/master.passwd -nt ${BASEDIR}/etc/passwd ]; then 2925*9b659110SEd Maste pwd_mkdb -d ${BASEDIR}/etc -p ${BASEDIR}/etc/master.passwd 2926db6b0a61SColin Percival fi 2927db6b0a61SColin Percival 2928db6b0a61SColin Percival # Rebuild /etc/login.conf.db if necessary. 2929c4a0c62cSThomas Quinot if [ ${BASEDIR}/etc/login.conf -nt ${BASEDIR}/etc/login.conf.db ]; then 2930c4a0c62cSThomas Quinot cap_mkdb ${BASEDIR}/etc/login.conf 2931db6b0a61SColin Percival fi 2932db6b0a61SColin Percival 2933db6b0a61SColin Percival # We've finished installing the world and deleting old files 2934db6b0a61SColin Percival # which are not shared libraries. 2935db6b0a61SColin Percival touch $1/worlddone 2936db6b0a61SColin Percival 2937db6b0a61SColin Percival # Do we need to ask the user to portupgrade now? 2938db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 29399546dbd1SColin Percival grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' | 2940db6b0a61SColin Percival cut -f 1 -d '|' | 2941db6b0a61SColin Percival sort > newfiles 2942db6b0a61SColin Percival if grep -vE '^/boot/' $1/INDEX-OLD | 29439546dbd1SColin Percival grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' | 2944db6b0a61SColin Percival cut -f 1 -d '|' | 2945db6b0a61SColin Percival sort | 2946db6b0a61SColin Percival join -v 1 - newfiles | 2947db6b0a61SColin Percival grep -q .; then 2948db6b0a61SColin Percival cat <<-EOF 2949db6b0a61SColin Percival 2950db6b0a61SColin PercivalCompleting this upgrade requires removing old shared object files. 2951db6b0a61SColin PercivalPlease rebuild all installed 3rd party software (e.g., programs 2952db6b0a61SColin Percivalinstalled from the ports tree) and then run "$0 install" 2953db6b0a61SColin Percivalagain to finish installing updates. 2954db6b0a61SColin Percival EOF 2955db6b0a61SColin Percival rm newfiles 2956db6b0a61SColin Percival exit 0 2957db6b0a61SColin Percival fi 2958db6b0a61SColin Percival rm newfiles 2959db6b0a61SColin Percival fi 2960db6b0a61SColin Percival 2961db6b0a61SColin Percival # Remove old shared libraries 2962db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 2963cd1ab228SColin Percival grep -vE '^[^|]+\|d\|' | 29649546dbd1SColin Percival grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW 2965db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 2966cd1ab228SColin Percival grep -vE '^[^|]+\|d\|' | 29679546dbd1SColin Percival grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD 2968db6b0a61SColin Percival install_delete INDEX-OLD INDEX-NEW || return 1 2969db6b0a61SColin Percival 2970cd1ab228SColin Percival # Remove old directories 2971ebc1d19cSColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 2972ebc1d19cSColin Percival grep -E '^[^|]+\|d\|' > INDEX-NEW 2973cd1ab228SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 2974cd1ab228SColin Percival grep -E '^[^|]+\|d\|' > INDEX-OLD 2975cd1ab228SColin Percival install_delete INDEX-OLD INDEX-NEW || return 1 2976cd1ab228SColin Percival 2977db6b0a61SColin Percival # Remove temporary files 2978db6b0a61SColin Percival rm INDEX-OLD INDEX-NEW 297948ffe56aSColin Percival} 298048ffe56aSColin Percival 298148ffe56aSColin Percival# Rearrange bits to allow the installed updates to be rolled back 298248ffe56aSColin Percivalinstall_setup_rollback () { 2983db6b0a61SColin Percival # Remove the "reboot after installing kernel", "kernel updated", and 2984db6b0a61SColin Percival # "finished installing the world" flags if present -- they are 2985db6b0a61SColin Percival # irrelevant when rolling back updates. 2986db6b0a61SColin Percival if [ -f ${BDHASH}-install/kernelfirst ]; then 2987db6b0a61SColin Percival rm ${BDHASH}-install/kernelfirst 2988db6b0a61SColin Percival rm ${BDHASH}-install/kerneldone 2989db6b0a61SColin Percival fi 2990db6b0a61SColin Percival if [ -f ${BDHASH}-install/worlddone ]; then 2991db6b0a61SColin Percival rm ${BDHASH}-install/worlddone 2992db6b0a61SColin Percival fi 2993db6b0a61SColin Percival 299448ffe56aSColin Percival if [ -L ${BDHASH}-rollback ]; then 299548ffe56aSColin Percival mv ${BDHASH}-rollback ${BDHASH}-install/rollback 299648ffe56aSColin Percival fi 299748ffe56aSColin Percival 299848ffe56aSColin Percival mv ${BDHASH}-install ${BDHASH}-rollback 299948ffe56aSColin Percival} 300048ffe56aSColin Percival 300148ffe56aSColin Percival# Actually install updates 300248ffe56aSColin Percivalinstall_run () { 300348ffe56aSColin Percival echo -n "Installing updates..." 300448ffe56aSColin Percival 300548ffe56aSColin Percival # Make sure we have all the files we should have 300648ffe56aSColin Percival install_verify ${BDHASH}-install/INDEX-OLD \ 300748ffe56aSColin Percival ${BDHASH}-install/INDEX-NEW || return 1 300848ffe56aSColin Percival 300948ffe56aSColin Percival # Remove system immutable flag from files 301048ffe56aSColin Percival install_unschg ${BDHASH}-install/INDEX-OLD \ 301148ffe56aSColin Percival ${BDHASH}-install/INDEX-NEW || return 1 301248ffe56aSColin Percival 3013db6b0a61SColin Percival # Install new files, delete old files, and update linker.hints 3014db6b0a61SColin Percival install_files ${BDHASH}-install || return 1 301548ffe56aSColin Percival 301648ffe56aSColin Percival # Rearrange bits to allow the installed updates to be rolled back 301748ffe56aSColin Percival install_setup_rollback 301848ffe56aSColin Percival 301948ffe56aSColin Percival echo " done." 302048ffe56aSColin Percival} 302148ffe56aSColin Percival 302248ffe56aSColin Percival# Rearrange bits to allow the previous set of updates to be rolled back next. 302348ffe56aSColin Percivalrollback_setup_rollback () { 302448ffe56aSColin Percival if [ -L ${BDHASH}-rollback/rollback ]; then 302548ffe56aSColin Percival mv ${BDHASH}-rollback/rollback rollback-tmp 302648ffe56aSColin Percival rm -r ${BDHASH}-rollback/ 302748ffe56aSColin Percival rm ${BDHASH}-rollback 302848ffe56aSColin Percival mv rollback-tmp ${BDHASH}-rollback 302948ffe56aSColin Percival else 303048ffe56aSColin Percival rm -r ${BDHASH}-rollback/ 303148ffe56aSColin Percival rm ${BDHASH}-rollback 303248ffe56aSColin Percival fi 303348ffe56aSColin Percival} 303448ffe56aSColin Percival 3035db6b0a61SColin Percival# Install old files, delete new files, and update linker.hints 3036db6b0a61SColin Percivalrollback_files () { 30371ec4fb3aSColin Percival # Install old shared library files which don't have the same path as 30381ec4fb3aSColin Percival # a new shared library file. 30391ec4fb3aSColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 3040fd0963d1SColin Percival grep -E '/lib/.*\.so\.[0-9]+\|' | 30411ec4fb3aSColin Percival cut -f 1 -d '|' | 30421ec4fb3aSColin Percival sort > INDEX-NEW.libs.flist 3043db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 3044fd0963d1SColin Percival grep -E '/lib/.*\.so\.[0-9]+\|' | 30451ec4fb3aSColin Percival sort -k 1,1 -t '|' - | 30461ec4fb3aSColin Percival join -t '|' -v 1 - INDEX-NEW.libs.flist > INDEX-OLD 3047db6b0a61SColin Percival install_from_index INDEX-OLD || return 1 3048db6b0a61SColin Percival 3049db6b0a61SColin Percival # Deal with files which are neither kernel nor shared library 3050db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 3051fd0963d1SColin Percival grep -vE '/lib/.*\.so\.[0-9]+\|' > INDEX-OLD 3052db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 3053fd0963d1SColin Percival grep -vE '/lib/.*\.so\.[0-9]+\|' > INDEX-NEW 3054db6b0a61SColin Percival install_from_index INDEX-OLD || return 1 3055db6b0a61SColin Percival install_delete INDEX-NEW INDEX-OLD || return 1 3056db6b0a61SColin Percival 30571ec4fb3aSColin Percival # Install any old shared library files which we didn't install above. 30581ec4fb3aSColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 3059fd0963d1SColin Percival grep -E '/lib/.*\.so\.[0-9]+\|' | 30601ec4fb3aSColin Percival sort -k 1,1 -t '|' - | 30611ec4fb3aSColin Percival join -t '|' - INDEX-NEW.libs.flist > INDEX-OLD 30621ec4fb3aSColin Percival install_from_index INDEX-OLD || return 1 30631ec4fb3aSColin Percival 3064db6b0a61SColin Percival # Delete unneeded shared library files 3065db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-OLD | 3066fd0963d1SColin Percival grep -E '/lib/.*\.so\.[0-9]+\|' > INDEX-OLD 3067db6b0a61SColin Percival grep -vE '^/boot/' $1/INDEX-NEW | 3068fd0963d1SColin Percival grep -E '/lib/.*\.so\.[0-9]+\|' > INDEX-NEW 3069db6b0a61SColin Percival install_delete INDEX-NEW INDEX-OLD || return 1 3070db6b0a61SColin Percival 3071db6b0a61SColin Percival # Deal with kernel files 3072db6b0a61SColin Percival grep -E '^/boot/' $1/INDEX-OLD > INDEX-OLD 3073db6b0a61SColin Percival grep -E '^/boot/' $1/INDEX-NEW > INDEX-NEW 3074db6b0a61SColin Percival install_from_index INDEX-OLD || return 1 3075db6b0a61SColin Percival install_delete INDEX-NEW INDEX-OLD || return 1 3076db6b0a61SColin Percival if [ -s INDEX-OLD -o -s INDEX-NEW ]; then 3077db6b0a61SColin Percival kldxref -R /boot/ 2>/dev/null 3078db6b0a61SColin Percival fi 3079db6b0a61SColin Percival 3080db6b0a61SColin Percival # Remove temporary files 30810e0d8d5aSColin Percival rm INDEX-OLD INDEX-NEW INDEX-NEW.libs.flist 3082db6b0a61SColin Percival} 3083db6b0a61SColin Percival 308448ffe56aSColin Percival# Actually rollback updates 308548ffe56aSColin Percivalrollback_run () { 308648ffe56aSColin Percival echo -n "Uninstalling updates..." 308748ffe56aSColin Percival 308848ffe56aSColin Percival # If there are updates waiting to be installed, remove them; we 308948ffe56aSColin Percival # want the user to re-run 'fetch' after rolling back updates. 309048ffe56aSColin Percival if [ -L ${BDHASH}-install ]; then 309148ffe56aSColin Percival rm -r ${BDHASH}-install/ 309248ffe56aSColin Percival rm ${BDHASH}-install 309348ffe56aSColin Percival fi 309448ffe56aSColin Percival 309548ffe56aSColin Percival # Make sure we have all the files we should have 309648ffe56aSColin Percival install_verify ${BDHASH}-rollback/INDEX-NEW \ 309748ffe56aSColin Percival ${BDHASH}-rollback/INDEX-OLD || return 1 309848ffe56aSColin Percival 309948ffe56aSColin Percival # Remove system immutable flag from files 310048ffe56aSColin Percival install_unschg ${BDHASH}-rollback/INDEX-NEW \ 310148ffe56aSColin Percival ${BDHASH}-rollback/INDEX-OLD || return 1 310248ffe56aSColin Percival 3103db6b0a61SColin Percival # Install old files, delete new files, and update linker.hints 3104db6b0a61SColin Percival rollback_files ${BDHASH}-rollback || return 1 310548ffe56aSColin Percival 310648ffe56aSColin Percival # Remove the rollback directory and the symlink pointing to it; and 310748ffe56aSColin Percival # rearrange bits to allow the previous set of updates to be rolled 310848ffe56aSColin Percival # back next. 310948ffe56aSColin Percival rollback_setup_rollback 311048ffe56aSColin Percival 311148ffe56aSColin Percival echo " done." 311248ffe56aSColin Percival} 311348ffe56aSColin Percival 311408e23beeSColin Percival# Compare INDEX-ALL and INDEX-PRESENT and print warnings about differences. 311508e23beeSColin PercivalIDS_compare () { 3116bb10a826SColin Percival # Get all the lines which mismatch in something other than file 3117bb10a826SColin Percival # flags. We ignore file flags because sysinstall doesn't seem to 3118bb10a826SColin Percival # set them when it installs FreeBSD; warning about these adds a 3119bb10a826SColin Percival # very large amount of noise. 3120bb10a826SColin Percival cut -f 1-5,7-8 -d '|' $1 > $1.noflags 3121bb10a826SColin Percival sort -k 1,1 -t '|' $1.noflags > $1.sorted 3122bb10a826SColin Percival cut -f 1-5,7-8 -d '|' $2 | 3123bb10a826SColin Percival comm -13 $1.noflags - | 3124bb10a826SColin Percival fgrep -v '|-|||||' | 312508e23beeSColin Percival sort -k 1,1 -t '|' | 312608e23beeSColin Percival join -t '|' $1.sorted - > INDEX-NOTMATCHING 312708e23beeSColin Percival 312808e23beeSColin Percival # Ignore files which match IDSIGNOREPATHS. 312908e23beeSColin Percival for X in ${IDSIGNOREPATHS}; do 313008e23beeSColin Percival grep -E "^${X}" INDEX-NOTMATCHING 313108e23beeSColin Percival done | 313208e23beeSColin Percival sort -u | 313308e23beeSColin Percival comm -13 - INDEX-NOTMATCHING > INDEX-NOTMATCHING.tmp 313408e23beeSColin Percival mv INDEX-NOTMATCHING.tmp INDEX-NOTMATCHING 313508e23beeSColin Percival 313608e23beeSColin Percival # Go through the lines and print warnings. 3137aa60062eSColin Percival local IFS='|' 3138aa60062eSColin Percival while read FPATH TYPE OWNER GROUP PERM HASH LINK P_TYPE P_OWNER P_GROUP P_PERM P_HASH P_LINK; do 313908e23beeSColin Percival # Warn about different object types. 314008e23beeSColin Percival if ! [ "${TYPE}" = "${P_TYPE}" ]; then 314108e23beeSColin Percival echo -n "${FPATH} is a " 314208e23beeSColin Percival case "${P_TYPE}" in 314308e23beeSColin Percival f) echo -n "regular file, " 314408e23beeSColin Percival ;; 314508e23beeSColin Percival d) echo -n "directory, " 314608e23beeSColin Percival ;; 314708e23beeSColin Percival L) echo -n "symlink, " 314808e23beeSColin Percival ;; 314908e23beeSColin Percival esac 315008e23beeSColin Percival echo -n "but should be a " 315108e23beeSColin Percival case "${TYPE}" in 315208e23beeSColin Percival f) echo -n "regular file." 315308e23beeSColin Percival ;; 315408e23beeSColin Percival d) echo -n "directory." 315508e23beeSColin Percival ;; 315608e23beeSColin Percival L) echo -n "symlink." 315708e23beeSColin Percival ;; 315808e23beeSColin Percival esac 315908e23beeSColin Percival echo 316008e23beeSColin Percival 316108e23beeSColin Percival # Skip other tests, since they don't make sense if 316208e23beeSColin Percival # we're comparing different object types. 316308e23beeSColin Percival continue 316408e23beeSColin Percival fi 316508e23beeSColin Percival 316608e23beeSColin Percival # Warn about different owners. 316708e23beeSColin Percival if ! [ "${OWNER}" = "${P_OWNER}" ]; then 316808e23beeSColin Percival echo -n "${FPATH} is owned by user id ${P_OWNER}, " 316908e23beeSColin Percival echo "but should be owned by user id ${OWNER}." 317008e23beeSColin Percival fi 317108e23beeSColin Percival 317208e23beeSColin Percival # Warn about different groups. 317308e23beeSColin Percival if ! [ "${GROUP}" = "${P_GROUP}" ]; then 317408e23beeSColin Percival echo -n "${FPATH} is owned by group id ${P_GROUP}, " 317508e23beeSColin Percival echo "but should be owned by group id ${GROUP}." 317608e23beeSColin Percival fi 317708e23beeSColin Percival 317808e23beeSColin Percival # Warn about different permissions. We do not warn about 317908e23beeSColin Percival # different permissions on symlinks, since some archivers 318008e23beeSColin Percival # don't extract symlink permissions correctly and they are 318108e23beeSColin Percival # ignored anyway. 318208e23beeSColin Percival if ! [ "${PERM}" = "${P_PERM}" ] && 318308e23beeSColin Percival ! [ "${TYPE}" = "L" ]; then 318408e23beeSColin Percival echo -n "${FPATH} has ${P_PERM} permissions, " 318508e23beeSColin Percival echo "but should have ${PERM} permissions." 318608e23beeSColin Percival fi 318708e23beeSColin Percival 318808e23beeSColin Percival # Warn about different file hashes / symlink destinations. 318908e23beeSColin Percival if ! [ "${HASH}" = "${P_HASH}" ]; then 319008e23beeSColin Percival if [ "${TYPE}" = "L" ]; then 319108e23beeSColin Percival echo -n "${FPATH} is a symlink to ${P_HASH}, " 319208e23beeSColin Percival echo "but should be a symlink to ${HASH}." 319308e23beeSColin Percival fi 319408e23beeSColin Percival if [ "${TYPE}" = "f" ]; then 319508e23beeSColin Percival echo -n "${FPATH} has SHA256 hash ${P_HASH}, " 319608e23beeSColin Percival echo "but should have SHA256 hash ${HASH}." 319708e23beeSColin Percival fi 319808e23beeSColin Percival fi 319908e23beeSColin Percival 320008e23beeSColin Percival # We don't warn about different hard links, since some 320108e23beeSColin Percival # some archivers break hard links, and as long as the 320208e23beeSColin Percival # underlying data is correct they really don't matter. 320308e23beeSColin Percival done < INDEX-NOTMATCHING 320408e23beeSColin Percival 320508e23beeSColin Percival # Clean up 3206bb10a826SColin Percival rm $1 $1.noflags $1.sorted $2 INDEX-NOTMATCHING 320708e23beeSColin Percival} 320808e23beeSColin Percival 320908e23beeSColin Percival# Do the work involved in comparing the system to a "known good" index 321008e23beeSColin PercivalIDS_run () { 321108e23beeSColin Percival workdir_init || return 1 321208e23beeSColin Percival 321308e23beeSColin Percival # Prepare the mirror list. 321408e23beeSColin Percival fetch_pick_server_init && fetch_pick_server 321508e23beeSColin Percival 321608e23beeSColin Percival # Try to fetch the public key until we run out of servers. 321708e23beeSColin Percival while ! fetch_key; do 321808e23beeSColin Percival fetch_pick_server || return 1 321908e23beeSColin Percival done 322008e23beeSColin Percival 322108e23beeSColin Percival # Try to fetch the metadata index signature ("tag") until we run 322208e23beeSColin Percival # out of available servers; and sanity check the downloaded tag. 322308e23beeSColin Percival while ! fetch_tag; do 322408e23beeSColin Percival fetch_pick_server || return 1 322508e23beeSColin Percival done 322608e23beeSColin Percival fetch_tagsanity || return 1 322708e23beeSColin Percival 322808e23beeSColin Percival # Fetch INDEX-OLD and INDEX-ALL. 322908e23beeSColin Percival fetch_metadata INDEX-OLD INDEX-ALL || return 1 323008e23beeSColin Percival 323108e23beeSColin Percival # Generate filtered INDEX-OLD and INDEX-ALL files containing only 323208e23beeSColin Percival # the components we want and without anything marked as "Ignore". 323308e23beeSColin Percival fetch_filter_metadata INDEX-OLD || return 1 323408e23beeSColin Percival fetch_filter_metadata INDEX-ALL || return 1 323508e23beeSColin Percival 323608e23beeSColin Percival # Merge the INDEX-OLD and INDEX-ALL files into INDEX-ALL. 323708e23beeSColin Percival sort INDEX-OLD INDEX-ALL > INDEX-ALL.tmp 323808e23beeSColin Percival mv INDEX-ALL.tmp INDEX-ALL 323908e23beeSColin Percival rm INDEX-OLD 324008e23beeSColin Percival 324108e23beeSColin Percival # Translate /boot/${KERNCONF} to ${KERNELDIR} 324208e23beeSColin Percival fetch_filter_kernel_names INDEX-ALL ${KERNCONF} 324308e23beeSColin Percival 324408e23beeSColin Percival # Inspect the system and generate an INDEX-PRESENT file. 324508e23beeSColin Percival fetch_inspect_system INDEX-ALL INDEX-PRESENT /dev/null || return 1 324608e23beeSColin Percival 324708e23beeSColin Percival # Compare INDEX-ALL and INDEX-PRESENT and print warnings about any 324808e23beeSColin Percival # differences. 324908e23beeSColin Percival IDS_compare INDEX-ALL INDEX-PRESENT 325008e23beeSColin Percival} 325108e23beeSColin Percival 325248ffe56aSColin Percival#### Main functions -- call parameter-handling and core functions 325348ffe56aSColin Percival 325448ffe56aSColin Percival# Using the command line, configuration file, and defaults, 325548ffe56aSColin Percival# set all the parameters which are needed later. 325648ffe56aSColin Percivalget_params () { 325748ffe56aSColin Percival init_params 325848ffe56aSColin Percival parse_cmdline $@ 325948ffe56aSColin Percival parse_conffile 326048ffe56aSColin Percival default_params 326148ffe56aSColin Percival} 326248ffe56aSColin Percival 326348ffe56aSColin Percival# Fetch command. Make sure that we're being called 326448ffe56aSColin Percival# interactively, then run fetch_check_params and fetch_run 326548ffe56aSColin Percivalcmd_fetch () { 32668bf2dcceSAllan Jude if [ ! -t 0 -a $NOTTYOK -eq 0 ]; then 326748ffe56aSColin Percival echo -n "`basename $0` fetch should not " 326848ffe56aSColin Percival echo "be run non-interactively." 326948ffe56aSColin Percival echo "Run `basename $0` cron instead." 327048ffe56aSColin Percival exit 1 327148ffe56aSColin Percival fi 327248ffe56aSColin Percival fetch_check_params 327348ffe56aSColin Percival fetch_run || exit 1 327433bd05c3SGuangyuan Yang ISFETCHED=1 327548ffe56aSColin Percival} 327648ffe56aSColin Percival 327748ffe56aSColin Percival# Cron command. Make sure the parameters are sensible; wait 327848ffe56aSColin Percival# rand(3600) seconds; then fetch updates. While fetching updates, 327948ffe56aSColin Percival# send output to a temporary file; only print that file if the 328048ffe56aSColin Percival# fetching failed. 328148ffe56aSColin Percivalcmd_cron () { 328248ffe56aSColin Percival fetch_check_params 328348ffe56aSColin Percival sleep `jot -r 1 0 3600` 328448ffe56aSColin Percival 328548ffe56aSColin Percival TMPFILE=`mktemp /tmp/freebsd-update.XXXXXX` || exit 1 328648ffe56aSColin Percival if ! fetch_run >> ${TMPFILE} || 328748ffe56aSColin Percival ! grep -q "No updates needed" ${TMPFILE} || 328848ffe56aSColin Percival [ ${VERBOSELEVEL} = "debug" ]; then 328948ffe56aSColin Percival mail -s "`hostname` security updates" ${MAILTO} < ${TMPFILE} 329048ffe56aSColin Percival fi 329148ffe56aSColin Percival 329248ffe56aSColin Percival rm ${TMPFILE} 329348ffe56aSColin Percival} 329448ffe56aSColin Percival 3295db6b0a61SColin Percival# Fetch files for upgrading to a new release. 3296db6b0a61SColin Percivalcmd_upgrade () { 3297db6b0a61SColin Percival upgrade_check_params 3298db6b0a61SColin Percival upgrade_run || exit 1 3299db6b0a61SColin Percival} 3300db6b0a61SColin Percival 330148ffe56aSColin Percival# Install downloaded updates. 330248ffe56aSColin Percivalcmd_install () { 330348ffe56aSColin Percival install_check_params 330448ffe56aSColin Percival install_run || exit 1 330548ffe56aSColin Percival} 330648ffe56aSColin Percival 330748ffe56aSColin Percival# Rollback most recently installed updates. 330848ffe56aSColin Percivalcmd_rollback () { 330948ffe56aSColin Percival rollback_check_params 331048ffe56aSColin Percival rollback_run || exit 1 331148ffe56aSColin Percival} 331248ffe56aSColin Percival 331308e23beeSColin Percival# Compare system against a "known good" index. 331408e23beeSColin Percivalcmd_IDS () { 331508e23beeSColin Percival IDS_check_params 331608e23beeSColin Percival IDS_run || exit 1 331708e23beeSColin Percival} 331808e23beeSColin Percival 331948ffe56aSColin Percival#### Entry point 332048ffe56aSColin Percival 332148ffe56aSColin Percival# Make sure we find utilities from the base system 332248ffe56aSColin Percivalexport PATH=/sbin:/bin:/usr/sbin:/usr/bin:${PATH} 332348ffe56aSColin Percival 33249c990fb2SGordon Tetlow# Set a pager if the user doesn't 33259c990fb2SGordon Tetlowif [ -z "$PAGER" ]; then 332647cc9ee1SAlan Somers PAGER=/usr/bin/less 33279c990fb2SGordon Tetlowfi 33289c990fb2SGordon Tetlow 3329f2890dbdSColin Percival# Set LC_ALL in order to avoid problems with character ranges like [A-Z]. 3330f2890dbdSColin Percivalexport LC_ALL=C 3331f2890dbdSColin Percival 333248ffe56aSColin Percivalget_params $@ 333348ffe56aSColin Percivalfor COMMAND in ${COMMANDS}; do 333448ffe56aSColin Percival cmd_${COMMAND} 333548ffe56aSColin Percivaldone 3336