portsnap.sh revision 158245
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 158245 2006-05-02 05:27:30Z 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 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. 329158245Scperciva# BIND 9 prints "$name has SRV record ..." while BIND 8 prints 330158245Scperciva# "$name server selection ..."; we allow either format. 331158245Scperciva MLIST="_http._tcp.${SERVERNAME}" 332158245Scperciva host -t srv "${MLIST}" | 333158245Scperciva sed -nE "s/${MLIST} (has SRV record|server selection) //p" | 334158245Scperciva cut -f 1,2,4 -d ' ' | 335158245Scperciva sed -e 's/\.$//' > serverlist 336148871Scperciva 337148871Scperciva# If no records, give up -- we'll just use the server name we were given. 338148871Scperciva if [ `wc -l < serverlist` -eq 0 ]; then 339148871Scperciva echo " none found." 340148871Scperciva return 341148871Scperciva fi 342148871Scperciva 343148871Scperciva# Find the highest priority level (lowest numeric value). 344148871Scperciva SRV_PRIORITY=`cut -f 1 -d ' ' serverlist | sort -n | head -1` 345148871Scperciva 346148871Scperciva# Add up the weights of the response lines at that priority level. 347148871Scperciva SRV_WSUM=0; 348148871Scperciva while read X; do 349148871Scperciva case "$X" in 350148871Scperciva ${SRV_PRIORITY}\ *) 351148871Scperciva SRV_W=`echo $X | cut -f 2 -d ' '` 352148871Scperciva SRV_WSUM=$(($SRV_WSUM + $SRV_W)) 353148871Scperciva ;; 354148871Scperciva esac 355148871Scperciva done < serverlist 356148871Scperciva 357148871Scperciva# If all the weights are 0, pretend that they are all 1 instead. 358148871Scperciva if [ ${SRV_WSUM} -eq 0 ]; then 359148871Scperciva SRV_WSUM=`grep -E "^${SRV_PRIORITY} " serverlist | wc -l` 360148871Scperciva SRV_W_ADD=1 361148871Scperciva else 362148871Scperciva SRV_W_ADD=0 363148871Scperciva fi 364148871Scperciva 365148871Scperciva# Pick a random value between 1 and the sum of the weights 366148871Scperciva SRV_RND=`jot -r 1 1 ${SRV_WSUM}` 367148871Scperciva 368148871Scperciva# Read through the list of mirrors and set SERVERNAME 369148871Scperciva while read X; do 370148871Scperciva case "$X" in 371148871Scperciva ${SRV_PRIORITY}\ *) 372148871Scperciva SRV_W=`echo $X | cut -f 2 -d ' '` 373148871Scperciva SRV_W=$(($SRV_W + $SRV_W_ADD)) 374148871Scperciva if [ $SRV_RND -le $SRV_W ]; then 375148871Scperciva SERVERNAME=`echo $X | cut -f 3 -d ' '` 376148871Scperciva break 377148871Scperciva else 378148871Scperciva SRV_RND=$(($SRV_RND - $SRV_W)) 379148871Scperciva fi 380148871Scperciva ;; 381148871Scperciva esac 382148871Scperciva done < serverlist 383148871Scperciva 384148871Scperciva echo " using ${SERVERNAME}" 385148871Scperciva} 386148871Scperciva 387148871Scperciva# Check that we have a public key with an appropriate hash, or 388148871Scperciva# fetch the key if it doesn't exist. 389148871Scpercivafetch_key() { 390148871Scperciva if [ -r pub.ssl ] && [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 391148871Scperciva return 392148871Scperciva fi 393148871Scperciva 394148871Scperciva echo -n "Fetching public key... " 395148871Scperciva rm -f pub.ssl 396148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/pub.ssl \ 397148871Scperciva 2>${QUIETREDIR} || true 398148871Scperciva if ! [ -r pub.ssl ]; then 399148871Scperciva echo "failed." 400148871Scperciva return 1 401148871Scperciva fi 402148871Scperciva if ! [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then 403148871Scperciva echo "key has incorrect hash." 404148871Scperciva rm -f pub.ssl 405148871Scperciva return 1 406148871Scperciva fi 407148871Scperciva echo "done." 408148871Scperciva} 409148871Scperciva 410148871Scperciva# Fetch a snapshot tag 411148871Scpercivafetch_tag() { 412148871Scperciva rm -f snapshot.ssl tag.new 413148871Scperciva 414148871Scperciva echo ${NDEBUG} "Fetching snapshot tag... " 415148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/$1.ssl 416148871Scperciva 2>${QUIETREDIR} || true 417148871Scperciva if ! [ -r $1.ssl ]; then 418148871Scperciva echo "failed." 419148871Scperciva return 1 420148871Scperciva fi 421148871Scperciva 422148871Scperciva openssl rsautl -pubin -inkey pub.ssl -verify \ 423148871Scperciva < $1.ssl > tag.new 2>${QUIETREDIR} || true 424148871Scperciva rm $1.ssl 425148871Scperciva 426148871Scperciva if ! [ `wc -l < tag.new` = 1 ] || 427148871Scperciva ! grep -qE "^portsnap\|[0-9]{10}\|[0-9a-f]{64}" tag.new; then 428148871Scperciva echo "invalid snapshot tag." 429148871Scperciva return 1 430148871Scperciva fi 431148871Scperciva 432148871Scperciva echo "done." 433148871Scperciva 434148871Scperciva SNAPSHOTDATE=`cut -f 2 -d '|' < tag.new` 435148871Scperciva SNAPSHOTHASH=`cut -f 3 -d '|' < tag.new` 436148871Scperciva} 437148871Scperciva 438148871Scperciva# Sanity-check the date on a snapshot tag 439148871Scpercivafetch_snapshot_tagsanity() { 440148871Scperciva if [ `date "+%s"` -gt `expr ${SNAPSHOTDATE} + 31536000` ]; then 441148871Scperciva echo "Snapshot appears to be more than a year old!" 442148871Scperciva echo "(Is the system clock correct?)" 443149868Scperciva echo "Cowardly refusing to proceed any further." 444148871Scperciva return 1 445148871Scperciva fi 446148871Scperciva if [ `date "+%s"` -lt `expr ${SNAPSHOTDATE} - 86400` ]; then 447148871Scperciva echo -n "Snapshot appears to have been created more than " 448148871Scperciva echo "one day into the future!" 449148871Scperciva echo "(Is the system clock correct?)" 450148871Scperciva echo "Cowardly refusing to proceed any further." 451148871Scperciva return 1 452148871Scperciva fi 453148871Scperciva} 454148871Scperciva 455148871Scperciva# Sanity-check the date on a snapshot update tag 456148871Scpercivafetch_update_tagsanity() { 457148871Scperciva fetch_snapshot_tagsanity || return 1 458148871Scperciva 459148871Scperciva if [ ${OLDSNAPSHOTDATE} -gt ${SNAPSHOTDATE} ]; then 460148871Scperciva echo -n "Latest snapshot on server is " 461148871Scperciva echo "older than what we already have!" 462148871Scperciva echo -n "Cowardly refusing to downgrade from " 463148871Scperciva date -r ${OLDSNAPSHOTDATE} 464148879Scperciva echo "to `date -r ${SNAPSHOTDATE}`." 465148871Scperciva return 1 466148871Scperciva fi 467148871Scperciva} 468148871Scperciva 469148871Scperciva# Compare old and new tags; return 1 if update is unnecessary 470148871Scpercivafetch_update_neededp() { 471148871Scperciva if [ ${OLDSNAPSHOTDATE} -eq ${SNAPSHOTDATE} ]; then 472148871Scperciva echo -n "Latest snapshot on server matches " 473148871Scperciva echo "what we already have." 474148871Scperciva echo "No updates needed." 475148871Scperciva rm tag.new 476148871Scperciva return 1 477148871Scperciva fi 478148871Scperciva if [ ${OLDSNAPSHOTHASH} = ${SNAPSHOTHASH} ]; then 479148871Scperciva echo -n "Ports tree hasn't changed since " 480148871Scperciva echo "last snapshot." 481148871Scperciva echo "No updates needed." 482148871Scperciva rm tag.new 483148871Scperciva return 1 484148871Scperciva fi 485148871Scperciva 486148871Scperciva return 0 487148871Scperciva} 488148871Scperciva 489148871Scperciva# Fetch snapshot metadata file 490148871Scpercivafetch_metadata() { 491148871Scperciva rm -f ${SNAPSHOTHASH} tINDEX.new 492148871Scperciva 493148871Scperciva echo ${NDEBUG} "Fetching snapshot metadata... " 494148871Scperciva fetch ${QUIETFLAG} http://${SERVERNAME}/t/${SNAPSHOTHASH} 495148871Scperciva 2>${QUIETREDIR} || return 496148871Scperciva if [ `${SHA256} -q ${SNAPSHOTHASH}` != ${SNAPSHOTHASH} ]; then 497148871Scperciva echo "snapshot metadata corrupt." 498148871Scperciva return 1 499148871Scperciva fi 500148871Scperciva mv ${SNAPSHOTHASH} tINDEX.new 501148871Scperciva echo "done." 502148871Scperciva} 503148871Scperciva 504148871Scperciva# Warn user about bogus metadata 505148871Scpercivafetch_metadata_freakout() { 506148871Scperciva echo 507148871Scperciva echo "Portsnap metadata is correctly signed, but contains" 508148871Scperciva echo "at least one line which appears bogus." 509148871Scperciva echo "Cowardly refusing to proceed any further." 510148871Scperciva} 511148871Scperciva 512148871Scperciva# Sanity-check a snapshot metadata file 513148871Scpercivafetch_metadata_sanity() { 514148871Scperciva if grep -qvE "^[0-9A-Z.]+\|[0-9a-f]{64}$" tINDEX.new; then 515148871Scperciva fetch_metadata_freakout 516148871Scperciva return 1 517148871Scperciva fi 518148871Scperciva if [ `look INDEX tINDEX.new | wc -l` != 1 ]; then 519148871Scperciva echo 520148871Scperciva echo "Portsnap metadata appears bogus." 521148871Scperciva echo "Cowardly refusing to proceed any further." 522148871Scperciva return 1 523148871Scperciva fi 524148871Scperciva} 525148871Scperciva 526148871Scperciva# Take a list of ${oldhash}|${newhash} and output a list of needed patches 527148871Scpercivafetch_make_patchlist() { 528148871Scperciva grep -vE "^([0-9a-f]{64})\|\1$" | 529148871Scperciva while read LINE; do 530148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 531148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 532148871Scperciva if [ -f "files/${Y}.gz" ]; then continue; fi 533148871Scperciva if [ ! -f "files/${X}.gz" ]; then continue; fi 534148871Scperciva echo "${LINE}" 535148871Scperciva done 536148871Scperciva} 537148871Scperciva 538148871Scperciva# Print user-friendly progress statistics 539148871Scpercivafetch_progress() { 540148871Scperciva LNC=0 541148871Scperciva while read x; do 542148871Scperciva LNC=$(($LNC + 1)) 543148871Scperciva if [ $(($LNC % 10)) = 0 ]; then 544149023Scperciva echo -n $LNC 545148871Scperciva elif [ $(($LNC % 2)) = 0 ]; then 546148871Scperciva echo -n . 547148871Scperciva fi 548148871Scperciva done 549148871Scperciva echo -n " " 550148871Scperciva} 551148871Scperciva 552148871Scperciva# Sanity-check an index file 553148871Scpercivafetch_index_sanity() { 554148871Scperciva if grep -qvE "^[-_+./@0-9A-Za-z]+\|[0-9a-f]{64}$" INDEX.new || 555148871Scperciva fgrep -q "./" INDEX.new; then 556148871Scperciva fetch_metadata_freakout 557148871Scperciva return 1 558148871Scperciva fi 559148871Scperciva} 560148871Scperciva 561148871Scperciva# Verify a list of files 562148871Scpercivafetch_snapshot_verify() { 563148871Scperciva while read F; do 564148871Scperciva if [ `gunzip -c snap/${F} | ${SHA256} -q` != ${F} ]; then 565148871Scperciva echo "snapshot corrupt." 566148871Scperciva return 1 567148871Scperciva fi 568148871Scperciva done 569148871Scperciva return 0 570148871Scperciva} 571148871Scperciva 572148871Scperciva# Fetch a snapshot tarball, extract, and verify. 573148871Scpercivafetch_snapshot() { 574148871Scperciva fetch_tag snapshot || return 1 575148871Scperciva fetch_snapshot_tagsanity || return 1 576148871Scperciva fetch_metadata || return 1 577148871Scperciva fetch_metadata_sanity || return 1 578148871Scperciva 579148871Scperciva rm -rf snap/ 580148871Scperciva 581148871Scperciva# Don't ask fetch(1) to be quiet -- downloading a snapshot of ~ 35MB will 582148871Scperciva# probably take a while, so the progrees reports that fetch(1) generates 583148871Scperciva# will be useful for keeping the users' attention from drifting. 584148871Scperciva echo "Fetching snapshot generated at `date -r ${SNAPSHOTDATE}`:" 585154693Scperciva fetch -r http://${SERVERNAME}/s/${SNAPSHOTHASH}.tgz || return 1 586148871Scperciva 587148871Scperciva echo -n "Extracting snapshot... " 588148871Scperciva tar -xzf ${SNAPSHOTHASH}.tgz snap/ || return 1 589148871Scperciva rm ${SNAPSHOTHASH}.tgz 590148871Scperciva echo "done." 591148871Scperciva 592148871Scperciva echo -n "Verifying snapshot integrity... " 593148871Scperciva# Verify the metadata files 594148871Scperciva cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1 595148871Scperciva# Extract the index 596148871Scperciva rm -f INDEX.new 597148871Scperciva gunzip -c snap/`look INDEX tINDEX.new | 598148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 599148871Scperciva fetch_index_sanity || return 1 600148871Scperciva# Verify the snapshot contents 601148871Scperciva cut -f 2 -d '|' INDEX.new | fetch_snapshot_verify || return 1 602148871Scperciva echo "done." 603148871Scperciva 604148871Scperciva# Move files into their proper locations 605148871Scperciva rm -f tag INDEX tINDEX 606148871Scperciva rm -rf files 607148871Scperciva mv tag.new tag 608148871Scperciva mv tINDEX.new tINDEX 609148871Scperciva mv INDEX.new INDEX 610148871Scperciva mv snap/ files/ 611148871Scperciva 612148871Scperciva return 0 613148871Scperciva} 614148871Scperciva 615148871Scperciva# Update a compressed snapshot 616148871Scpercivafetch_update() { 617148871Scperciva rm -f patchlist diff OLD NEW filelist INDEX.new 618148871Scperciva 619148871Scperciva OLDSNAPSHOTDATE=`cut -f 2 -d '|' < tag` 620148871Scperciva OLDSNAPSHOTHASH=`cut -f 3 -d '|' < tag` 621148871Scperciva 622148871Scperciva fetch_tag latest || return 1 623148871Scperciva fetch_update_tagsanity || return 1 624148871Scperciva fetch_update_neededp || return 0 625148871Scperciva fetch_metadata || return 1 626148871Scperciva fetch_metadata_sanity || return 1 627148871Scperciva 628148871Scperciva echo -n "Updating from `date -r ${OLDSNAPSHOTDATE}` " 629148871Scperciva echo "to `date -r ${SNAPSHOTDATE}`." 630148871Scperciva 631148871Scperciva# Generate a list of wanted metadata patches 632148871Scperciva join -t '|' -o 1.2,2.2 tINDEX tINDEX.new | 633148871Scperciva fetch_make_patchlist > patchlist 634148871Scperciva 635148871Scperciva# Attempt to fetch metadata patches 636148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 637148871Scperciva echo ${NDEBUG} "metadata patches.${DDSTATS}" 638148871Scperciva tr '|' '-' < patchlist | 639148871Scperciva lam -s "tp/" - -s ".gz" | 640148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 641148871Scperciva 2>${STATSREDIR} | fetch_progress 642148871Scperciva echo "done." 643148871Scperciva 644148871Scperciva# Attempt to apply metadata patches 645148871Scperciva echo -n "Applying metadata patches... " 646148871Scperciva while read LINE; do 647148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 648148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 649148871Scperciva if [ ! -f "${X}-${Y}.gz" ]; then continue; fi 650148871Scperciva gunzip -c < ${X}-${Y}.gz > diff 651148871Scperciva gunzip -c < files/${X}.gz > OLD 652148871Scperciva cut -c 2- diff | join -t '|' -v 2 - OLD > ptmp 653148871Scperciva grep '^\+' diff | cut -c 2- | 654148871Scperciva sort -k 1,1 -t '|' -m - ptmp > NEW 655148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 656148871Scperciva mv NEW files/${Y} 657148871Scperciva gzip -n files/${Y} 658148871Scperciva fi 659148871Scperciva rm -f diff OLD NEW ${X}-${Y}.gz ptmp 660148871Scperciva done < patchlist 2>${QUIETREDIR} 661148871Scperciva echo "done." 662148871Scperciva 663148871Scperciva# Update metadata without patches 664148871Scperciva join -t '|' -v 2 tINDEX tINDEX.new | 665148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 666148871Scperciva while read Y; do 667148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 668148871Scperciva echo ${Y}; 669148871Scperciva fi 670148871Scperciva done > filelist 671148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 672148871Scperciva echo ${NDEBUG} "metadata files... " 673148871Scperciva lam -s "f/" - -s ".gz" < filelist | 674148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 675148871Scperciva 2>${QUIETREDIR} 676148871Scperciva 677148871Scperciva while read Y; do 678148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 679148871Scperciva mv ${Y}.gz files/${Y}.gz 680148871Scperciva else 681148871Scperciva echo "metadata is corrupt." 682148871Scperciva return 1 683148871Scperciva fi 684148871Scperciva done < filelist 685148871Scperciva echo "done." 686148871Scperciva 687148871Scperciva# Extract the index 688148871Scperciva gunzip -c files/`look INDEX tINDEX.new | 689148871Scperciva cut -f 2 -d '|'`.gz > INDEX.new 690148871Scperciva fetch_index_sanity || return 1 691148871Scperciva 692149824Scperciva# If we have decided to refuse certain updates, construct a hybrid index which 693149824Scperciva# is equal to the old index for parts of the tree which we don't want to 694149824Scperciva# update, and equal to the new index for parts of the tree which gets updates. 695149824Scperciva# This means that we should always have a "complete snapshot" of the ports 696149824Scperciva# tree -- with the caveat that it isn't actually a snapshot. 697149824Scperciva if [ ! -z "${REFUSE}" ]; then 698149824Scperciva echo "Refusing to download updates for ${REFUSE}" \ 699149824Scperciva >${QUIETREDIR} 700149824Scperciva 701149824Scperciva grep -Ev "${REFUSE}" INDEX.new > INDEX.tmp 702149824Scperciva grep -E "${REFUSE}" INDEX | 703149824Scperciva sort -m -k 1,1 -t '|' - INDEX.tmp > INDEX.new 704149824Scperciva rm -f INDEX.tmp 705149824Scperciva fi 706149824Scperciva 707148871Scperciva# Generate a list of wanted ports patches 708148871Scperciva join -t '|' -o 1.2,2.2 INDEX INDEX.new | 709148871Scperciva fetch_make_patchlist > patchlist 710148871Scperciva 711148871Scperciva# Attempt to fetch ports patches 712148871Scperciva echo -n "Fetching `wc -l < patchlist | tr -d ' '` " 713148871Scperciva echo ${NDEBUG} "patches.${DDSTATS}" 714148871Scperciva tr '|' '-' < patchlist | lam -s "bp/" - | 715148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 716148871Scperciva 2>${STATSREDIR} | fetch_progress 717148871Scperciva echo "done." 718148871Scperciva 719148871Scperciva# Attempt to apply ports patches 720148871Scperciva echo -n "Applying patches... " 721148871Scperciva while read LINE; do 722148871Scperciva X=`echo ${LINE} | cut -f 1 -d '|'` 723148871Scperciva Y=`echo ${LINE} | cut -f 2 -d '|'` 724148871Scperciva if [ ! -f "${X}-${Y}" ]; then continue; fi 725148871Scperciva gunzip -c < files/${X}.gz > OLD 726148871Scperciva ${BSPATCH} OLD NEW ${X}-${Y} 727148871Scperciva if [ `${SHA256} -q NEW` = ${Y} ]; then 728148871Scperciva mv NEW files/${Y} 729148871Scperciva gzip -n files/${Y} 730148871Scperciva fi 731148871Scperciva rm -f diff OLD NEW ${X}-${Y} 732148871Scperciva done < patchlist 2>${QUIETREDIR} 733148871Scperciva echo "done." 734148871Scperciva 735148871Scperciva# Update ports without patches 736148871Scperciva join -t '|' -v 2 INDEX INDEX.new | 737148871Scperciva cut -f 2 -d '|' /dev/stdin patchlist | 738148871Scperciva while read Y; do 739148871Scperciva if [ ! -f "files/${Y}.gz" ]; then 740148871Scperciva echo ${Y}; 741148871Scperciva fi 742148871Scperciva done > filelist 743148871Scperciva echo -n "Fetching `wc -l < filelist | tr -d ' '` " 744148871Scperciva echo ${NDEBUG} "new ports or files... " 745148871Scperciva lam -s "f/" - -s ".gz" < filelist | 746148879Scperciva xargs ${XARGST} ${PHTTPGET} ${SERVERNAME} \ 747148871Scperciva 2>${QUIETREDIR} 748148871Scperciva 749148871Scperciva while read Y; do 750148871Scperciva if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then 751148871Scperciva mv ${Y}.gz files/${Y}.gz 752148871Scperciva else 753148871Scperciva echo "snapshot is corrupt." 754148871Scperciva return 1 755148871Scperciva fi 756148871Scperciva done < filelist 757148871Scperciva echo "done." 758148871Scperciva 759148871Scperciva# Remove files which are no longer needed 760148871Scperciva cut -f 2 -d '|' tINDEX INDEX | sort > oldfiles 761148871Scperciva cut -f 2 -d '|' tINDEX.new INDEX.new | sort | comm -13 - oldfiles | 762148871Scperciva lam -s "files/" - -s ".gz" | xargs rm -f 763148871Scperciva rm patchlist filelist oldfiles 764148871Scperciva 765148871Scperciva# We're done! 766148871Scperciva mv INDEX.new INDEX 767148871Scperciva mv tINDEX.new tINDEX 768148871Scperciva mv tag.new tag 769148871Scperciva 770148871Scperciva return 0 771148871Scperciva} 772148871Scperciva 773148871Scperciva# Do the actual work involved in "fetch" / "cron". 774148871Scpercivafetch_run() { 775148871Scperciva fetch_pick_server 776148871Scperciva 777148871Scperciva fetch_key || return 1 778148871Scperciva 779148871Scperciva if ! [ -d files -a -r tag -a -r INDEX -a -r tINDEX ]; then 780148871Scperciva fetch_snapshot || return 1 781148871Scperciva fi 782148871Scperciva fetch_update || return 1 783148871Scperciva} 784148871Scperciva 785148871Scperciva# Build a ports INDEX file 786148871Scpercivaextract_make_index() { 787148871Scperciva gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX | 788148871Scperciva cut -f 2 -d '|'`.gz" | ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2 789148871Scperciva} 790148871Scperciva 791148871Scperciva# Create INDEX, INDEX-5, INDEX-6 792148871Scpercivaextract_indices() { 793148871Scperciva echo -n "Building new INDEX files... " 794148871Scperciva extract_make_index DESCRIBE.4 INDEX || return 1 795148871Scperciva extract_make_index DESCRIBE.5 INDEX-5 || return 1 796148871Scperciva extract_make_index DESCRIBE.6 INDEX-6 || return 1 797148871Scperciva echo "done." 798148871Scperciva} 799148871Scperciva 800149824Scperciva# Create .portsnap.INDEX; if we are REFUSEing to touch certain directories, 801149824Scperciva# merge the values from any exiting .portsnap.INDEX file. 802148871Scpercivaextract_metadata() { 803149824Scperciva if [ -z "${REFUSE}" ]; then 804149984Scperciva sort ${WORKDIR}/INDEX > ${PORTSDIR}/.portsnap.INDEX 805149824Scperciva elif [ -f ${PORTSDIR}/.portsnap.INDEX ]; then 806149824Scperciva grep -E "${REFUSE}" ${PORTSDIR}/.portsnap.INDEX \ 807149824Scperciva > ${PORTSDIR}/.portsnap.INDEX.tmp 808149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort | 809149824Scperciva sort -m - ${PORTSDIR}/.portsnap.INDEX.tmp \ 810149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 811149824Scperciva rm -f ${PORTSDIR}/.portsnap.INDEX.tmp 812149824Scperciva else 813149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort \ 814149824Scperciva > ${PORTSDIR}/.portsnap.INDEX 815149824Scperciva fi 816148871Scperciva} 817148871Scperciva 818148871Scperciva# Do the actual work involved in "extract" 819148871Scpercivaextract_run() { 820154088Scperciva mkdir -p ${PORTSDIR} || return 1 821154088Scperciva 822149824Scperciva if ! 823149824Scperciva if ! [ -z "${EXTRACTPATH}" ]; then 824149824Scperciva grep "^${EXTRACTPATH}" ${WORKDIR}/INDEX 825149824Scperciva elif ! [ -z "${REFUSE}" ]; then 826149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX 827149824Scperciva else 828149824Scperciva cat ${WORKDIR}/INDEX 829149824Scperciva fi | while read LINE; do 830148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 831148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 832148871Scperciva echo ${PORTSDIR}/${FILE} 833148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 834148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 835148871Scperciva return 1 836148871Scperciva fi 837148871Scperciva case ${FILE} in 838148871Scperciva */) 839148871Scperciva rm -rf ${PORTSDIR}/${FILE} 840148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 841148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 842148871Scperciva -C ${PORTSDIR}/${FILE} 843148871Scperciva ;; 844148871Scperciva *) 845148871Scperciva rm -f ${PORTSDIR}/${FILE} 846148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 847148871Scperciva -C ${PORTSDIR} ${FILE} 848148871Scperciva ;; 849148871Scperciva esac 850149041Scperciva done; then 851149041Scperciva return 1 852149041Scperciva fi 853148871Scperciva if [ ! -z "${EXTRACTPATH}" ]; then 854148871Scperciva return 0; 855148871Scperciva fi 856148871Scperciva 857148871Scperciva extract_metadata 858148871Scperciva extract_indices 859148871Scperciva} 860148871Scperciva 861148871Scperciva# Do the actual work involved in "update" 862148871Scpercivaupdate_run() { 863148871Scperciva if ! [ -z "${INDEXONLY}" ]; then 864148871Scperciva extract_indices >/dev/null || return 1 865148871Scperciva return 0 866148871Scperciva fi 867148871Scperciva 868148981Scperciva if sort ${WORKDIR}/INDEX | 869149042Scperciva cmp -s ${PORTSDIR}/.portsnap.INDEX -; then 870148958Scperciva echo "Ports tree is already up to date." 871148958Scperciva return 0 872148958Scperciva fi 873148958Scperciva 874149824Scperciva# If we are REFUSEing to touch certain directories, don't remove files 875149824Scperciva# from those directories (even if they are out of date) 876148871Scperciva echo -n "Removing old files and directories... " 877149824Scperciva if ! [ -z "${REFUSE}" ]; then 878149824Scperciva sort ${WORKDIR}/INDEX | 879149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 880149824Scperciva grep -vE "${REFUSE}" | 881149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 882149824Scperciva else 883149824Scperciva sort ${WORKDIR}/INDEX | 884149824Scperciva comm -23 ${PORTSDIR}/.portsnap.INDEX - | cut -f 1 -d '|' | 885149824Scperciva lam -s "${PORTSDIR}/" - | xargs rm -rf 886149824Scperciva fi 887148871Scperciva echo "done." 888148871Scperciva 889148871Scperciva# Install new files 890148871Scperciva echo "Extracting new files:" 891149824Scperciva if ! 892149824Scperciva if ! [ -z "${REFUSE}" ]; then 893149824Scperciva grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort 894149824Scperciva else 895149824Scperciva sort ${WORKDIR}/INDEX 896149824Scperciva fi | 897149041Scperciva comm -13 ${PORTSDIR}/.portsnap.INDEX - | 898148871Scperciva while read LINE; do 899148871Scperciva FILE=`echo ${LINE} | cut -f 1 -d '|'` 900148871Scperciva HASH=`echo ${LINE} | cut -f 2 -d '|'` 901148871Scperciva echo ${PORTSDIR}/${FILE} 902148871Scperciva if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then 903148871Scperciva echo "files/${HASH}.gz not found -- snapshot corrupt." 904148871Scperciva return 1 905148871Scperciva fi 906148871Scperciva case ${FILE} in 907148871Scperciva */) 908148871Scperciva mkdir -p ${PORTSDIR}/${FILE} 909148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 910148871Scperciva -C ${PORTSDIR}/${FILE} 911148871Scperciva ;; 912148871Scperciva *) 913148871Scperciva tar -xzf ${WORKDIR}/files/${HASH}.gz \ 914148871Scperciva -C ${PORTSDIR} ${FILE} 915148871Scperciva ;; 916148871Scperciva esac 917149041Scperciva done; then 918149041Scperciva return 1 919149041Scperciva fi 920148871Scperciva 921148871Scperciva extract_metadata 922148871Scperciva extract_indices 923148871Scperciva} 924148871Scperciva 925148871Scperciva#### Main functions -- call parameter-handling and core functions 926148871Scperciva 927148871Scperciva# Using the command line, configuration file, and defaults, 928148871Scperciva# set all the parameters which are needed later. 929148871Scpercivaget_params() { 930148871Scperciva init_params 931148871Scperciva parse_cmdline $@ 932148871Scperciva sanity_conffile 933148871Scperciva default_conffile 934148871Scperciva parse_conffile 935148871Scperciva default_params 936148871Scperciva} 937148871Scperciva 938148871Scperciva# Fetch command. Make sure that we're being called 939148871Scperciva# interactively, then run fetch_check_params and fetch_run 940148871Scpercivacmd_fetch() { 941148871Scperciva if [ ! -t 0 ]; then 942148871Scperciva echo -n "`basename $0` fetch should not " 943148871Scperciva echo "be run non-interactively." 944148871Scperciva echo "Run `basename $0` cron instead." 945148871Scperciva exit 1 946148871Scperciva fi 947148871Scperciva fetch_check_params 948148871Scperciva fetch_run || exit 1 949148871Scperciva} 950148871Scperciva 951148871Scperciva# Cron command. Make sure the parameters are sensible; wait 952148871Scperciva# rand(3600) seconds; then fetch updates. While fetching updates, 953148871Scperciva# send output to a temporary file; only print that file if the 954148871Scperciva# fetching failed. 955148871Scpercivacmd_cron() { 956148871Scperciva fetch_check_params 957148871Scperciva sleep `jot -r 1 0 3600` 958148871Scperciva 959148871Scperciva TMPFILE=`mktemp /tmp/portsnap.XXXXXX` || exit 1 960148871Scperciva if ! fetch_run >> ${TMPFILE}; then 961148871Scperciva cat ${TMPFILE} 962148871Scperciva rm ${TMPFILE} 963148871Scperciva exit 1 964148871Scperciva fi 965148871Scperciva 966148871Scperciva rm ${TMPFILE} 967148871Scperciva} 968148871Scperciva 969148871Scperciva# Extract command. Make sure the parameters are sensible, 970148871Scperciva# then extract the ports tree (or part thereof). 971148871Scpercivacmd_extract() { 972148871Scperciva extract_check_params 973148871Scperciva extract_run || exit 1 974148871Scperciva} 975148871Scperciva 976148871Scperciva# Update command. Make sure the parameters are sensible, 977148871Scperciva# then update the ports tree. 978148871Scpercivacmd_update() { 979148871Scperciva update_check_params 980148871Scperciva update_run || exit 1 981148871Scperciva} 982148871Scperciva 983148871Scperciva#### Entry point 984148871Scperciva 985148871Scperciva# Make sure we find utilities from the base system 986148871Scpercivaexport PATH=/sbin:/bin:/usr/sbin:/usr/bin:${PATH} 987148871Scperciva 988148871Scpercivaget_params $@ 989149027Scpercivafor COMMAND in ${COMMANDS}; do 990149027Scperciva cmd_${COMMAND} 991149027Scpercivadone 992