portsnap.sh revision 156813
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 156813 2006-03-17 18:54:44Z ru $ 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 321156813Sru# WITHOUT_BIND 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" | 331156406Sume cut -f 5,6,8 -d ' ' | sed -e 's/\.$//' > 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 -rf snap/ 576148871Scperciva 577148871Scperciva# Don't ask fetch(1) to be quiet -- downloading a snapshot of ~ 35MB will 578148871Scperciva# probably take a while, so the progrees reports that fetch(1) generates 579148871Scperciva# will be useful for keeping the users' attention from drifting. 580148871Scperciva echo "Fetching snapshot generated at `date -r ${SNAPSHOTDATE}`:" 581154693Scperciva fetch -r http://${SERVERNAME}/s/${SNAPSHOTHASH}.tgz || return 1 582148871Scperciva 583148871Scperciva echo -n "Extracting snapshot... " 584148871Scperciva tar -xzf ${SNAPSHOTHASH}.tgz snap/ || return 1 585148871Scperciva rm ${SNAPSHOTHASH}.tgz 586148871Scperciva echo "done." 587148871Scperciva 588148871Scperciva echo -n "Verifying snapshot integrity... " 589148871Scperciva# Verify the metadata files 590148871Scperciva cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1 591148871Scperciva# Extract the index 592148871Scperciva rm -f INDEX.new 593148871Scperciva gunzip -c snap/`look INDEX tINDEX.new | 594148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 595148871Scperciva fetch_index_sanity || return 1 596148871Scperciva# Verify the snapshot contents 597148871Scperciva cut -f 2 -d '|' INDEX.new | fetch_snapshot_verify || return 1 598148871Scperciva echo "done." 599148871Scperciva 600148871Scperciva# Move files into their proper locations 601148871Scperciva rm -f tag INDEX tINDEX 602148871Scperciva rm -rf files 603148871Scperciva mv tag.new tag 604148871Scperciva mv tINDEX.new tINDEX 605148871Scperciva mv INDEX.new INDEX 606148871Scperciva mv snap/ files/ 607148871Scperciva 608148871Scperciva return 0 609148871Scperciva} 610148871Scperciva 611148871Scperciva# Update a compressed snapshot 612148871Scpercivafetch_update() { 613148871Scperciva rm -f patchlist diff OLD NEW filelist INDEX.new 614148871Scperciva 615148871Scperciva OLDSNAPSHOTDATE=`cut -f 2 -d '|' < tag` 616148871Scperciva OLDSNAPSHOTHASH=`cut -f 3 -d '|' < tag` 617148871Scperciva 618148871Scperciva fetch_tag latest || return 1 619148871Scperciva fetch_update_tagsanity || return 1 620148871Scperciva fetch_update_neededp || return 0 621148871Scperciva fetch_metadata || return 1 622148871Scperciva fetch_metadata_sanity || return 1 623148871Scperciva 624148871Scperciva echo -n "Updating from `date -r ${OLDSNAPSHOTDATE}` " 625148871Scperciva echo "to `date -r ${SNAPSHOTDATE}`." 626148871Scperciva 627148871Scperciva# Generate a list of wanted metadata patches 628148871Scperciva join -t '|' -o 1.2,2.2 tINDEX tINDEX.new | 629148871Scperciva fetch_make_patchlist > patchlist 630148871Scperciva 631148871Scperciva# Attempt to fetch metadata patches 632148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 633148871Scperciva echo ${NDEBUG} "metadata patches.${DDSTATS}" 634148871Scperciva tr '|' '-' < patchlist | 635148871Scperciva lam -s "tp/" - -s ".gz" | 636148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 637148871Scperciva 2>${STATSREDIR} | fetch_progress 638148871Scperciva echo "done." 639148871Scperciva 640148871Scperciva# Attempt to apply metadata patches 641148871Scperciva echo -n "Applying metadata patches... " 642148871Scperciva while read LINE; do 643148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 644148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 645148871Scperciva if [ ! -f "${X}-${Y}.gz" ]; then continue; fi 646148871Scperciva gunzip -c < ${X}-${Y}.gz > diff 647148871Scperciva gunzip -c < files/${X}.gz > OLD 648148871Scperciva cut -c 2- diff | join -t '|' -v 2 - OLD > ptmp 649148871Scperciva grep '^\+' diff | cut -c 2- | 650148871Scperciva sort -k 1,1 -t '|' -m - ptmp > NEW 651148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 652148871Scperciva mv NEW files/${Y} 653148871Scperciva gzip -n files/${Y} 654148871Scperciva fi 655148871Scperciva rm -f diff OLD NEW ${X}-${Y}.gz ptmp 656148871Scperciva done < patchlist 2>${QUIETREDIR} 657148871Scperciva echo "done." 658148871Scperciva 659148871Scperciva# Update metadata without patches 660148871Scperciva join -t '|' -v 2 tINDEX tINDEX.new | 661148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 662148871Scperciva while read Y; do 663148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 664148871Scperciva echo ${Y}; 665148871Scperciva fi 666148871Scperciva done > filelist 667148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 668148871Scperciva echo ${NDEBUG} "metadata files... " 669148871Scperciva lam -s "f/" - -s ".gz" < filelist | 670148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 671148871Scperciva 2>${QUIETREDIR} 672148871Scperciva 673148871Scperciva while read Y; do 674148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 675148871Scperciva mv ${Y}.gz files/${Y}.gz 676148871Scperciva else 677148871Scperciva echo "metadata is corrupt." 678148871Scperciva return 1 679148871Scperciva fi 680148871Scperciva done < filelist 681148871Scperciva echo "done." 682148871Scperciva 683148871Scperciva# Extract the index 684148871Scperciva gunzip -c files/`look INDEX tINDEX.new | 685148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 686148871Scperciva fetch_index_sanity || return 1 687148871Scperciva 688149824Scperciva# If we have decided to refuse certain updates, construct a hybrid index which 689149824Scperciva# is equal to the old index for parts of the tree which we don't want to 690149824Scperciva# update, and equal to the new index for parts of the tree which gets updates. 691149824Scperciva# This means that we should always have a "complete snapshot" of the ports 692149824Scperciva# tree -- with the caveat that it isn't actually a snapshot. 693149824Scperciva if [ ! -z "${REFUSE}" ]; then 694149824Scperciva echo "Refusing to download updates for ${REFUSE}" \ 695149824Scperciva >${QUIETREDIR} 696149824Scperciva 697149824Scperciva grep -Ev "${REFUSE}" INDEX.new > INDEX.tmp 698149824Scperciva grep -E "${REFUSE}" INDEX | 699149824Scperciva sort -m -k 1,1 -t '|' - INDEX.tmp > INDEX.new 700149824Scperciva rm -f INDEX.tmp 701149824Scperciva fi 702149824Scperciva 703148871Scperciva# Generate a list of wanted ports patches 704148871Scperciva join -t '|' -o 1.2,2.2 INDEX INDEX.new | 705148871Scperciva fetch_make_patchlist > patchlist 706148871Scperciva 707148871Scperciva# Attempt to fetch ports patches 708148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 709148871Scperciva echo ${NDEBUG} "patches.${DDSTATS}" 710148871Scperciva tr '|' '-' < patchlist | lam -s "bp/" - | 711148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 712148871Scperciva 2>${STATSREDIR} | fetch_progress 713148871Scperciva echo "done." 714148871Scperciva 715148871Scperciva# Attempt to apply ports patches 716148871Scperciva echo -n "Applying patches... " 717148871Scperciva while read LINE; do 718148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 719148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 720148871Scperciva if [ ! -f "${X}-${Y}" ]; then continue; fi 721148871Scperciva gunzip -c < files/${X}.gz > OLD 722148871Scperciva ${BSPATCH} OLD NEW ${X}-${Y} 723148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 724148871Scperciva mv NEW files/${Y} 725148871Scperciva gzip -n files/${Y} 726148871Scperciva fi 727148871Scperciva rm -f diff OLD NEW ${X}-${Y} 728148871Scperciva done < patchlist 2>${QUIETREDIR} 729148871Scperciva echo "done." 730148871Scperciva 731148871Scperciva# Update ports without patches 732148871Scperciva join -t '|' -v 2 INDEX INDEX.new | 733148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 734148871Scperciva while read Y; do 735148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 736148871Scperciva echo ${Y}; 737148871Scperciva fi 738148871Scperciva done > filelist 739148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 740148871Scperciva echo ${NDEBUG} "new ports or files... " 741148871Scperciva lam -s "f/" - -s ".gz" < filelist | 742148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 743148871Scperciva 2>${QUIETREDIR} 744148871Scperciva 745148871Scperciva while read Y; do 746148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 747148871Scperciva mv ${Y}.gz files/${Y}.gz 748148871Scperciva else 749148871Scperciva echo "snapshot is corrupt." 750148871Scperciva return 1 751148871Scperciva fi 752148871Scperciva done < filelist 753148871Scperciva echo "done." 754148871Scperciva 755148871Scperciva# Remove files which are no longer needed 756148871Scperciva cut -f 2 -d '|' tINDEX INDEX | sort > oldfiles 757148871Scperciva cut -f 2 -d '|' tINDEX.new INDEX.new | sort | comm -13 - oldfiles | 758148871Scperciva lam -s "files/" - -s ".gz" | xargs rm -f 759148871Scperciva rm patchlist filelist oldfiles 760148871Scperciva 761148871Scperciva# We're done! 762148871Scperciva mv INDEX.new INDEX 763148871Scperciva mv tINDEX.new tINDEX 764148871Scperciva mv tag.new tag 765148871Scperciva 766148871Scperciva return 0 767148871Scperciva} 768148871Scperciva 769148871Scperciva# Do the actual work involved in "fetch" / "cron". 770148871Scpercivafetch_run() { 771148871Scperciva fetch_pick_server 772148871Scperciva 773148871Scperciva fetch_key || return 1 774148871Scperciva 775148871Scperciva if ! [ -d files -a -r tag -a -r INDEX -a -r tINDEX ]; then 776148871Scperciva fetch_snapshot || return 1 777148871Scperciva fi 778148871Scperciva fetch_update || return 1 779148871Scperciva} 780148871Scperciva 781148871Scperciva# Build a ports INDEX file 782148871Scpercivaextract_make_index() { 783148871Scperciva gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX | 784148871Scperciva cut -f 2 -d '|'`.gz" | ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2 785148871Scperciva} 786148871Scperciva 787148871Scperciva# Create INDEX, INDEX-5, INDEX-6 788148871Scpercivaextract_indices() { 789148871Scperciva echo -n "Building new INDEX files... " 790148871Scperciva extract_make_index DESCRIBE.4 INDEX || return 1 791148871Scperciva extract_make_index DESCRIBE.5 INDEX-5 || return 1 792148871Scperciva extract_make_index DESCRIBE.6 INDEX-6 || return 1 793148871Scperciva echo "done." 794148871Scperciva} 795148871Scperciva 796149824Scperciva# Create .portsnap.INDEX; if we are REFUSEing to touch certain directories, 797149824Scperciva# merge the values from any exiting .portsnap.INDEX file. 798148871Scpercivaextract_metadata() { 799149824Scperciva if [ -z "${REFUSE}" ]; then 800149984Scperciva sort ${WORKDIR}/INDEX > ${PORTSDIR}/.portsnap.INDEX 801149824Scperciva elif [ -f ${PORTSDIR}/.portsnap.INDEX ]; then 802149824Scperciva grep -E "${REFUSE}" ${PORTSDIR}/.portsnap.INDEX \ 803149824Scperciva > ${PORTSDIR}/.portsnap.INDEX.tmp 804149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort | 805149824Scperciva sort -m - ${PORTSDIR}/.portsnap.INDEX.tmp \ 806149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 807149824Scperciva rm -f ${PORTSDIR}/.portsnap.INDEX.tmp 808149824Scperciva else 809149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort \ 810149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 811149824Scperciva fi 812148871Scperciva} 813148871Scperciva 814148871Scperciva# Do the actual work involved in "extract" 815148871Scpercivaextract_run() { 816154088Scperciva mkdir -p ${PORTSDIR} || return 1 817154088Scperciva 818149824Scperciva if ! 819149824Scperciva if ! [ -z "${EXTRACTPATH}" ]; then 820149824Scperciva grep "^${EXTRACTPATH}" ${WORKDIR}/INDEX 821149824Scperciva elif ! [ -z "${REFUSE}" ]; then 822149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX 823149824Scperciva else 824149824Scperciva cat ${WORKDIR}/INDEX 825149824Scperciva fi | while read LINE; do 826148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 827148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 828148871Scperciva echo ${PORTSDIR}/${FILE} 829148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 830148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 831148871Scperciva return 1 832148871Scperciva fi 833148871Scperciva case ${FILE} in 834148871Scperciva */) 835148871Scperciva rm -rf ${PORTSDIR}/${FILE} 836148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 837148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 838148871Scperciva -C ${PORTSDIR}/${FILE} 839148871Scperciva ;; 840148871Scperciva *) 841148871Scperciva rm -f ${PORTSDIR}/${FILE} 842148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 843148871Scperciva -C ${PORTSDIR} ${FILE} 844148871Scperciva ;; 845148871Scperciva esac 846149041Scperciva done; then 847149041Scperciva return 1 848149041Scperciva fi 849148871Scperciva if [ ! -z "${EXTRACTPATH}" ]; then 850148871Scperciva return 0; 851148871Scperciva fi 852148871Scperciva 853148871Scperciva extract_metadata 854148871Scperciva extract_indices 855148871Scperciva} 856148871Scperciva 857148871Scperciva# Do the actual work involved in "update" 858148871Scpercivaupdate_run() { 859148871Scperciva if ! [ -z "${INDEXONLY}" ]; then 860148871Scperciva extract_indices >/dev/null || return 1 861148871Scperciva return 0 862148871Scperciva fi 863148871Scperciva 864148981Scperciva if sort ${WORKDIR}/INDEX | 865149042Scperciva cmp -s ${PORTSDIR}/.portsnap.INDEX -; then 866148958Scperciva echo "Ports tree is already up to date." 867148958Scperciva return 0 868148958Scperciva fi 869148958Scperciva 870149824Scperciva# If we are REFUSEing to touch certain directories, don't remove files 871149824Scperciva# from those directories (even if they are out of date) 872148871Scperciva echo -n "Removing old files and directories... " 873149824Scperciva if ! [ -z "${REFUSE}" ]; then 874149824Scperciva sort ${WORKDIR}/INDEX | 875149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 876149824Scperciva grep -vE "${REFUSE}" | 877149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 878149824Scperciva else 879149824Scperciva sort ${WORKDIR}/INDEX | 880149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 881149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 882149824Scperciva fi 883148871Scperciva echo "done." 884148871Scperciva 885148871Scperciva# Install new files 886148871Scperciva echo "Extracting new files:" 887149824Scperciva if ! 888149824Scperciva if ! [ -z "${REFUSE}" ]; then 889149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort 890149824Scperciva else 891149824Scperciva sort ${WORKDIR}/INDEX 892149824Scperciva fi | 893149041Scperciva comm -13 ${PORTSDIR}/.portsnap.INDEX - | 894148871Scperciva while read LINE; do 895148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 896148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 897148871Scperciva echo ${PORTSDIR}/${FILE} 898148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 899148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 900148871Scperciva return 1 901148871Scperciva fi 902148871Scperciva case ${FILE} in 903148871Scperciva */) 904148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 905148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 906148871Scperciva -C ${PORTSDIR}/${FILE} 907148871Scperciva ;; 908148871Scperciva *) 909148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 910148871Scperciva -C ${PORTSDIR} ${FILE} 911148871Scperciva ;; 912148871Scperciva esac 913149041Scperciva done; then 914149041Scperciva return 1 915149041Scperciva fi 916148871Scperciva 917148871Scperciva extract_metadata 918148871Scperciva extract_indices 919148871Scperciva} 920148871Scperciva 921148871Scperciva#### Main functions -- call parameter-handling and core functions 922148871Scperciva 923148871Scperciva# Using the command line, configuration file, and defaults, 924148871Scperciva# set all the parameters which are needed later. 925148871Scpercivaget_params() { 926148871Scperciva init_params 927148871Scperciva parse_cmdline $@ 928148871Scperciva sanity_conffile 929148871Scperciva default_conffile 930148871Scperciva parse_conffile 931148871Scperciva default_params 932148871Scperciva} 933148871Scperciva 934148871Scperciva# Fetch command. Make sure that we're being called 935148871Scperciva# interactively, then run fetch_check_params and fetch_run 936148871Scpercivacmd_fetch() { 937148871Scperciva if [ ! -t 0 ]; then 938148871Scperciva echo -n "`basename $0` fetch should not " 939148871Scperciva echo "be run non-interactively." 940148871Scperciva echo "Run `basename $0` cron instead." 941148871Scperciva exit 1 942148871Scperciva fi 943148871Scperciva fetch_check_params 944148871Scperciva fetch_run || exit 1 945148871Scperciva} 946148871Scperciva 947148871Scperciva# Cron command. Make sure the parameters are sensible; wait 948148871Scperciva# rand(3600) seconds; then fetch updates. While fetching updates, 949148871Scperciva# send output to a temporary file; only print that file if the 950148871Scperciva# fetching failed. 951148871Scpercivacmd_cron() { 952148871Scperciva fetch_check_params 953148871Scperciva sleep `jot -r 1 0 3600` 954148871Scperciva 955148871Scperciva TMPFILE=`mktemp /tmp/portsnap.XXXXXX` || exit 1 956148871Scperciva if ! fetch_run >> ${TMPFILE}; then 957148871Scperciva cat ${TMPFILE} 958148871Scperciva rm ${TMPFILE} 959148871Scperciva exit 1 960148871Scperciva fi 961148871Scperciva 962148871Scperciva rm ${TMPFILE} 963148871Scperciva} 964148871Scperciva 965148871Scperciva# Extract command. Make sure the parameters are sensible, 966148871Scperciva# then extract the ports tree (or part thereof). 967148871Scpercivacmd_extract() { 968148871Scperciva extract_check_params 969148871Scperciva extract_run || exit 1 970148871Scperciva} 971148871Scperciva 972148871Scperciva# Update command. Make sure the parameters are sensible, 973148871Scperciva# then update the ports tree. 974148871Scpercivacmd_update() { 975148871Scperciva update_check_params 976148871Scperciva update_run || exit 1 977148871Scperciva} 978148871Scperciva 979148871Scperciva#### Entry point 980148871Scperciva 981148871Scperciva# Make sure we find utilities from the base system 982148871Scpercivaexport PATH=/sbin:/bin:/usr/sbin:/usr/bin:${PATH} 983148871Scperciva 984148871Scpercivaget_params $@ 985149027Scpercivafor COMMAND in ${COMMANDS}; do 986149027Scperciva cmd_${COMMAND} 987149027Scpercivadone 988