#!/bin/bash
#
#  YUP - "Yum Update Proxy" for SLE 10 Maintenance
#  Copyright (C) 2006 SUSE Linux Products GmbH
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
#  This packages allows to configure an update-mirror
#  for Novell maintenance packages for SUSE Linux
#  Enterprise 10.
#
#  Please make sure, that the number of systems to serve with the
#  mirrored packages is in compliance with the number of
#  subscriptions you are allowed to exercise according to your
#  contract with Novell.
#
#  To configure network access rules (proxies, proxy
#  authentication, ...) please use YaST2 -> Network Services ->
#  Proxy.  The resulting configuration can be found in
#  /etc/sysconfig/proxy and /root/.curlrc (authentication data).
#
#  $Id: yup.sh 44 2006-10-12 16:25:37Z mge $
#

# Fail on errors in simple commands.
# set -e

# Keep a log of errors that cause a delayed exit
errorlog=""

# Obtain a temporary file which we will use to capture curl command output
CURLTMPFILE=$(mktemp -t yup.XXXXXXXXXX)
if test "x$CURLTMPFILE" = "x" ; then
	echo "Failed to create temp file"
	exit 1
fi

# Obtain another temporary file which we will use for loop data
LOOPTMPFILE=$(mktemp -t yup.XXXXXXXXXX)
if test "x$LOOPTMPFILE" = "x" ; then
	echo "Failed to create temp file"
	exit 1
fi

# Clean up after us
trap "rm -f $CURLTMPFILE $LOOPTMPFILE" EXIT 

function fetch_url() {
	# Wrapper function: url [localfile]
	# Fetch a URL to a local file; when the URL cannot be fetched
	# successfully, display details and terminate.

	url=$1
	localfile=$2
	if test x$localfile = "x"; then
		localfile=$(basename $url)
	fi

	echo -n "Fetching $url... "
	# Fetch the URL. As this command may fail, run it in a subshell so
	# as not to exit immediately.

	( $YUP_CURL $YUP_CURLPARAMS $url -o $localfile > $CURLTMPFILE 2>&1 )
	rc=$?
	if [ $rc -eq 0 ] ; then
		echo "done"
	else
		echo "FAILED with exit code $rc"
		echo "Failure details:"
		echo "----------------------------------------------------------------------------"
		cat $CURLTMPFILE
		echo "----------------------------------------------------------------------------"
		return $rc
		# echo "Exiting"
		# exit 1
	fi
	return 0
}

# import the update parameters
# ( YUP_CURL YUP_CURLPARAMS YUP_DEST_DIR 
#   YUP_ID YUP_PASS YUP_ID_SLED YUP_PASS_SLED 
#   YUP_ID_SLES YUP_PASS_SLES YUP_ARCH YUP_PRODUCTS )
#
. /etc/sysconfig/yup

# evaluate update parameters
#
echo "YUP_CURL       ="${YUP_CURL:="/usr/bin/curl"}
echo "YUP_CURLPARAMS ="${YUP_CURLPARAMS:="--verbose --digest --remote-time --fail"}
	# --verbose: we use a wrapper function and only display curl output in
	# case of errors; in that case, we want details.
	#
	# --fail: we want curl to exit with a non-zero exit status when a URL
	# could not be retrieved, in particular for things like invalid
	# credentials (HTTP 403)

echo "YUP_SERVER     ="${YUP_SERVER:="update.novell.com"}
echo "YUP_DEST_DIR   ="${YUP_DEST_DIR:="/tmp/SLE10-YUP"}
echo "YUP_ARCH       ="${YUP_ARCH:="i586"}
if [ "$YUP_DEBUGINFO." = "yes." ] ; then
	YUP_PRODUCTS="${YUP_PRODUCTS:=SLES10} SLE10-Debug"
else
	YUP_PRODUCTS="${YUP_PRODUCTS:=SLES10}"
fi
if [ "$YUP_SDK." = "yes." ] ; then
	YUP_PRODUCTS="$YUP_PRODUCTS SDK10"
fi
echo "YUP_PRODUCTS   =$YUP_PRODUCTS"

#
if [ "$YUP_ID." = "." ] || [ "$YUP_PASS." = "." ] ; then
	if [ "$YUP_ID_SLED." = "." ] || [ "$YUP_PASS_SLED." = "." ] ; then
		if [ "$YUP_ID_SLES." = "." ] || [ "$YUP_PASS_SLES." = "." ] ; then
			echo "UpdateMirror not configured properly - please run: "
			echo "YaST->System->Sysconfig Editor->System->YUP"
			exit 1;
		fi
	fi
fi

# import public proxy parameters; proxy-authentication params
# are in /root/.curlrc and automatically evaluated by curl.
# ( PROXY_ENABLED HTTPS_PROXY )
#
. /etc/sysconfig/proxy

# evaluate proxy parameters
#
if [ "$PROXY_ENABLED" = "yes" ]; then
	if ! [ "$HTTPS_PROXY." = "." ]; then
		YUP_CURLPARAMS="$YUP_CURLPARAMS --proxy $HTTPS_PROXY"
	fi
fi

for useARCH in $YUP_ARCH; do
	for SLE in $YUP_PRODUCTS; do
		useID=$YUP_ID
		usePASS=$YUP_PASS
		useSERVER=$YUP_SERVER
		if [ "$SLE." = "SLES10." ]; then
			UPD="SLES10-Updates/sles-10"
			if [ "$YUP_ID_SLES." != "." ] && [ "$YUP_PASS_SLES." != "." ] ; then
				useID=$YUP_ID_SLES
				usePASS=$YUP_PASS_SLES
			fi
			if [ "$YUP_SERVER_SLES." != "." ] ; then
				useSERVER=$YUP_SERVER_SLES
			fi
		elif [ "$SLE." = "SLE10-Debug." ]; then
			UPD="SLE10-Debuginfo-Updates/sles-10"
			if [ "$YUP_ID_SLES." != "." ] && [ "$YUP_PASS_SLES." != "." ] ; then
				useID=$YUP_ID_SLES
				usePASS=$YUP_PASS_SLES
			fi
			if [ "$YUP_SERVER_SLES." != "." ] ; then
				useSERVER=$YUP_SERVER_SLES
			fi
		elif [ "$SLE." = "SLED10." ]; then
			UPD="SLED10-Updates/sled-10"
			if [ "$YUP_ID_SLED." != "." ] && [ "$YUP_PASS_SLED." != "." ] ; then
				useID=$YUP_ID_SLED
				usePASS=$YUP_PASS_SLED
			fi
			if [ "$YUP_SERVER_SLED." != "." ] ; then
				useSERVER=$YUP_SERVER_SLED
			fi
		elif [ "$SLE." = "SDK10." ]; then
			UPD="SLE10-SDK-Updates/sles-10"
			if [ "$YUP_ID." = "." ] || [ "$YUP_PASS." = "." ] ; then
				if [ "$YUP_ID_SLES." = "." ] || [ "$YUP_PASS_SLES." = "." ] ; then
					useID=$YUP_ID_SLED
					usePASS=$YUP_PASS_SLED
				else
					useID=$YUP_ID_SLES
					usePASS=$YUP_PASS_SLES
				fi
			fi
			if [ "$YUP_SERVER." = "." ] ; then
				if [ "$YUP_SERVER_SLES." = "." ] ; then 
					useSERVER=$YUP_SERVER_SLED
				else
					useSERVER=$YUP_SERVER_SLES
				fi
			fi
		else
			echo "Warning: SLE $SLE unknown. Proceeding anyways ..."
			# exit 1
		fi

		bn="https://${useID}:${usePASS}@${useSERVER}/repo/\$RCE/${UPD}-${useARCH}"

		echo "Using $bn"

		mkdir -p ${YUP_DEST_DIR}/${SLE}/${useARCH}
		cd ${YUP_DEST_DIR}/${SLE}/${useARCH}

		mkdir -p repodata 2>/dev/null

		# Always download all the necessary metadata

		fetch_url "$bn/repodata/repomd.xml.asc" "repodata/repomd.xml.asc"
		fetch_url "$bn/repodata/repomd.xml.key" "repodata/repomd.xml.key"
		fetch_url "$bn/repodata/repomd.xml" "repodata/repomd.xml"
		fetch_url "$bn/repodata/filelists.xml.gz" "repodata/filelists.xml.gz"
		fetch_url "$bn/repodata/primary.xml.gz" "repodata/primary.xml.gz"
		fetch_url "$bn/repodata/patches.xml" "repodata/patches.xml"

		# Download all the rpms mentioned in primary.xml.gz for the YUM repo.
		zcat repodata/primary.xml.gz|grep location.href > $LOOPTMPFILE
		{
			while read line ; do
				uri=`echo "$line"|sed -e 's/^[^"]*"//;s/".*$//;'`
				dn=`dirname $uri`
				test -d $dn || mkdir -p $dn
				if ! test -f "$uri"; then
					if !  fetch_url "$bn/$uri" "$uri" ; then
						errorlog="$errorlog $bn/$uri"
					fi
				fi
				echo $uri
			done
		} < $LOOPTMPFILE

		# Download all the repo-md patches, cross check with SHA1 sum for changed ones.
		grep -E "(location.href|checksum.type..sha)" repodata/patches.xml > $LOOPTMPFILE
		{
			while read line ; do
				echo "$line"|grep "checksum.type..sha" >/dev/null
				res=$?
				if [ "$res" == "0" ]; then
					sha1=`echo "$line"|sed -e 's/^.*sha">//;s/<.checksum.*$//;'`
				else
					uri=`echo "$line"|sed -e 's/^[^"]*"//;s/".*$//;'`
					dn=`dirname $uri`
					test -d $dn || mkdir -p $dn
					nsum=`sha1sum "$uri"|sed -e 's/ .*//;'`
					if [ "x$nsum" != "x$sha1" ]; then
						echo "$uri is bad ($nsum / $sha1), reloading"
						rm -f "$uri"
					fi
					if !  test -f "$uri" ; then
						if ! fetch_url "$bn/$uri" "$uri" ; then
							errorlog="$errorlog $bn/$uri"
						fi
					fi
					echo $uri
				fi
			done || exit $?
		} < $LOOPTMPFILE

		# Download all the patch and delta rpms mentioned in the patches.
		grep location.href repodata/patch-*.xml > $LOOPTMPFILE
		{
			while read line ; do
				uri=`echo "$line"|sed -e 's/^[^"]*"//;s/".*$//;'`
				dn=`dirname $uri`
				test -d $dn || mkdir -p $dn
				if ! test -f "$uri" ; then
					if ! fetch_url "$bn/$uri" "$uri" ; then
						errorlog="$errorlog $bn/$uri"
					fi
				fi
				echo $uri
			done || exit $?
		} < $LOOPTMPFILE
	done || exit $?
done || exit $?

if test "x$errorlog" != "x"; then
	echo "Error exit delayed from previous errors"
	echo "Problematic URIs were: $errorlog"
	exit 1
fi

#
#	Finis Africae
#

