portsnap.sh revision 154088
1148871Scperciva#!/bin/sh 2148871Scperciva 3148871Scperciva#- 4148871Scperciva# Copyright 2004-2005 Colin Percival 5148871Scperciva# All rights reserved 6148871Scperciva# 7148871Scperciva# Redistribution and use in source and binary forms, with or without 8148871Scperciva# modification, are permitted providing that the following conditions 9148871Scperciva# are met: 10148871Scperciva# 1. Redistributions of source code must retain the above copyright 11148871Scperciva# notice, this list of conditions and the following disclaimer. 12148871Scperciva# 2. Redistributions in binary form must reproduce the above copyright 13148871Scperciva# notice, this list of conditions and the following disclaimer in the 14148871Scperciva# documentation and/or other materials provided with the distribution. 15148871Scperciva# 16148871Scperciva# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17148871Scperciva# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18148871Scperciva# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19148871Scperciva# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20148871Scperciva# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21148871Scperciva# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22148871Scperciva# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23148871Scperciva# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24148871Scperciva# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25148871Scperciva# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26148871Scperciva# POSSIBILITY OF SUCH DAMAGE. 27148871Scperciva 28148871Scperciva# $FreeBSD: head/usr.sbin/portsnap/portsnap/portsnap.sh 154088 2006-01-06 20:39:11Z cperciva $ 29148871Scperciva 30148871Scperciva#### Usage function -- called from command-line handling code. 31148871Scperciva 32148871Scperciva# Usage instructions. Options not listed: 33148871Scperciva# --debug -- don't filter output from utilities 34148871Scperciva# --no-stats -- don't show progress statistics while fetching files 35148871Scpercivausage() { 36148871Scperciva cat <<EOF 37149027Scpercivausage: `basename $0` [options] command ... [path] 38148871Scperciva 39148871ScpercivaOptions: 40148871Scperciva -d workdir -- Store working files in workdir 41148871Scperciva (default: /var/db/portsnap/) 42148871Scperciva -f conffile -- Read configuration options from conffile 43148871Scperciva (default: /etc/portsnap.conf) 44148871Scperciva -I -- Update INDEX only. (update command only) 45148871Scperciva -k KEY -- Trust an RSA key with SHA256 hash of KEY 46148871Scperciva -p portsdir -- Location of uncompressed ports tree 47148871Scperciva (default: /usr/ports/) 48148871Scperciva -s server -- Server from which to fetch updates. 49148871Scperciva (default: portsnap.FreeBSD.org) 50148871Scperciva path -- Extract only parts of the tree starting with the given 51148871Scperciva string. (extract command only) 52148871ScpercivaCommands: 53148871Scperciva fetch -- Fetch a compressed snapshot of the ports tree, 54148871Scperciva or update an existing snapshot. 55148871Scperciva cron -- Sleep rand(3600) seconds, and then fetch updates. 56148871Scperciva extract -- Extract snapshot of ports tree, replacing existing 57148871Scperciva files and directories. 58148871Scperciva update -- Update ports tree to match current snapshot, replacing 59148871Scperciva files and directories which have changed. 60148871ScpercivaEOF 61148871Scperciva exit 0 62148871Scperciva} 63148871Scperciva 64148871Scperciva#### Parameter handling functions. 65148871Scperciva 66148871Scperciva# Initialize parameters to null, just in case they're 67148871Scperciva# set in the environment. 68148871Scpercivainit_params() { 69148871Scperciva KEYPRINT="" 70148871Scperciva EXTRACTPATH="" 71148871Scperciva WORKDIR="" 72148871Scperciva PORTSDIR="" 73148871Scperciva CONFFILE="" 74148871Scperciva COMMAND="" 75149027Scperciva COMMANDS="" 76148871Scperciva QUIETREDIR="" 77148871Scperciva QUIETFLAG="" 78148871Scperciva STATSREDIR="" 79148879Scperciva XARGST="" 80148871Scperciva NDEBUG="" 81148871Scperciva DDSTATS="" 82148871Scperciva INDEXONLY="" 83148871Scperciva SERVERNAME="" 84149824Scperciva REFUSE="" 85148871Scperciva} 86148871Scperciva 87148871Scperciva# Parse the command line 88148871Scpercivaparse_cmdline() { 89148871Scperciva while [ $# -gt 0 ]; do 90148871Scperciva case "$1" in 91148871Scperciva -d) 92148871Scperciva if [ $# -eq 1 ]; then usage; fi 93148871Scperciva if [ ! -z "${WORKDIR}" ]; then usage; fi 94148871Scperciva shift; WORKDIR="$1" 95148871Scperciva ;; 96148871Scperciva --debug) 97148871Scperciva QUIETREDIR="/dev/stderr" 98148871Scperciva STATSREDIR="/dev/stderr" 99148871Scperciva QUIETFLAG=" " 100148871Scperciva NDEBUG=" " 101148879Scperciva XARGST="-t" 102148871Scperciva DDSTATS=".." 103148871Scperciva ;; 104148871Scperciva -f) 105148871Scperciva if [ $# -eq 1 ]; then usage; fi 106148871Scperciva if [ ! -z "${CONFFILE}" ]; then usage; fi 107148871Scperciva shift; CONFFILE="$1" 108148871Scperciva ;; 109148871Scperciva -h | --help | help) 110148871Scperciva usage 111148871Scperciva ;; 112148871Scperciva -I) 113148871Scperciva INDEXONLY="YES" 114148871Scperciva ;; 115148871Scperciva -k) 116148871Scperciva if [ $# -eq 1 ]; then usage; fi 117148871Scperciva if [ ! -z "${KEYPRINT}" ]; then usage; fi 118148871Scperciva shift; KEYPRINT="$1" 119148871Scperciva ;; 120148871Scperciva --no-stats) 121148871Scperciva if [ -z "${STATSREDIR}" ]; then 122148871Scperciva STATSREDIR="/dev/null" 123148871Scperciva DDSTATS=".. " 124148871Scperciva fi 125148871Scperciva ;; 126148871Scperciva -p) 127148871Scperciva if [ $# -eq 1 ]; then usage; fi 128148871Scperciva if [ ! -z "${PORTSDIR}" ]; then usage; fi 129148871Scperciva shift; PORTSDIR="$1" 130148871Scperciva ;; 131148871Scperciva -s) 132148871Scperciva if [ $# -eq 1 ]; then usage; fi 133148871Scperciva if [ ! -z "${SERVERNAME}" ]; then usage; fi 134148871Scperciva shift; SERVERNAME="$1" 135148871Scperciva ;; 136148871Scperciva cron | extract | fetch | update) 137149027Scperciva COMMANDS="${COMMANDS} $1" 138148871Scperciva ;; 139148871Scperciva *) 140148871Scperciva if [ $# -gt 1 ]; then usage; fi 141149027Scperciva if echo ${COMMANDS} | grep -vq extract; then 142149027Scperciva usage 143149027Scperciva fi 144148871Scperciva EXTRACTPATH="$1" 145148871Scperciva ;; 146148871Scperciva esac 147148871Scperciva shift 148148871Scperciva done 149148871Scperciva 150149027Scperciva if [ -z "${COMMANDS}" ]; then 151148871Scperciva usage 152148871Scperciva fi 153148871Scperciva} 154148871Scperciva 155148871Scperciva# If CONFFILE was specified at the command-line, make 156148871Scperciva# sure that it exists and is readable. 157148871Scpercivasanity_conffile() { 158148871Scperciva if [ ! -z "${CONFFILE}" ] && [ ! -r "${CONFFILE}" ]; then 159148871Scperciva echo -n "File does not exist " 160148871Scperciva echo -n "or is not readable: " 161148871Scperciva echo ${CONFFILE} 162148871Scperciva exit 1 163148871Scperciva fi 164148871Scperciva} 165148871Scperciva 166148871Scperciva# If a configuration file hasn't been specified, use 167148871Scperciva# the default value (/etc/portsnap.conf) 168148871Scpercivadefault_conffile() { 169148871Scperciva if [ -z "${CONFFILE}" ]; then 170148871Scperciva CONFFILE="/etc/portsnap.conf" 171148871Scperciva fi 172148871Scperciva} 173148871Scperciva 174148871Scperciva# Read {KEYPRINT, SERVERNAME, WORKDIR, PORTSDIR} from the configuration 175148871Scperciva# file if they haven't already been set. If the configuration 176148871Scperciva# file doesn't exist, do nothing. 177149824Scperciva# Also read REFUSE (which cannot be set via the command line) if it is 178149824Scperciva# present in the configuration file. 179148871Scpercivaparse_conffile() { 180148871Scperciva if [ -r "${CONFFILE}" ]; then 181148871Scperciva for X in KEYPRINT WORKDIR PORTSDIR SERVERNAME; do 182148871Scperciva eval _=\$${X} 183148871Scperciva if [ -z "${_}" ]; then 184148871Scperciva eval ${X}=`grep "^${X}=" "${CONFFILE}" | 185148871Scperciva cut -f 2- -d '=' | tail -1` 186148871Scperciva fi 187148871Scperciva done 188149824Scperciva 189149824Scperciva if grep -qE "^REFUSE[[:space:]]" ${CONFFILE}; then 190149824Scperciva REFUSE="^(` 191149824Scperciva grep -E "^REFUSE[[:space:]]" "${CONFFILE}" | 192149824Scperciva cut -c 7- | xargs echo | tr ' ' '|' 193149824Scperciva `)" 194149824Scperciva fi 195148871Scperciva fi 196148871Scperciva} 197148871Scperciva 198148871Scperciva# If parameters have not been set, use default values 199148871Scpercivadefault_params() { 200148871Scperciva _QUIETREDIR="/dev/null" 201148871Scperciva _QUIETFLAG="-q" 202148871Scperciva _STATSREDIR="/dev/stdout" 203148871Scperciva _WORKDIR="/var/db/portsnap" 204148871Scperciva _PORTSDIR="/usr/ports" 205148871Scperciva _NDEBUG="-n" 206148871Scperciva for X in QUIETREDIR QUIETFLAG STATSREDIR WORKDIR PORTSDIR NDEBUG; do 207148871Scperciva eval _=\$${X} 208148871Scperciva eval __=\$_${X} 209148871Scperciva if [ -z "${_}" ]; then 210148871Scperciva eval ${X}=${__} 211148871Scperciva fi 212148871Scperciva done 213148871Scperciva} 214148871Scperciva 215148871Scperciva# Perform sanity checks and set some final parameters 216148871Scperciva# in preparation for fetching files. Also chdir into 217148871Scperciva# the working directory. 218148871Scpercivafetch_check_params() { 219148871Scperciva export HTTP_USER_AGENT="portsnap (${COMMAND}, `uname -r`)" 220148871Scperciva 221148871Scperciva _SERVERNAME_z=\ 222148871Scperciva"SERVERNAME must be given via command line or configuration file." 223148871Scperciva _KEYPRINT_z="Key must be given via -k option or configuration file." 224148871Scperciva _KEYPRINT_bad="Invalid key fingerprint: " 225148871Scperciva _WORKDIR_bad="Directory does not exist or is not writable: " 226148871Scperciva 227148871Scperciva if [ -z "${SERVERNAME}" ]; then 228148871Scperciva echo -n "`basename $0`: " 229148871Scperciva echo "${_SERVERNAME_z}" 230148871Scperciva exit 1 231148871Scperciva fi 232148871Scperciva if [ -z "${KEYPRINT}" ]; then 233148871Scperciva echo -n "`basename $0`: " 234148871Scperciva echo "${_KEYPRINT_z}" 235148871Scperciva exit 1 236148871Scperciva fi 237148871Scperciva if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then 238148871Scperciva echo -n "`basename $0`: " 239148871Scperciva echo -n "${_KEYPRINT_bad}" 240148871Scperciva echo ${KEYPRINT} 241148871Scperciva exit 1 242148871Scperciva fi 243148871Scperciva if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then 244148871Scperciva echo -n "`basename $0`: " 245148871Scperciva echo -n "${_WORKDIR_bad}" 246148871Scperciva echo ${WORKDIR} 247148871Scperciva exit 1 248148871Scperciva fi 249148871Scperciva cd ${WORKDIR} || exit 1 250148871Scperciva 251148871Scperciva BSPATCH=/usr/bin/bspatch 252148871Scperciva SHA256=/sbin/sha256 253148871Scperciva PHTTPGET=/usr/libexec/phttpget 254148871Scperciva} 255148871Scperciva 256148871Scperciva# Perform sanity checks and set some final parameters 257148871Scperciva# in preparation for extracting or updating ${PORTSDIR} 258154088Scperciva# Complain if ${PORTSDIR} exists but is not writable, 259154088Scperciva# but don't complain if ${PORTSDIR} doesn't exist. 260148871Scpercivaextract_check_params() { 261148871Scperciva _WORKDIR_bad="Directory does not exist: " 262154088Scperciva _PORTSDIR_bad="Directory is not writable: " 263148871Scperciva 264148871Scperciva if ! [ -d "${WORKDIR}" ]; then 265148871Scperciva echo -n "`basename $0`: " 266148871Scperciva echo -n "${_WORKDIR_bad}" 267148871Scperciva echo ${WORKDIR} 268148871Scperciva exit 1 269148871Scperciva fi 270154088Scperciva if [ -d "${PORTSDIR}" ] && ! [ -w "${PORTSDIR}" ]; then 271148871Scperciva echo -n "`basename $0`: " 272148871Scperciva echo -n "${_PORTSDIR_bad}" 273148871Scperciva echo ${PORTSDIR} 274148871Scperciva exit 1 275148871Scperciva fi 276148871Scperciva 277148871Scperciva if ! [ -d "${WORKDIR}/files" -a -r "${WORKDIR}/tag" \ 278148871Scperciva -a -r "${WORKDIR}/INDEX" -a -r "${WORKDIR}/tINDEX" ]; then 279148871Scperciva echo "No snapshot available. Try running" 280148871Scperciva echo "# `basename $0` fetch" 281148871Scperciva exit 1 282148871Scperciva fi 283148871Scperciva 284148871Scperciva MKINDEX=/usr/libexec/make_index 285148871Scperciva} 286148871Scperciva 287148871Scperciva# Perform sanity checks and set some final parameters 288148871Scperciva# in preparation for updating ${PORTSDIR} 289148871Scpercivaupdate_check_params() { 290148871Scperciva extract_check_params 291148871Scperciva 292148871Scperciva if ! [ -r ${PORTSDIR}/.portsnap.INDEX ]; then 293148871Scperciva echo "${PORTSDIR} was not created by portsnap." 294148871Scperciva echo -n "You must run '`basename $0` extract' before " 295148871Scperciva echo "running '`basename $0` update'." 296148871Scperciva exit 1 297148871Scperciva fi 298148871Scperciva 299148871Scperciva} 300148871Scperciva 301148871Scperciva#### Core functionality -- the actual work gets done here 302148871Scperciva 303148871Scperciva# Use an SRV query to pick a server. If the SRV query doesn't provide 304148871Scperciva# a useful answer, use the server name specified by the user. 305148871Scperciva# Put another way... look up _http._tcp.${SERVERNAME} and pick a server 306148871Scperciva# from that; or if no servers are returned, use ${SERVERNAME}. 307148871Scperciva# This allows a user to specify "portsnap.freebsd.org" (in which case 308148871Scperciva# portsnap will select one of the mirrors) or "portsnap5.tld.freebsd.org" 309148871Scperciva# (in which case portsnap will use that particular server, since there 310148871Scperciva# won't be an SRV entry for that name). 311148871Scperciva# 312148871Scperciva# We don't implement the recommendations from RFC 2782 completely, since 313148871Scperciva# we are only looking to pick a single server -- the recommendations are 314148871Scperciva# targetted at applications which obtain a list of servers and then try 315148871Scperciva# each in turn, but we are instead just going to pick one server and let 316148871Scperciva# the user re-run portsnap if a broken server was selected. 317148871Scperciva# 318148871Scperciva# We also ignore the Port field, since we are always going to use port 80. 319148871Scpercivafetch_pick_server() { 320150159Scperciva# Check that host(1) exists (i.e., that the system wasn't built with the 321150159Scperciva# NO_BIND flag set) and don't try to find a mirror if it doesn't exist. 322150159Scperciva if ! which -s host; then 323150159Scperciva return 324150159Scperciva fi 325150159Scperciva 326148871Scperciva echo -n "Looking up ${SERVERNAME} mirrors..." 327148871Scperciva 328148871Scperciva# Issue the SRV query and pull out the Priority, Weight, and Target fields. 329148871Scperciva host -t srv "_http._tcp.${SERVERNAME}" | 330148871Scperciva grep -E "^_http._tcp.${SERVERNAME} has SRV record" | 331148871Scperciva cut -f 5,6,8 -d ' ' > serverlist 332148871Scperciva 333148871Scperciva# If no records, give up -- we'll just use the server name we were given. 334148871Scperciva if [ `wc -l < serverlist` -eq 0 ]; then 335148871Scperciva echo " none found." 336148871Scperciva return 337148871Scperciva fi 338148871Scperciva 339148871Scperciva# Find the highest priority level (lowest numeric value). 340148871Scperciva SRV_PRIORITY=`cut -f 1 -d ' ' serverlist | sort -n | head -1` 341148871Scperciva 342148871Scperciva# Add up the weights of the response lines at that priority level. 343148871Scperciva SRV_WSUM=0; 344148871Scperciva while read X; do 345148871Scperciva case "$X" in 346148871Scperciva ${SRV_PRIORITY}\ *) 347148871Scperciva SRV_W=`echo $X | cut -f 2 -d ' '` 348148871Scperciva SRV_WSUM=$(($SRV_WSUM + $SRV_W)) 349148871Scperciva ;; 350148871Scperciva esac 351148871Scperciva done < serverlist 352148871Scperciva 353148871Scperciva# If all the weights are 0, pretend that they are all 1 instead. 354148871Scperciva if [ ${SRV_WSUM} -eq 0 ]; then 355148871Scperciva SRV_WSUM=`grep -E "^${SRV_PRIORITY} " serverlist | wc -l` 356148871Scperciva SRV_W_ADD=1 357148871Scperciva else 358148871Scperciva SRV_W_ADD=0 359148871Scperciva fi 360148871Scperciva 361148871Scperciva# Pick a random value between 1 and the sum of the weights 362148871Scperciva SRV_RND=`jot -r 1 1 ${SRV_WSUM}` 363148871Scperciva 364148871Scperciva# Read through the list of mirrors and set SERVERNAME 365148871Scperciva while read X; do 366148871Scperciva case "$X" in 367148871Scperciva ${SRV_PRIORITY}\ *) 368148871Scperciva SRV_W=`echo $X | cut -f 2 -d ' '` 369148871Scperciva SRV_W=$(($SRV_W + $SRV_W_ADD)) 370148871Scperciva if [ $SRV_RND -le $SRV_W ]; then 371148871Scperciva SERVERNAME=`echo $X | cut -f 3 -d ' '` 372148871Scperciva break 373148871Scperciva else 374148871Scperciva SRV_RND=$(($SRV_RND - $SRV_W)) 375148871Scperciva fi 376148871Scperciva ;; 377148871Scperciva esac 378148871Scperciva done < serverlist 379148871Scperciva 380148871Scperciva echo " using ${SERVERNAME}" 381148871Scperciva} 382148871Scperciva 383148871Scperciva# Check that we have a public key with an appropriate hash, or 384148871Scperciva# fetch the key if it doesn't exist. 385148871Scpercivafetch_key() { 386148871Scperciva if [ -r pub.ssl ] && [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 387148871Scperciva return 388148871Scperciva fi 389148871Scperciva 390148871Scperciva echo -n "Fetching public key... " 391148871Scperciva rm -f pub.ssl 392148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/pub.ssl \ 393148871Scperciva 2>${QUIETREDIR} || true 394148871Scperciva if ! [ -r pub.ssl ]; then 395148871Scperciva echo "failed." 396148871Scperciva return 1 397148871Scperciva fi 398148871Scperciva if ! [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 399148871Scperciva echo "key has incorrect hash." 400148871Scperciva rm -f pub.ssl 401148871Scperciva return 1 402148871Scperciva fi 403148871Scperciva echo "done." 404148871Scperciva} 405148871Scperciva 406148871Scperciva# Fetch a snapshot tag 407148871Scpercivafetch_tag() { 408148871Scperciva rm -f snapshot.ssl tag.new 409148871Scperciva 410148871Scperciva echo ${NDEBUG} "Fetching snapshot tag... " 411148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/$1.ssl 412148871Scperciva 2>${QUIETREDIR} || true 413148871Scperciva if ! [ -r $1.ssl ]; then 414148871Scperciva echo "failed." 415148871Scperciva return 1 416148871Scperciva fi 417148871Scperciva 418148871Scperciva openssl rsautl -pubin -inkey pub.ssl -verify \ 419148871Scperciva < $1.ssl > tag.new 2>${QUIETREDIR} || true 420148871Scperciva rm $1.ssl 421148871Scperciva 422148871Scperciva if ! [ `wc -l < tag.new` = 1 ] || 423148871Scperciva ! grep -qE "^portsnap\|[0-9]{10}\|[0-9a-f]{64}" tag.new; then 424148871Scperciva echo "invalid snapshot tag." 425148871Scperciva return 1 426148871Scperciva fi 427148871Scperciva 428148871Scperciva echo "done." 429148871Scperciva 430148871Scperciva SNAPSHOTDATE=`cut -f 2 -d '|' < tag.new` 431148871Scperciva SNAPSHOTHASH=`cut -f 3 -d '|' < tag.new` 432148871Scperciva} 433148871Scperciva 434148871Scperciva# Sanity-check the date on a snapshot tag 435148871Scpercivafetch_snapshot_tagsanity() { 436148871Scperciva if [ `date "+%s"` -gt `expr ${SNAPSHOTDATE} + 31536000` ]; then 437148871Scperciva echo "Snapshot appears to be more than a year old!" 438148871Scperciva echo "(Is the system clock correct?)" 439149868Scperciva echo "Cowardly refusing to proceed any further." 440148871Scperciva return 1 441148871Scperciva fi 442148871Scperciva if [ `date "+%s"` -lt `expr ${SNAPSHOTDATE} - 86400` ]; then 443148871Scperciva echo -n "Snapshot appears to have been created more than " 444148871Scperciva echo "one day into the future!" 445148871Scperciva echo "(Is the system clock correct?)" 446148871Scperciva echo "Cowardly refusing to proceed any further." 447148871Scperciva return 1 448148871Scperciva fi 449148871Scperciva} 450148871Scperciva 451148871Scperciva# Sanity-check the date on a snapshot update tag 452148871Scpercivafetch_update_tagsanity() { 453148871Scperciva fetch_snapshot_tagsanity || return 1 454148871Scperciva 455148871Scperciva if [ ${OLDSNAPSHOTDATE} -gt ${SNAPSHOTDATE} ]; then 456148871Scperciva echo -n "Latest snapshot on server is " 457148871Scperciva echo "older than what we already have!" 458148871Scperciva echo -n "Cowardly refusing to downgrade from " 459148871Scperciva date -r ${OLDSNAPSHOTDATE} 460148879Scperciva echo "to `date -r ${SNAPSHOTDATE}`." 461148871Scperciva return 1 462148871Scperciva fi 463148871Scperciva} 464148871Scperciva 465148871Scperciva# Compare old and new tags; return 1 if update is unnecessary 466148871Scpercivafetch_update_neededp() { 467148871Scperciva if [ ${OLDSNAPSHOTDATE} -eq ${SNAPSHOTDATE} ]; then 468148871Scperciva echo -n "Latest snapshot on server matches " 469148871Scperciva echo "what we already have." 470148871Scperciva echo "No updates needed." 471148871Scperciva rm tag.new 472148871Scperciva return 1 473148871Scperciva fi 474148871Scperciva if [ ${OLDSNAPSHOTHASH} = ${SNAPSHOTHASH} ]; then 475148871Scperciva echo -n "Ports tree hasn't changed since " 476148871Scperciva echo "last snapshot." 477148871Scperciva echo "No updates needed." 478148871Scperciva rm tag.new 479148871Scperciva return 1 480148871Scperciva fi 481148871Scperciva 482148871Scperciva return 0 483148871Scperciva} 484148871Scperciva 485148871Scperciva# Fetch snapshot metadata file 486148871Scpercivafetch_metadata() { 487148871Scperciva rm -f ${SNAPSHOTHASH} tINDEX.new 488148871Scperciva 489148871Scperciva echo ${NDEBUG} "Fetching snapshot metadata... " 490148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/t/${SNAPSHOTHASH} 491148871Scperciva 2>${QUIETREDIR} || return 492148871Scperciva if [ `${SHA256} -q ${SNAPSHOTHASH}` != ${SNAPSHOTHASH} ]; then 493148871Scperciva echo "snapshot metadata corrupt." 494148871Scperciva return 1 495148871Scperciva fi 496148871Scperciva mv ${SNAPSHOTHASH} tINDEX.new 497148871Scperciva echo "done." 498148871Scperciva} 499148871Scperciva 500148871Scperciva# Warn user about bogus metadata 501148871Scpercivafetch_metadata_freakout() { 502148871Scperciva echo 503148871Scperciva echo "Portsnap metadata is correctly signed, but contains" 504148871Scperciva echo "at least one line which appears bogus." 505148871Scperciva echo "Cowardly refusing to proceed any further." 506148871Scperciva} 507148871Scperciva 508148871Scperciva# Sanity-check a snapshot metadata file 509148871Scpercivafetch_metadata_sanity() { 510148871Scperciva if grep -qvE "^[0-9A-Z.]+\|[0-9a-f]{64}$" tINDEX.new; then 511148871Scperciva fetch_metadata_freakout 512148871Scperciva return 1 513148871Scperciva fi 514148871Scperciva if [ `look INDEX tINDEX.new | wc -l` != 1 ]; then 515148871Scperciva echo 516148871Scperciva echo "Portsnap metadata appears bogus." 517148871Scperciva echo "Cowardly refusing to proceed any further." 518148871Scperciva return 1 519148871Scperciva fi 520148871Scperciva} 521148871Scperciva 522148871Scperciva# Take a list of ${oldhash}|${newhash} and output a list of needed patches 523148871Scpercivafetch_make_patchlist() { 524148871Scperciva grep -vE "^([0-9a-f]{64})\|\1$" | 525148871Scperciva while read LINE; do 526148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 527148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 528148871Scperciva if [ -f "files/${Y}.gz" ]; then continue; fi 529148871Scperciva if [ ! -f "files/${X}.gz" ]; then continue; fi 530148871Scperciva echo "${LINE}" 531148871Scperciva done 532148871Scperciva} 533148871Scperciva 534148871Scperciva# Print user-friendly progress statistics 535148871Scpercivafetch_progress() { 536148871Scperciva LNC=0 537148871Scperciva while read x; do 538148871Scperciva LNC=$(($LNC + 1)) 539148871Scperciva if [ $(($LNC % 10)) = 0 ]; then 540149023Scperciva echo -n $LNC 541148871Scperciva elif [ $(($LNC % 2)) = 0 ]; then 542148871Scperciva echo -n . 543148871Scperciva fi 544148871Scperciva done 545148871Scperciva echo -n " " 546148871Scperciva} 547148871Scperciva 548148871Scperciva# Sanity-check an index file 549148871Scpercivafetch_index_sanity() { 550148871Scperciva if grep -qvE "^[-_+./@0-9A-Za-z]+\|[0-9a-f]{64}$" INDEX.new || 551148871Scperciva fgrep -q "./" INDEX.new; then 552148871Scperciva fetch_metadata_freakout 553148871Scperciva return 1 554148871Scperciva fi 555148871Scperciva} 556148871Scperciva 557148871Scperciva# Verify a list of files 558148871Scpercivafetch_snapshot_verify() { 559148871Scperciva while read F; do 560148871Scperciva if [ `gunzip -c snap/${F} | ${SHA256} -q` != ${F} ]; then 561148871Scperciva echo "snapshot corrupt." 562148871Scperciva return 1 563148871Scperciva fi 564148871Scperciva done 565148871Scperciva return 0 566148871Scperciva} 567148871Scperciva 568148871Scperciva# Fetch a snapshot tarball, extract, and verify. 569148871Scpercivafetch_snapshot() { 570148871Scperciva fetch_tag snapshot || return 1 571148871Scperciva fetch_snapshot_tagsanity || return 1 572148871Scperciva fetch_metadata || return 1 573148871Scperciva fetch_metadata_sanity || return 1 574148871Scperciva 575148871Scperciva rm -f ${SNAPSHOTHASH}.tgz 576148871Scperciva rm -rf snap/ 577148871Scperciva 578148871Scperciva# Don't ask fetch(1) to be quiet -- downloading a snapshot of ~ 35MB will 579148871Scperciva# probably take a while, so the progrees reports that fetch(1) generates 580148871Scperciva# will be useful for keeping the users' attention from drifting. 581148871Scperciva echo "Fetching snapshot generated at `date -r ${SNAPSHOTDATE}`:" 582148871Scperciva fetch http://${SERVERNAME}/s/${SNAPSHOTHASH}.tgz || return 1 583148871Scperciva 584148871Scperciva echo -n "Extracting snapshot... " 585148871Scperciva tar -xzf ${SNAPSHOTHASH}.tgz snap/ || return 1 586148871Scperciva rm ${SNAPSHOTHASH}.tgz 587148871Scperciva echo "done." 588148871Scperciva 589148871Scperciva echo -n "Verifying snapshot integrity... " 590148871Scperciva# Verify the metadata files 591148871Scperciva cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1 592148871Scperciva# Extract the index 593148871Scperciva rm -f INDEX.new 594148871Scperciva gunzip -c snap/`look INDEX tINDEX.new | 595148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 596148871Scperciva fetch_index_sanity || return 1 597148871Scperciva# Verify the snapshot contents 598148871Scperciva cut -f 2 -d '|' INDEX.new | fetch_snapshot_verify || return 1 599148871Scperciva echo "done." 600148871Scperciva 601148871Scperciva# Move files into their proper locations 602148871Scperciva rm -f tag INDEX tINDEX 603148871Scperciva rm -rf files 604148871Scperciva mv tag.new tag 605148871Scperciva mv tINDEX.new tINDEX 606148871Scperciva mv INDEX.new INDEX 607148871Scperciva mv snap/ files/ 608148871Scperciva 609148871Scperciva return 0 610148871Scperciva} 611148871Scperciva 612148871Scperciva# Update a compressed snapshot 613148871Scpercivafetch_update() { 614148871Scperciva rm -f patchlist diff OLD NEW filelist INDEX.new 615148871Scperciva 616148871Scperciva OLDSNAPSHOTDATE=`cut -f 2 -d '|' < tag` 617148871Scperciva OLDSNAPSHOTHASH=`cut -f 3 -d '|' < tag` 618148871Scperciva 619148871Scperciva fetch_tag latest || return 1 620148871Scperciva fetch_update_tagsanity || return 1 621148871Scperciva fetch_update_neededp || return 0 622148871Scperciva fetch_metadata || return 1 623148871Scperciva fetch_metadata_sanity || return 1 624148871Scperciva 625148871Scperciva echo -n "Updating from `date -r ${OLDSNAPSHOTDATE}` " 626148871Scperciva echo "to `date -r ${SNAPSHOTDATE}`." 627148871Scperciva 628148871Scperciva# Generate a list of wanted metadata patches 629148871Scperciva join -t '|' -o 1.2,2.2 tINDEX tINDEX.new | 630148871Scperciva fetch_make_patchlist > patchlist 631148871Scperciva 632148871Scperciva# Attempt to fetch metadata patches 633148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 634148871Scperciva echo ${NDEBUG} "metadata patches.${DDSTATS}" 635148871Scperciva tr '|' '-' < patchlist | 636148871Scperciva lam -s "tp/" - -s ".gz" | 637148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 638148871Scperciva 2>${STATSREDIR} | fetch_progress 639148871Scperciva echo "done." 640148871Scperciva 641148871Scperciva# Attempt to apply metadata patches 642148871Scperciva echo -n "Applying metadata patches... " 643148871Scperciva while read LINE; do 644148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 645148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 646148871Scperciva if [ ! -f "${X}-${Y}.gz" ]; then continue; fi 647148871Scperciva gunzip -c < ${X}-${Y}.gz > diff 648148871Scperciva gunzip -c < files/${X}.gz > OLD 649148871Scperciva cut -c 2- diff | join -t '|' -v 2 - OLD > ptmp 650148871Scperciva grep '^\+' diff | cut -c 2- | 651148871Scperciva sort -k 1,1 -t '|' -m - ptmp > NEW 652148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 653148871Scperciva mv NEW files/${Y} 654148871Scperciva gzip -n files/${Y} 655148871Scperciva fi 656148871Scperciva rm -f diff OLD NEW ${X}-${Y}.gz ptmp 657148871Scperciva done < patchlist 2>${QUIETREDIR} 658148871Scperciva echo "done." 659148871Scperciva 660148871Scperciva# Update metadata without patches 661148871Scperciva join -t '|' -v 2 tINDEX tINDEX.new | 662148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 663148871Scperciva while read Y; do 664148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 665148871Scperciva echo ${Y}; 666148871Scperciva fi 667148871Scperciva done > filelist 668148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 669148871Scperciva echo ${NDEBUG} "metadata files... " 670148871Scperciva lam -s "f/" - -s ".gz" < filelist | 671148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 672148871Scperciva 2>${QUIETREDIR} 673148871Scperciva 674148871Scperciva while read Y; do 675148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 676148871Scperciva mv ${Y}.gz files/${Y}.gz 677148871Scperciva else 678148871Scperciva echo "metadata is corrupt." 679148871Scperciva return 1 680148871Scperciva fi 681148871Scperciva done < filelist 682148871Scperciva echo "done." 683148871Scperciva 684148871Scperciva# Extract the index 685148871Scperciva gunzip -c files/`look INDEX tINDEX.new | 686148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 687148871Scperciva fetch_index_sanity || return 1 688148871Scperciva 689149824Scperciva# If we have decided to refuse certain updates, construct a hybrid index which 690149824Scperciva# is equal to the old index for parts of the tree which we don't want to 691149824Scperciva# update, and equal to the new index for parts of the tree which gets updates. 692149824Scperciva# This means that we should always have a "complete snapshot" of the ports 693149824Scperciva# tree -- with the caveat that it isn't actually a snapshot. 694149824Scperciva if [ ! -z "${REFUSE}" ]; then 695149824Scperciva echo "Refusing to download updates for ${REFUSE}" \ 696149824Scperciva >${QUIETREDIR} 697149824Scperciva 698149824Scperciva grep -Ev "${REFUSE}" INDEX.new > INDEX.tmp 699149824Scperciva grep -E "${REFUSE}" INDEX | 700149824Scperciva sort -m -k 1,1 -t '|' - INDEX.tmp > INDEX.new 701149824Scperciva rm -f INDEX.tmp 702149824Scperciva fi 703149824Scperciva 704148871Scperciva# Generate a list of wanted ports patches 705148871Scperciva join -t '|' -o 1.2,2.2 INDEX INDEX.new | 706148871Scperciva fetch_make_patchlist > patchlist 707148871Scperciva 708148871Scperciva# Attempt to fetch ports patches 709148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 710148871Scperciva echo ${NDEBUG} "patches.${DDSTATS}" 711148871Scperciva tr '|' '-' < patchlist | lam -s "bp/" - | 712148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 713148871Scperciva 2>${STATSREDIR} | fetch_progress 714148871Scperciva echo "done." 715148871Scperciva 716148871Scperciva# Attempt to apply ports patches 717148871Scperciva echo -n "Applying patches... " 718148871Scperciva while read LINE; do 719148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 720148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 721148871Scperciva if [ ! -f "${X}-${Y}" ]; then continue; fi 722148871Scperciva gunzip -c < files/${X}.gz > OLD 723148871Scperciva ${BSPATCH} OLD NEW ${X}-${Y} 724148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 725148871Scperciva mv NEW files/${Y} 726148871Scperciva gzip -n files/${Y} 727148871Scperciva fi 728148871Scperciva rm -f diff OLD NEW ${X}-${Y} 729148871Scperciva done < patchlist 2>${QUIETREDIR} 730148871Scperciva echo "done." 731148871Scperciva 732148871Scperciva# Update ports without patches 733148871Scperciva join -t '|' -v 2 INDEX INDEX.new | 734148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 735148871Scperciva while read Y; do 736148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 737148871Scperciva echo ${Y}; 738148871Scperciva fi 739148871Scperciva done > filelist 740148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 741148871Scperciva echo ${NDEBUG} "new ports or files... " 742148871Scperciva lam -s "f/" - -s ".gz" < filelist | 743148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 744148871Scperciva 2>${QUIETREDIR} 745148871Scperciva 746148871Scperciva while read Y; do 747148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 748148871Scperciva mv ${Y}.gz files/${Y}.gz 749148871Scperciva else 750148871Scperciva echo "snapshot is corrupt." 751148871Scperciva return 1 752148871Scperciva fi 753148871Scperciva done < filelist 754148871Scperciva echo "done." 755148871Scperciva 756148871Scperciva# Remove files which are no longer needed 757148871Scperciva cut -f 2 -d '|' tINDEX INDEX | sort > oldfiles 758148871Scperciva cut -f 2 -d '|' tINDEX.new INDEX.new | sort | comm -13 - oldfiles | 759148871Scperciva lam -s "files/" - -s ".gz" | xargs rm -f 760148871Scperciva rm patchlist filelist oldfiles 761148871Scperciva 762148871Scperciva# We're done! 763148871Scperciva mv INDEX.new INDEX 764148871Scperciva mv tINDEX.new tINDEX 765148871Scperciva mv tag.new tag 766148871Scperciva 767148871Scperciva return 0 768148871Scperciva} 769148871Scperciva 770148871Scperciva# Do the actual work involved in "fetch" / "cron". 771148871Scpercivafetch_run() { 772148871Scperciva fetch_pick_server 773148871Scperciva 774148871Scperciva fetch_key || return 1 775148871Scperciva 776148871Scperciva if ! [ -d files -a -r tag -a -r INDEX -a -r tINDEX ]; then 777148871Scperciva fetch_snapshot || return 1 778148871Scperciva fi 779148871Scperciva fetch_update || return 1 780148871Scperciva} 781148871Scperciva 782148871Scperciva# Build a ports INDEX file 783148871Scpercivaextract_make_index() { 784148871Scperciva gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX | 785148871Scperciva cut -f 2 -d '|'`.gz" | ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2 786148871Scperciva} 787148871Scperciva 788148871Scperciva# Create INDEX, INDEX-5, INDEX-6 789148871Scpercivaextract_indices() { 790148871Scperciva echo -n "Building new INDEX files... " 791148871Scperciva extract_make_index DESCRIBE.4 INDEX || return 1 792148871Scperciva extract_make_index DESCRIBE.5 INDEX-5 || return 1 793148871Scperciva extract_make_index DESCRIBE.6 INDEX-6 || return 1 794148871Scperciva echo "done." 795148871Scperciva} 796148871Scperciva 797149824Scperciva# Create .portsnap.INDEX; if we are REFUSEing to touch certain directories, 798149824Scperciva# merge the values from any exiting .portsnap.INDEX file. 799148871Scpercivaextract_metadata() { 800149824Scperciva if [ -z "${REFUSE}" ]; then 801149984Scperciva sort ${WORKDIR}/INDEX > ${PORTSDIR}/.portsnap.INDEX 802149824Scperciva elif [ -f ${PORTSDIR}/.portsnap.INDEX ]; then 803149824Scperciva grep -E "${REFUSE}" ${PORTSDIR}/.portsnap.INDEX \ 804149824Scperciva > ${PORTSDIR}/.portsnap.INDEX.tmp 805149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort | 806149824Scperciva sort -m - ${PORTSDIR}/.portsnap.INDEX.tmp \ 807149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 808149824Scperciva rm -f ${PORTSDIR}/.portsnap.INDEX.tmp 809149824Scperciva else 810149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort \ 811149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 812149824Scperciva fi 813148871Scperciva} 814148871Scperciva 815148871Scperciva# Do the actual work involved in "extract" 816148871Scpercivaextract_run() { 817154088Scperciva mkdir -p ${PORTSDIR} || return 1 818154088Scperciva 819149824Scperciva if ! 820149824Scperciva if ! [ -z "${EXTRACTPATH}" ]; then 821149824Scperciva grep "^${EXTRACTPATH}" ${WORKDIR}/INDEX 822149824Scperciva elif ! [ -z "${REFUSE}" ]; then 823149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX 824149824Scperciva else 825149824Scperciva cat ${WORKDIR}/INDEX 826149824Scperciva fi | while read LINE; do 827148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 828148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 829148871Scperciva echo ${PORTSDIR}/${FILE} 830148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 831148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 832148871Scperciva return 1 833148871Scperciva fi 834148871Scperciva case ${FILE} in 835148871Scperciva */) 836148871Scperciva rm -rf ${PORTSDIR}/${FILE} 837148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 838148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 839148871Scperciva -C ${PORTSDIR}/${FILE} 840148871Scperciva ;; 841148871Scperciva *) 842148871Scperciva rm -f ${PORTSDIR}/${FILE} 843148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 844148871Scperciva -C ${PORTSDIR} ${FILE} 845148871Scperciva ;; 846148871Scperciva esac 847149041Scperciva done; then 848149041Scperciva return 1 849149041Scperciva fi 850148871Scperciva if [ ! -z "${EXTRACTPATH}" ]; then 851148871Scperciva return 0; 852148871Scperciva fi 853148871Scperciva 854148871Scperciva extract_metadata 855148871Scperciva extract_indices 856148871Scperciva} 857148871Scperciva 858148871Scperciva# Do the actual work involved in "update" 859148871Scpercivaupdate_run() { 860148871Scperciva if ! [ -z "${INDEXONLY}" ]; then 861148871Scperciva extract_indices >/dev/null || return 1 862148871Scperciva return 0 863148871Scperciva fi 864148871Scperciva 865148981Scperciva if sort ${WORKDIR}/INDEX | 866149042Scperciva cmp -s ${PORTSDIR}/.portsnap.INDEX -; then 867148958Scperciva echo "Ports tree is already up to date." 868148958Scperciva return 0 869148958Scperciva fi 870148958Scperciva 871149824Scperciva# If we are REFUSEing to touch certain directories, don't remove files 872149824Scperciva# from those directories (even if they are out of date) 873148871Scperciva echo -n "Removing old files and directories... " 874149824Scperciva if ! [ -z "${REFUSE}" ]; then 875149824Scperciva sort ${WORKDIR}/INDEX | 876149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 877149824Scperciva grep -vE "${REFUSE}" | 878149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 879149824Scperciva else 880149824Scperciva sort ${WORKDIR}/INDEX | 881149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 882149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 883149824Scperciva fi 884148871Scperciva echo "done." 885148871Scperciva 886148871Scperciva# Install new files 887148871Scperciva echo "Extracting new files:" 888149824Scperciva if ! 889149824Scperciva if ! [ -z "${REFUSE}" ]; then 890149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort 891149824Scperciva else 892149824Scperciva sort ${WORKDIR}/INDEX 893149824Scperciva fi | 894149041Scperciva comm -13 ${PORTSDIR}/.portsnap.INDEX - | 895148871Scperciva while read LINE; do 896148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 897148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 898148871Scperciva echo ${PORTSDIR}/${FILE} 899148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 900148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 901148871Scperciva return 1 902148871Scperciva fi 903148871Scperciva case ${FILE} in 904148871Scperciva */) 905148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 906148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 907148871Scperciva -C ${PORTSDIR}/${FILE} 908148871Scperciva ;; 909148871Scperciva *) 910148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 911148871Scperciva -C ${PORTSDIR} ${FILE} 912148871Scperciva ;; 913148871Scperciva esac 914149041Scperciva done; then 915149041Scperciva return 1 916149041Scperciva fi 917148871Scperciva 918148871Scperciva extract_metadata 919148871Scperciva extract_indices 920148871Scperciva} 921148871Scperciva 922148871Scperciva#### Main functions -- call parameter-handling and core functions 923148871Scperciva 924148871Scperciva# Using the command line, configuration file, and defaults, 925148871Scperciva# set all the parameters which are needed later. 926148871Scpercivaget_params() { 927148871Scperciva init_params 928148871Scperciva parse_cmdline $@ 929148871Scperciva sanity_conffile 930148871Scperciva default_conffile 931148871Scperciva parse_conffile 932148871Scperciva default_params 933148871Scperciva} 934148871Scperciva 935148871Scperciva# Fetch command. Make sure that we're being called 936148871Scperciva# interactively, then run fetch_check_params and fetch_run 937148871Scpercivacmd_fetch() { 938148871Scperciva if [ ! -t 0 ]; then 939148871Scperciva echo -n "`basename $0` fetch should not " 940148871Scperciva echo "be run non-interactively." 941148871Scperciva echo "Run `basename $0` cron instead." 942148871Scperciva exit 1 943148871Scperciva fi 944148871Scperciva fetch_check_params 945148871Scperciva fetch_run || exit 1 946148871Scperciva} 947148871Scperciva 948148871Scperciva# Cron command. Make sure the parameters are sensible; wait 949148871Scperciva# rand(3600) seconds; then fetch updates. While fetching updates, 950148871Scperciva# send output to a temporary file; only print that file if the 951148871Scperciva# fetching failed. 952148871Scpercivacmd_cron() { 953148871Scperciva fetch_check_params 954148871Scperciva sleep `jot -r 1 0 3600` 955148871Scperciva 956148871Scperciva TMPFILE=`mktemp /tmp/portsnap.XXXXXX` || exit 1 957148871Scperciva if ! fetch_run >> ${TMPFILE}; then 958148871Scperciva cat ${TMPFILE} 959148871Scperciva rm ${TMPFILE} 960148871Scperciva exit 1 961148871Scperciva fi 962148871Scperciva 963148871Scperciva rm ${TMPFILE} 964148871Scperciva} 965148871Scperciva 966148871Scperciva# Extract command. Make sure the parameters are sensible, 967148871Scperciva# then extract the ports tree (or part thereof). 968148871Scpercivacmd_extract() { 969148871Scperciva extract_check_params 970148871Scperciva extract_run || exit 1 971148871Scperciva} 972148871Scperciva 973148871Scperciva# Update command. Make sure the parameters are sensible, 974148871Scperciva# then update the ports tree. 975148871Scpercivacmd_update() { 976148871Scperciva update_check_params 977148871Scperciva update_run || exit 1 978148871Scperciva} 979148871Scperciva 980148871Scperciva#### Entry point 981148871Scperciva 982148871Scperciva# Make sure we find utilities from the base system 983148871Scpercivaexport PATH=/sbin:/bin:/usr/sbin:/usr/bin:${PATH} 984148871Scperciva 985148871Scpercivaget_params $@ 986149027Scpercivafor COMMAND in ${COMMANDS}; do 987149027Scperciva cmd_${COMMAND} 988149027Scpercivadone 989